diff options
Diffstat (limited to 'core/java')
22 files changed, 429 insertions, 204 deletions
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java index 130754e..8947550 100644 --- a/core/java/android/animation/ObjectAnimator.java +++ b/core/java/android/animation/ObjectAnimator.java @@ -16,11 +16,14 @@ package android.animation; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.Path; import android.graphics.PointF; import android.util.Log; import android.util.Property; +import java.lang.ref.WeakReference; import java.util.ArrayList; /** @@ -41,10 +44,15 @@ import java.util.ArrayList; * */ public final class ObjectAnimator extends ValueAnimator { + private static final String LOG_TAG = "ObjectAnimator"; + private static final boolean DBG = false; - // The target object on which the property exists, set in the constructor - private Object mTarget; + /** + * A weak reference to the target object on which the property exists, set + * in the constructor. We'll cancel the animation if this goes away. + */ + private WeakReference<Object> mTarget; private String mPropertyName; @@ -78,7 +86,7 @@ public final class ObjectAnimator extends ValueAnimator { * * @param propertyName The name of the property being animated. Should not be null. */ - public void setPropertyName(String propertyName) { + public void setPropertyName(@NonNull String propertyName) { // mValues could be null if this is being constructed piecemeal. Just record the // propertyName to be used later when setValues() is called if so. if (mValues != null) { @@ -100,7 +108,7 @@ public final class ObjectAnimator extends ValueAnimator { * * @param property The property being animated. Should not be null. */ - public void setProperty(Property property) { + public void setProperty(@NonNull Property property) { // mValues could be null if this is being constructed piecemeal. Just record the // propertyName to be used later when setValues() is called if so. if (mValues != null) { @@ -134,6 +142,7 @@ public final class ObjectAnimator extends ValueAnimator { * object (if there was just one) or a comma-separated list of all of the * names (if there are more than one).</p> */ + @Nullable public String getPropertyName() { String propertyName = null; if (mPropertyName != null) { @@ -176,7 +185,7 @@ public final class ObjectAnimator extends ValueAnimator { * @param propertyName The name of the property being animated. */ private ObjectAnimator(Object target, String propertyName) { - mTarget = target; + setTarget(target); setPropertyName(propertyName); } @@ -187,7 +196,7 @@ public final class ObjectAnimator extends ValueAnimator { * @param property The property being animated. */ private <T> ObjectAnimator(T target, Property<T, ?> property) { - mTarget = target; + setTarget(target); setProperty(property); } @@ -574,8 +583,9 @@ public final class ObjectAnimator extends ValueAnimator { * @param path The <code>Path</code> to animate values along. * @return An ObjectAnimator object that is set up to animate along <code>path</code>. */ + @NonNull public static ObjectAnimator ofObject(Object target, String propertyName, - TypeConverter<PointF, ?> converter, Path path) { + @Nullable TypeConverter<PointF, ?> converter, Path path) { PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(propertyName, converter, path); return ofPropertyValuesHolder(target, pvh); } @@ -595,6 +605,7 @@ public final class ObjectAnimator extends ValueAnimator { * @param values A set of values that the animation will animate between over time. * @return An ObjectAnimator object that is set up to animate between the given values. */ + @NonNull public static <T, V> ObjectAnimator ofObject(T target, Property<T, V> property, TypeEvaluator<V> evaluator, V... values) { ObjectAnimator anim = new ObjectAnimator(target, property); @@ -622,6 +633,7 @@ public final class ObjectAnimator extends ValueAnimator { * @param values A set of values that the animation will animate between over time. * @return An ObjectAnimator object that is set up to animate between the given values. */ + @NonNull public static <T, V, P> ObjectAnimator ofObject(T target, Property<T, P> property, TypeConverter<V, P> converter, TypeEvaluator<V> evaluator, V... values) { PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(property, converter, evaluator, @@ -644,8 +656,9 @@ public final class ObjectAnimator extends ValueAnimator { * @param path The <code>Path</code> to animate values along. * @return An ObjectAnimator object that is set up to animate along <code>path</code>. */ - public static <T, V> ObjectAnimator ofObject(T target, Property<T, V> property, - TypeConverter<PointF, V> converter, Path path) { + @NonNull + public static <T, V> ObjectAnimator ofObject(T target, @NonNull Property<T, V> property, + @Nullable TypeConverter<PointF, V> converter, Path path) { PropertyValuesHolder pvh = PropertyValuesHolder.ofObject(property, converter, path); return ofPropertyValuesHolder(target, pvh); } @@ -667,10 +680,11 @@ public final class ObjectAnimator extends ValueAnimator { * over time. * @return An ObjectAnimator object that is set up to animate between the given values. */ + @NonNull public static ObjectAnimator ofPropertyValuesHolder(Object target, PropertyValuesHolder... values) { ObjectAnimator anim = new ObjectAnimator(); - anim.mTarget = target; + anim.setTarget(target); anim.setValues(values); return anim; } @@ -736,10 +750,10 @@ public final class ObjectAnimator extends ValueAnimator { mAutoCancel = cancel; } - private boolean hasSameTargetAndProperties(Animator anim) { + private boolean hasSameTargetAndProperties(@Nullable Animator anim) { if (anim instanceof ObjectAnimator) { PropertyValuesHolder[] theirValues = ((ObjectAnimator) anim).getValues(); - if (((ObjectAnimator) anim).getTarget() == mTarget && + if (((ObjectAnimator) anim).getTarget() == getTarget() && mValues.length == theirValues.length) { for (int i = 0; i < mValues.length; ++i) { PropertyValuesHolder pvhMine = mValues[i]; @@ -789,11 +803,11 @@ public final class ObjectAnimator extends ValueAnimator { } } if (DBG) { - Log.d("ObjectAnimator", "Anim target, duration: " + mTarget + ", " + getDuration()); + Log.d(LOG_TAG, "Anim target, duration: " + getTarget() + ", " + getDuration()); for (int i = 0; i < mValues.length; ++i) { PropertyValuesHolder pvh = mValues[i]; ArrayList<Keyframe> keyframes = pvh.mKeyframeSet.mKeyframes; - Log.d("ObjectAnimator", " Values[" + i + "]: " + + Log.d(LOG_TAG, " Values[" + i + "]: " + pvh.getPropertyName() + ", " + keyframes.get(0).getValue() + ", " + keyframes.get(pvh.mKeyframeSet.mNumKeyframes - 1).getValue()); } @@ -818,9 +832,12 @@ public final class ObjectAnimator extends ValueAnimator { if (!mInitialized) { // mValueType may change due to setter/getter setup; do this before calling super.init(), // which uses mValueType to set up the default type evaluator. - int numValues = mValues.length; - for (int i = 0; i < numValues; ++i) { - mValues[i].setupSetterAndGetter(mTarget); + final Object target = getTarget(); + if (target != null) { + final int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].setupSetterAndGetter(target); + } } super.initAnimation(); } @@ -836,6 +853,7 @@ public final class ObjectAnimator extends ValueAnimator { * <code>ObjectAnimator.ofInt(target, propertyName, 0, 10).setDuration(500).start()</code>. */ @Override + @NonNull public ObjectAnimator setDuration(long duration) { super.setDuration(duration); return this; @@ -847,8 +865,9 @@ public final class ObjectAnimator extends ValueAnimator { * * @return The object being animated */ + @Nullable public Object getTarget() { - return mTarget; + return mTarget == null ? null : mTarget.get(); } /** @@ -857,10 +876,10 @@ public final class ObjectAnimator extends ValueAnimator { * @param target The object being animated */ @Override - public void setTarget(Object target) { - if (mTarget != target) { - final Object oldTarget = mTarget; - mTarget = target; + public void setTarget(@Nullable Object target) { + final Object oldTarget = getTarget(); + if (oldTarget != target) { + mTarget = target == null ? null : new WeakReference<Object>(target); if (oldTarget != null && target != null && oldTarget.getClass() == target.getClass()) { return; } @@ -872,18 +891,26 @@ public final class ObjectAnimator extends ValueAnimator { @Override public void setupStartValues() { initAnimation(); - int numValues = mValues.length; - for (int i = 0; i < numValues; ++i) { - mValues[i].setupStartValue(mTarget); + + final Object target = getTarget(); + if (target != null) { + final int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].setupStartValue(target); + } } } @Override public void setupEndValues() { initAnimation(); - int numValues = mValues.length; - for (int i = 0; i < numValues; ++i) { - mValues[i].setupEndValue(mTarget); + + final Object target = getTarget(); + if (target != null) { + final int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].setupEndValue(target); + } } } @@ -901,10 +928,17 @@ public final class ObjectAnimator extends ValueAnimator { */ @Override void animateValue(float fraction) { + final Object target = getTarget(); + if (mTarget != null && target == null) { + // We lost the target reference, cancel and clean up. + cancel(); + return; + } + super.animateValue(fraction); int numValues = mValues.length; for (int i = 0; i < numValues; ++i) { - mValues[i].setAnimatedValue(mTarget); + mValues[i].setAnimatedValue(target); } } @@ -915,9 +949,10 @@ public final class ObjectAnimator extends ValueAnimator { } @Override + @NonNull public String toString() { String returnVal = "ObjectAnimator@" + Integer.toHexString(hashCode()) + ", target " + - mTarget; + getTarget(); if (mValues != null) { for (int i = 0; i < mValues.length; ++i) { returnVal += "\n " + mValues[i].toString(); diff --git a/core/java/android/annotation/PrivateApi.java b/core/java/android/annotation/SystemApi.java index 985eafe..55028eb 100644 --- a/core/java/android/annotation/PrivateApi.java +++ b/core/java/android/annotation/SystemApi.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2014 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. @@ -16,16 +16,29 @@ package android.annotation; +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PACKAGE; +import static java.lang.annotation.ElementType.TYPE; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** - * Indicates an API is exposed for use by bundled applications. + * Indicates an API is exposed for use by bundled system applications. * <p> * These APIs are not guaranteed to remain consistent release-to-release, - * and are not for use by apps linking against the SDK. + * and are not for use by apps linking against the Android SDK. + * </p><p> + * This annotation should only appear on API that is already marked <pre>@hide</pre>. + * </p> + * * @hide */ +@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE}) @Retention(RetentionPolicy.SOURCE) -public @interface PrivateApi { +public @interface SystemApi { } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 72b5cd9..a1cdf59 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -17,6 +17,8 @@ package android.app; import android.annotation.IntDef; +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; import android.content.Context; import android.content.Intent; import android.content.res.Resources; @@ -74,6 +76,15 @@ public class Notification implements Parcelable private static final String TAG = "Notification"; /** + * An activity that provides a user interface for adjusting notification preferences for its + * containing application. Optional but recommended for apps that post + * {@link android.app.Notification Notifications}. + */ + @SdkConstant(SdkConstantType.INTENT_CATEGORY) + public static final String INTENT_CATEGORY_NOTIFICATION_PREFERENCES + = "android.intent.category.NOTIFICATION_PREFERENCES"; + + /** * Use all default values (where applicable). */ public static final int DEFAULT_ALL = ~0; diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index 33c3409..261b15d 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -253,6 +253,7 @@ public class SearchManager * for more information on these schemes. */ public final static String SUGGEST_COLUMN_ICON_1 = "suggest_icon_1"; + /** * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column, * then all suggestions will be provided in a format that includes space for two small icons, @@ -269,6 +270,24 @@ public class SearchManager * for more information on these schemes. */ public final static String SUGGEST_COLUMN_ICON_2 = "suggest_icon_2"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column, + * then the image will be displayed when forming the suggestion. The suggested dimension for + * the image is 270x400 px for portrait mode and 400x225 px for landscape mode. The data in the + * column must be a resource ID of a drawable, or a URI in one of the following formats: + * + * <ul> + * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li> + * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})</li> + * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li> + * </ul> + * + * See {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String)} + * for more information on these schemes. + */ + public final static String SUGGEST_COLUMN_RESULT_CARD_IMAGE = "suggest_result_card_image"; + /** * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i> * this element exists at the given row, this is the action that will be used when @@ -279,6 +298,7 @@ public class SearchManager * it from the cursor. */ public final static String SUGGEST_COLUMN_INTENT_ACTION = "suggest_intent_action"; + /** * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i> * this element exists at the given row, this is the data that will be used when @@ -289,6 +309,7 @@ public class SearchManager * it is more efficient to specify it using XML metadata and omit it from the cursor. */ public final static String SUGGEST_COLUMN_INTENT_DATA = "suggest_intent_data"; + /** * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i> * this element exists at the given row, this is the data that will be used when @@ -297,6 +318,7 @@ public class SearchManager * an extra under the key {@link #EXTRA_DATA_KEY}. */ public final static String SUGGEST_COLUMN_INTENT_EXTRA_DATA = "suggest_intent_extra_data"; + /** * Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i> * this element exists at the given row, then "/" and this value will be appended to the data @@ -304,6 +326,7 @@ public class SearchManager * appropriate base string. */ public final static String SUGGEST_COLUMN_INTENT_DATA_ID = "suggest_intent_data_id"; + /** * Column name for suggestions cursor. <i>Required if action is * {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}, optional otherwise.</i> If this @@ -331,6 +354,89 @@ public class SearchManager "suggest_spinner_while_refreshing"; /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is media type, you + * should provide this column so search app could understand more about your content. The data + * in the column must specify the MIME type of the content. + */ + public final static String SUGGEST_COLUMN_CONTENT_TYPE = "suggest_content_type"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is media type, you + * should provide this column to specify whether your content is live media such as live video + * or live audio. The value in the column is of integer type with value of either 0 indicating + * non-live content or 1 indicating live content. + */ + public final static String SUGGEST_COLUMN_IS_LIVE = "suggest_is_live"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is video, you should + * provide this column to specify the number of vertical lines. The data in the column is of + * integer type. + */ + public final static String SUGGEST_COLUMN_VIDEO_WIDTH = "suggest_video_width"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is video, you should + * provide this column to specify the number of horizontal lines. The data in the column is of + * integer type. + */ + public final static String SUGGEST_COLUMN_VIDEO_HEIGHT = "suggest_video_height"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content contains audio, you + * should provide this column to specify the audio channel configuration. The data in the + * column is string with format like "channels.subchannels" such as "1.0" or "5.1". + */ + public final static String SUGGEST_COLUMN_AUDIO_CHANNEL_CONFIG = "suggest_audio_channel_config"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is purchasable, you + * should provide this column to specify the displayable string representation of the purchase + * price of your content including the currency and the amount. If it's free, you should + * provide localized string to specify that it's free. This column can be omitted if the content + * is not applicable to purchase. + */ + public final static String SUGGEST_COLUMN_PURCHASE_PRICE = "suggest_purchase_price"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is rentable, you + * should provide this column to specify the displayable string representation of the rental + * price of your content including the currency and the amount. If it's free, you should + * provide localized string to specify that it's free. This column can be ommitted if the + * content is not applicable to rent. + */ + public final static String SUGGEST_COLUMN_RENTAL_PRICE = "suggest_rental_price"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content has a rating, you + * should provide this column to specify the rating style of your content. The data in the + * column must be one of the constant values specified in {@link android.media.Rating} + */ + public final static String SUGGEST_COLUMN_RATING_STYLE = "suggest_rating_style"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content has a rating, you + * should provide this column to specify the rating score of your content. The data in the + * column is of float type. See {@link android.media.Rating} about valid rating scores for each + * rating style. + */ + public final static String SUGGEST_COLUMN_RATING_SCORE = "suggest_rating_score"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is video or audio and + * has a known production year, you should provide this column to specify the production year + * of your content. The data in the column is of integer type. + */ + public final static String SUGGEST_COLUMN_PRODUCTION_YEAR = "suggest_production_year"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> If your content is video or audio, you + * should provide this column to specify the duration of your content in milliseconds. The data + * in the column is of long type. + */ + public final static String SUGGEST_COLUMN_DURATION = "suggest_duration"; + + /** * Column name for suggestions cursor. <i>Optional.</i> This column is used to specify * additional flags per item. Multiple flags can be specified. * <p> diff --git a/core/java/android/app/TaskManagerImpl.java b/core/java/android/app/TaskManagerImpl.java index f42839e..fe29fb7 100644 --- a/core/java/android/app/TaskManagerImpl.java +++ b/core/java/android/app/TaskManagerImpl.java @@ -20,6 +20,7 @@ package android.app; import android.app.task.ITaskManager; import android.app.task.Task; import android.app.task.TaskManager; +import android.os.RemoteException; import java.util.List; @@ -37,26 +38,35 @@ public class TaskManagerImpl extends TaskManager { @Override public int schedule(Task task) { - // TODO Auto-generated method stub - return 0; + try { + return mBinder.schedule(task); + } catch (RemoteException e) { + return TaskManager.RESULT_FAILURE; + } } @Override public void cancel(int taskId) { - // TODO Auto-generated method stub + try { + mBinder.cancel(taskId); + } catch (RemoteException e) {} } @Override public void cancelAll() { - // TODO Auto-generated method stub + try { + mBinder.cancelAll(); + } catch (RemoteException e) {} } @Override public List<Task> getAllPendingTasks() { - // TODO Auto-generated method stub - return null; + try { + return mBinder.getAllPendingTasks(); + } catch (RemoteException e) { + return null; + } } - } diff --git a/core/java/android/app/task/Task.java b/core/java/android/app/task/Task.java index 87d57fb..0e660b3 100644 --- a/core/java/android/app/task/Task.java +++ b/core/java/android/app/task/Task.java @@ -48,6 +48,11 @@ public class Task implements Parcelable { * @hide */ public static final int DEFAULT_BACKOFF_POLICY = BackoffPolicy.EXPONENTIAL; + /** + * Maximum backoff we allow for a job, in milliseconds. + * @hide + */ + public static final long MAX_BACKOFF_DELAY_MILLIS = 24 * 60 * 60 * 1000; // 24 hours. /** * Linear: retry_time(failure_time, t) = failure_time + initial_retry_delay * t, t >= 1 @@ -185,7 +190,7 @@ public class Task implements Parcelable { private Task(Parcel in) { taskId = in.readInt(); extras = in.readPersistableBundle(); - service = ComponentName.readFromParcel(in); + service = in.readParcelable(null); requireCharging = in.readInt() == 1; requireDeviceIdle = in.readInt() == 1; networkCapabilities = in.readInt(); @@ -201,7 +206,7 @@ public class Task implements Parcelable { private Task(Task.Builder b) { taskId = b.mTaskId; - extras = new PersistableBundle(b.mExtras); + extras = b.mExtras; service = b.mTaskService; requireCharging = b.mRequiresCharging; requireDeviceIdle = b.mRequiresDeviceIdle; @@ -225,7 +230,7 @@ public class Task implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeInt(taskId); out.writePersistableBundle(extras); - ComponentName.writeToParcel(service, out); + out.writeParcelable(service, flags); out.writeInt(requireCharging ? 1 : 0); out.writeInt(requireDeviceIdle ? 1 : 0); out.writeInt(networkCapabilities); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 571bb4d..9fe9bce 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StringDef; +import android.annotation.SystemApi; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; @@ -2641,7 +2642,9 @@ public abstract class Context { * * @see #getSystemService * @see android.hardware.hdmi.HdmiControlManager + * @hide */ + @SystemApi public static final String HDMI_CONTROL_SERVICE = "hdmi_control"; /** diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index bd07470..cd0de12 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2731,6 +2731,7 @@ public class Intent implements Parcelable, Cloneable { * returned in {@link #getClipData()}. * * @see DocumentsContract + * @see #ACTION_OPEN_DOCUMENT_TREE * @see #ACTION_CREATE_DOCUMENT * @see #FLAG_GRANT_PERSISTABLE_URI_PERMISSION */ @@ -2765,28 +2766,30 @@ public class Intent implements Parcelable, Cloneable { * * @see DocumentsContract * @see #ACTION_OPEN_DOCUMENT + * @see #ACTION_OPEN_DOCUMENT_TREE * @see #FLAG_GRANT_PERSISTABLE_URI_PERMISSION */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_CREATE_DOCUMENT = "android.intent.action.CREATE_DOCUMENT"; /** - * Activity Action: Allow the user to pick a directory. When invoked, the - * system will display the various {@link DocumentsProvider} instances - * installed on the device, letting the user navigate through them. Apps can - * fully manage documents within the returned directory. + * Activity Action: Allow the user to pick a directory subtree. When + * invoked, the system will display the various {@link DocumentsProvider} + * instances installed on the device, letting the user navigate through + * them. Apps can fully manage documents within the returned directory. * <p> * To gain access to descendant (child, grandchild, etc) documents, use - * {@link DocumentsContract#buildDocumentViaUri(Uri, String)} and - * {@link DocumentsContract#buildChildDocumentsViaUri(Uri, String)} using - * the returned directory URI. + * {@link DocumentsContract#buildDocumentUriUsingTree(Uri, String)} and + * {@link DocumentsContract#buildChildDocumentsUriUsingTree(Uri, String)} + * with the returned URI. * <p> - * Output: The URI representing the selected directory. + * Output: The URI representing the selected directory tree. * * @see DocumentsContract */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_PICK_DIRECTORY = "android.intent.action.PICK_DIRECTORY"; + public static final String + ACTION_OPEN_DOCUMENT_TREE = "android.intent.action.OPEN_DOCUMENT_TREE"; // --------------------------------------------------------------------- // --------------------------------------------------------------------- @@ -2976,14 +2979,6 @@ public class Intent implements Parcelable, Cloneable { @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_CAR_MODE = "android.intent.category.CAR_MODE"; - /** - * An activity that provides a user interface for adjusting notification preferences for its - * containing application. Optional but recommended for apps that post - * {@link android.app.Notification Notifications}. - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_NOTIFICATION_PREFERENCES = "android.intent.category.NOTIFICATION_PREFERENCES"; - // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Application launch intent categories (see addCategory()). @@ -3373,8 +3368,8 @@ public class Intent implements Parcelable, Cloneable { * * @see #ACTION_GET_CONTENT * @see #ACTION_OPEN_DOCUMENT + * @see #ACTION_OPEN_DOCUMENT_TREE * @see #ACTION_CREATE_DOCUMENT - * @see #ACTION_PICK_DIRECTORY */ public static final String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY"; diff --git a/core/java/android/content/pm/ContainerEncryptionParams.java b/core/java/android/content/pm/ContainerEncryptionParams.java index dd1332b..ab3aa27 100644 --- a/core/java/android/content/pm/ContainerEncryptionParams.java +++ b/core/java/android/content/pm/ContainerEncryptionParams.java @@ -16,7 +16,7 @@ package android.content.pm; -import android.annotation.PrivateApi; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -35,7 +35,7 @@ import javax.crypto.spec.IvParameterSpec; * @deprecated encrypted containers are legacy. * @hide */ -@PrivateApi +@SystemApi @Deprecated public class ContainerEncryptionParams implements Parcelable { protected static final String TAG = "ContainerEncryptionParams"; diff --git a/core/java/android/content/pm/ManifestDigest.java b/core/java/android/content/pm/ManifestDigest.java index 943534f..1fbef7a 100644 --- a/core/java/android/content/pm/ManifestDigest.java +++ b/core/java/android/content/pm/ManifestDigest.java @@ -16,7 +16,7 @@ package android.content.pm; -import android.annotation.PrivateApi; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.util.Slog; @@ -37,7 +37,7 @@ import libcore.io.IoUtils; * * @hide */ -@PrivateApi +@SystemApi public class ManifestDigest implements Parcelable { private static final String TAG = "ManifestDigest"; diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index aadb10e..0ba7180 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -17,7 +17,7 @@ package android.content.pm; import android.annotation.IntDef; -import android.annotation.PrivateApi; +import android.annotation.SystemApi; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.PackageInstallObserver; @@ -370,7 +370,7 @@ public abstract class PackageManager { * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} on success. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_SUCCEEDED = 1; /** @@ -379,7 +379,7 @@ public abstract class PackageManager { * already installed. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_ALREADY_EXISTS = -1; /** @@ -388,7 +388,7 @@ public abstract class PackageManager { * file is invalid. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_INVALID_APK = -2; /** @@ -397,7 +397,7 @@ public abstract class PackageManager { * is invalid. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_INVALID_URI = -3; /** @@ -406,7 +406,7 @@ public abstract class PackageManager { * service found that the device didn't have enough storage space to install the app. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_INSUFFICIENT_STORAGE = -4; /** @@ -415,7 +415,7 @@ public abstract class PackageManager { * package is already installed with the same name. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_DUPLICATE_PACKAGE = -5; /** @@ -424,7 +424,7 @@ public abstract class PackageManager { * the requested shared user does not exist. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_NO_SHARED_USER = -6; /** @@ -434,7 +434,7 @@ public abstract class PackageManager { * than the new package (and the old package's data was not removed). * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_UPDATE_INCOMPATIBLE = -7; /** @@ -444,7 +444,7 @@ public abstract class PackageManager { * device and does not have matching signature. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8; /** @@ -453,7 +453,7 @@ public abstract class PackageManager { * the new package uses a shared library that is not available. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_MISSING_SHARED_LIBRARY = -9; /** @@ -462,7 +462,7 @@ public abstract class PackageManager { * the new package uses a shared library that is not available. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10; /** @@ -472,7 +472,7 @@ public abstract class PackageManager { * either because there was not enough storage or the validation failed. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_DEXOPT = -11; /** @@ -482,7 +482,7 @@ public abstract class PackageManager { * that required by the package. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_OLDER_SDK = -12; /** @@ -492,7 +492,7 @@ public abstract class PackageManager { * same authority as a provider already installed in the system. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13; /** @@ -502,7 +502,7 @@ public abstract class PackageManager { * that required by the package. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_NEWER_SDK = -14; /** @@ -513,7 +513,7 @@ public abstract class PackageManager { * flag. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_TEST_ONLY = -15; /** @@ -523,7 +523,7 @@ public abstract class PackageManager { * compatible with the the device's CPU_ABI. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_CPU_ABI_INCOMPATIBLE = -16; /** @@ -532,7 +532,7 @@ public abstract class PackageManager { * the new package uses a feature that is not available. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_MISSING_FEATURE = -17; // ------ Errors related to sdcard @@ -542,7 +542,7 @@ public abstract class PackageManager { * a secure container mount point couldn't be accessed on external media. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_CONTAINER_ERROR = -18; /** @@ -552,7 +552,7 @@ public abstract class PackageManager { * location. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_INVALID_INSTALL_LOCATION = -19; /** @@ -562,7 +562,7 @@ public abstract class PackageManager { * location because the media is not available. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_MEDIA_UNAVAILABLE = -20; /** @@ -571,7 +571,7 @@ public abstract class PackageManager { * the new package couldn't be installed because the verification timed out. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_VERIFICATION_TIMEOUT = -21; /** @@ -580,7 +580,7 @@ public abstract class PackageManager { * the new package couldn't be installed because the verification did not succeed. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_VERIFICATION_FAILURE = -22; /** @@ -589,7 +589,7 @@ public abstract class PackageManager { * the package changed from what the calling program expected. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_PACKAGE_CHANGED = -23; /** @@ -615,7 +615,7 @@ public abstract class PackageManager { * '.apk' extension. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_PARSE_FAILED_NOT_APK = -100; /** @@ -624,7 +624,7 @@ public abstract class PackageManager { * if the parser was unable to retrieve the AndroidManifest.xml file. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_PARSE_FAILED_BAD_MANIFEST = -101; /** @@ -633,7 +633,7 @@ public abstract class PackageManager { * if the parser encountered an unexpected exception. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102; /** @@ -642,7 +642,7 @@ public abstract class PackageManager { * if the parser did not find any certificates in the .apk. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103; /** @@ -651,7 +651,7 @@ public abstract class PackageManager { * if the parser found inconsistent certificates on the files in the .apk. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES = -104; /** @@ -661,7 +661,7 @@ public abstract class PackageManager { * files in the .apk. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING = -105; /** @@ -670,7 +670,7 @@ public abstract class PackageManager { * if the parser encountered a bad or missing package name in the manifest. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME = -106; /** @@ -679,7 +679,7 @@ public abstract class PackageManager { * if the parser encountered a bad shared user id name in the manifest. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID = -107; /** @@ -688,7 +688,7 @@ public abstract class PackageManager { * if the parser encountered some structural problem in the manifest. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_PARSE_FAILED_MANIFEST_MALFORMED = -108; /** @@ -698,7 +698,7 @@ public abstract class PackageManager { * in the manifest. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_PARSE_FAILED_MANIFEST_EMPTY = -109; /** @@ -707,7 +707,7 @@ public abstract class PackageManager { * if the system failed to install the package because of system issues. * @hide */ - @PrivateApi + @SystemApi public static final int INSTALL_FAILED_INTERNAL_ERROR = -110; /** @@ -2907,7 +2907,7 @@ public abstract class PackageManager { * instead. This method will continue to be supported but the older observer interface * will not get additional failure details. */ - // @PrivateApi + // @SystemApi public abstract void installPackage( Uri packageURI, IPackageInstallObserver observer, int flags, String installerPackageName); @@ -2942,7 +2942,7 @@ public abstract class PackageManager { * continue to be supported but the older observer interface will not get additional failure * details. */ - // @PrivateApi + // @SystemApi public abstract void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer, int flags, String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest, @@ -3071,7 +3071,7 @@ public abstract class PackageManager { * on the system for other users, also install it for the calling user. * @hide */ - // @PrivateApi + // @SystemApi public abstract int installExistingPackage(String packageName) throws NameNotFoundException; @@ -3161,7 +3161,7 @@ public abstract class PackageManager { * * @hide */ - // @PrivateApi + // @SystemApi public abstract void deletePackage( String packageName, IPackageDeleteObserver observer, int flags); @@ -3230,7 +3230,7 @@ public abstract class PackageManager { * * @hide */ - // @PrivateApi + // @SystemApi public abstract void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer); /** diff --git a/core/java/android/hardware/hdmi/HdmiCec.java b/core/java/android/hardware/hdmi/HdmiCec.java index 723eda1..8ad9463 100644 --- a/core/java/android/hardware/hdmi/HdmiCec.java +++ b/core/java/android/hardware/hdmi/HdmiCec.java @@ -16,9 +16,14 @@ package android.hardware.hdmi; +import android.annotation.SystemApi; + /** * Defines constants and utility methods related to HDMI-CEC protocol. + * + * @hide */ +@SystemApi public final class HdmiCec { /** TV device type. */ diff --git a/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java index 9698445..fbfcca0 100644 --- a/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java +++ b/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java @@ -16,6 +16,7 @@ package android.hardware.hdmi; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -23,7 +24,10 @@ import android.os.Parcelable; * A class to encapsulate device information for HDMI-CEC. This container * include basic information such as logical address, physical address and * device type, and additional information like vendor id and osd name. + * + * @hide */ +@SystemApi public final class HdmiCecDeviceInfo implements Parcelable { // Logical address, phsical address, device type, vendor id and display name // are immutable value. diff --git a/core/java/android/hardware/hdmi/HdmiCecMessage.java b/core/java/android/hardware/hdmi/HdmiCecMessage.java index 62fa279..ac16ad8 100644 --- a/core/java/android/hardware/hdmi/HdmiCecMessage.java +++ b/core/java/android/hardware/hdmi/HdmiCecMessage.java @@ -16,6 +16,7 @@ package android.hardware.hdmi; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -27,7 +28,10 @@ import java.util.Arrays; * A class to encapsulate HDMI-CEC message used for the devices connected via * HDMI cable to communicate with one another. A message is defined by its * source and destination address, command (or opcode), and optional parameters. + * + * @hide */ +@SystemApi public final class HdmiCecMessage implements Parcelable { public static final byte[] EMPTY_PARAM = EmptyArray.BYTE; diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java index 5b6e862..f15fa00 100644 --- a/core/java/android/hardware/hdmi/HdmiControlManager.java +++ b/core/java/android/hardware/hdmi/HdmiControlManager.java @@ -17,6 +17,7 @@ package android.hardware.hdmi; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.os.RemoteException; /** @@ -28,7 +29,10 @@ import android.os.RemoteException; * {@link HdmiTvClient} object if the system is configured to host one. Android system * can host more than one logical CEC devices. If multiple types are configured they * all work as if they were independent logical devices running in the system. + * + * @hide */ +@SystemApi public final class HdmiControlManager { @Nullable private final IHdmiControlService mService; diff --git a/core/java/android/hardware/hdmi/HdmiHotplugEvent.java b/core/java/android/hardware/hdmi/HdmiHotplugEvent.java index 1462f83..7be4bc5 100644 --- a/core/java/android/hardware/hdmi/HdmiHotplugEvent.java +++ b/core/java/android/hardware/hdmi/HdmiHotplugEvent.java @@ -16,12 +16,16 @@ package android.hardware.hdmi; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; /** * A class that describes the HDMI port hotplug event. + * + * @hide */ +@SystemApi public final class HdmiHotplugEvent implements Parcelable { private final int mPort; diff --git a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java index f0bd237..2e49a38 100644 --- a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java +++ b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java @@ -16,6 +16,7 @@ package android.hardware.hdmi; +import android.annotation.SystemApi; import android.os.RemoteException; import android.util.Log; @@ -25,7 +26,10 @@ import android.util.Log; * in the Android system which acts as a playback device such as set-top box. * It provides with methods that control, get information from TV/Display device * connected through HDMI bus. + * + * @hide */ +@SystemApi public final class HdmiPlaybackClient { private static final String TAG = "HdmiPlaybackClient"; diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java index 73c7247..6dc4a4f 100644 --- a/core/java/android/hardware/hdmi/HdmiTvClient.java +++ b/core/java/android/hardware/hdmi/HdmiTvClient.java @@ -15,11 +15,16 @@ */ package android.hardware.hdmi; +import android.annotation.SystemApi; + /** * HdmiTvClient represents HDMI-CEC logical device of type TV in the Android system * which acts as TV/Display. It provides with methods that manage, interact with other * devices on the CEC bus. + * + * @hide */ +@SystemApi public final class HdmiTvClient { private static final String TAG = "HdmiTvClient"; diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java index 6b8e2de..327fe4a 100644 --- a/core/java/android/provider/DocumentsContract.java +++ b/core/java/android/provider/DocumentsContract.java @@ -60,7 +60,8 @@ import java.util.List; * <p> * All client apps must hold a valid URI permission grant to access documents, * typically issued when a user makes a selection through - * {@link Intent#ACTION_OPEN_DOCUMENT} or {@link Intent#ACTION_CREATE_DOCUMENT}. + * {@link Intent#ACTION_OPEN_DOCUMENT}, {@link Intent#ACTION_CREATE_DOCUMENT}, + * or {@link Intent#ACTION_OPEN_DOCUMENT_TREE}. * * @see DocumentsProvider */ @@ -73,8 +74,8 @@ public final class DocumentsContract { // content://com.example/root/sdcard/search/?query=pony // content://com.example/document/12/ // content://com.example/document/12/children/ - // content://com.example/via/12/document/24/ - // content://com.example/via/12/document/24/children/ + // content://com.example/tree/12/document/24/ + // content://com.example/tree/12/document/24/children/ private DocumentsContract() { } @@ -441,12 +442,13 @@ public final class DocumentsContract { public static final int FLAG_SUPPORTS_SEARCH = 1 << 3; /** - * Flag indicating that this root supports directory selection. + * Flag indicating that this root supports testing parent child + * relationships. * * @see #COLUMN_FLAGS * @see DocumentsProvider#isChildDocument(String, String) */ - public static final int FLAG_SUPPORTS_DIR_SELECTION = 1 << 4; + public static final int FLAG_SUPPORTS_IS_CHILD = 1 << 4; /** * Flag indicating that this root is currently empty. This may be used @@ -518,7 +520,7 @@ public final class DocumentsContract { private static final String PATH_DOCUMENT = "document"; private static final String PATH_CHILDREN = "children"; private static final String PATH_SEARCH = "search"; - private static final String PATH_VIA = "via"; + private static final String PATH_TREE = "tree"; private static final String PARAM_QUERY = "query"; private static final String PARAM_MANAGE = "manage"; @@ -564,17 +566,17 @@ public final class DocumentsContract { * Build URI representing access to descendant documents of the given * {@link Document#COLUMN_DOCUMENT_ID}. * - * @see #getViaDocumentId(Uri) + * @see #getTreeDocumentId(Uri) */ - public static Uri buildViaUri(String authority, String documentId) { + public static Uri buildTreeDocumentUri(String authority, String documentId) { return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority) - .appendPath(PATH_VIA).appendPath(documentId).build(); + .appendPath(PATH_TREE).appendPath(documentId).build(); } /** - * Build URI representing the given {@link Document#COLUMN_DOCUMENT_ID} in a - * document provider. When queried, a provider will return a single row with - * columns defined by {@link Document}. + * Build URI representing the target {@link Document#COLUMN_DOCUMENT_ID} in + * a document provider. When queried, a provider will return a single row + * with columns defined by {@link Document}. * * @see DocumentsProvider#queryDocument(String, String[]) * @see #getDocumentId(Uri) @@ -585,42 +587,46 @@ public final class DocumentsContract { } /** - * Build URI representing the given {@link Document#COLUMN_DOCUMENT_ID} in a - * document provider. Instead of directly accessing the target document, - * gain access via another document. The target document must be a - * descendant (child, grandchild, etc) of the via document. + * Build URI representing the target {@link Document#COLUMN_DOCUMENT_ID} in + * a document provider. When queried, a provider will return a single row + * with columns defined by {@link Document}. + * <p> + * However, instead of directly accessing the target document, the returned + * URI will leverage access granted through a subtree URI, typically + * returned by {@link Intent#ACTION_OPEN_DOCUMENT_TREE}. The target document + * must be a descendant (child, grandchild, etc) of the subtree. * <p> * This is typically used to access documents under a user-selected - * directory, since it doesn't require the user to separately confirm each - * new document access. + * directory tree, since it doesn't require the user to separately confirm + * each new document access. * - * @param viaUri a related document (directory) that the caller is - * leveraging to gain access to the target document. The target - * document must be a descendant of this directory. + * @param treeUri the subtree to leverage to gain access to the target + * document. The target directory must be a descendant of this + * subtree. * @param documentId the target document, which the caller may not have * direct access to. - * @see Intent#ACTION_PICK_DIRECTORY + * @see Intent#ACTION_OPEN_DOCUMENT_TREE * @see DocumentsProvider#isChildDocument(String, String) * @see #buildDocumentUri(String, String) */ - public static Uri buildDocumentViaUri(Uri viaUri, String documentId) { + public static Uri buildDocumentUriUsingTree(Uri treeUri, String documentId) { return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) - .authority(viaUri.getAuthority()).appendPath(PATH_VIA) - .appendPath(getViaDocumentId(viaUri)).appendPath(PATH_DOCUMENT) + .authority(treeUri.getAuthority()).appendPath(PATH_TREE) + .appendPath(getTreeDocumentId(treeUri)).appendPath(PATH_DOCUMENT) .appendPath(documentId).build(); } /** {@hide} */ - public static Uri buildDocumentMaybeViaUri(Uri baseUri, String documentId) { - if (isViaUri(baseUri)) { - return buildDocumentViaUri(baseUri, documentId); + public static Uri buildDocumentUriMaybeUsingTree(Uri baseUri, String documentId) { + if (isTreeUri(baseUri)) { + return buildDocumentUriUsingTree(baseUri, documentId); } else { return buildDocumentUri(baseUri.getAuthority(), documentId); } } /** - * Build URI representing the children of the given directory in a document + * Build URI representing the children of the target directory in a document * provider. When queried, a provider will return zero or more rows with * columns defined by {@link Document}. * @@ -637,28 +643,33 @@ public final class DocumentsContract { } /** - * Build URI representing the children of the given directory in a document - * provider. Instead of directly accessing the target document, gain access - * via another document. The target document must be a descendant (child, - * grandchild, etc) of the via document. + * Build URI representing the children of the target directory in a document + * provider. When queried, a provider will return zero or more rows with + * columns defined by {@link Document}. + * <p> + * However, instead of directly accessing the target directory, the returned + * URI will leverage access granted through a subtree URI, typically + * returned by {@link Intent#ACTION_OPEN_DOCUMENT_TREE}. The target + * directory must be a descendant (child, grandchild, etc) of the subtree. * <p> * This is typically used to access documents under a user-selected - * directory, since it doesn't require the user to separately confirm each - * new document access. + * directory tree, since it doesn't require the user to separately confirm + * each new document access. * - * @param viaUri a related document (directory) that the caller is - * leveraging to gain access to the target document. The target - * document must be a descendant of this directory. - * @param parentDocumentId the target document, which the caller may not - * have direct access to. - * @see Intent#ACTION_PICK_DIRECTORY + * @param treeUri the subtree to leverage to gain access to the target + * document. The target directory must be a descendant of this + * subtree. + * @param parentDocumentId the document to return children for, which the + * caller may not have direct access to, and which must be a + * directory with MIME type of {@link Document#MIME_TYPE_DIR}. + * @see Intent#ACTION_OPEN_DOCUMENT_TREE * @see DocumentsProvider#isChildDocument(String, String) * @see #buildChildDocumentsUri(String, String) */ - public static Uri buildChildDocumentsViaUri(Uri viaUri, String parentDocumentId) { + public static Uri buildChildDocumentsUriUsingTree(Uri treeUri, String parentDocumentId) { return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) - .authority(viaUri.getAuthority()).appendPath(PATH_VIA) - .appendPath(getViaDocumentId(viaUri)).appendPath(PATH_DOCUMENT) + .authority(treeUri.getAuthority()).appendPath(PATH_TREE) + .appendPath(getTreeDocumentId(treeUri)).appendPath(PATH_DOCUMENT) .appendPath(parentDocumentId).appendPath(PATH_CHILDREN).build(); } @@ -683,21 +694,24 @@ public final class DocumentsContract { * {@link DocumentsProvider}. * * @see #buildDocumentUri(String, String) - * @see #buildDocumentViaUri(Uri, String) + * @see #buildDocumentUriUsingTree(Uri, String) */ public static boolean isDocumentUri(Context context, Uri uri) { final List<String> paths = uri.getPathSegments(); - if (paths.size() >= 2 - && (PATH_DOCUMENT.equals(paths.get(0)) || PATH_VIA.equals(paths.get(0)))) { + if (paths.size() == 2 && PATH_DOCUMENT.equals(paths.get(0))) { + return isDocumentsProvider(context, uri.getAuthority()); + } + if (paths.size() == 4 && PATH_TREE.equals(paths.get(0)) + && PATH_DOCUMENT.equals(paths.get(2))) { return isDocumentsProvider(context, uri.getAuthority()); } return false; } /** {@hide} */ - public static boolean isViaUri(Uri uri) { + public static boolean isTreeUri(Uri uri) { final List<String> paths = uri.getPathSegments(); - return (paths.size() >= 2 && PATH_VIA.equals(paths.get(0))); + return (paths.size() >= 2 && PATH_TREE.equals(paths.get(0))); } private static boolean isDocumentsProvider(Context context, String authority) { @@ -733,7 +747,7 @@ public final class DocumentsContract { if (paths.size() >= 2 && PATH_DOCUMENT.equals(paths.get(0))) { return paths.get(1); } - if (paths.size() >= 4 && PATH_VIA.equals(paths.get(0)) + if (paths.size() >= 4 && PATH_TREE.equals(paths.get(0)) && PATH_DOCUMENT.equals(paths.get(2))) { return paths.get(3); } @@ -742,12 +756,10 @@ public final class DocumentsContract { /** * Extract the via {@link Document#COLUMN_DOCUMENT_ID} from the given URI. - * - * @see #isViaUri(Uri) */ - public static String getViaDocumentId(Uri documentUri) { + public static String getTreeDocumentId(Uri documentUri) { final List<String> paths = documentUri.getPathSegments(); - if (paths.size() >= 2 && PATH_VIA.equals(paths.get(0))) { + if (paths.size() >= 2 && PATH_TREE.equals(paths.get(0))) { return paths.get(1); } throw new IllegalArgumentException("Invalid URI: " + documentUri); diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java index 066b4aa..021fff4 100644 --- a/core/java/android/provider/DocumentsProvider.java +++ b/core/java/android/provider/DocumentsProvider.java @@ -20,10 +20,14 @@ import static android.provider.DocumentsContract.EXTRA_THUMBNAIL_SIZE; import static android.provider.DocumentsContract.METHOD_CREATE_DOCUMENT; import static android.provider.DocumentsContract.METHOD_DELETE_DOCUMENT; import static android.provider.DocumentsContract.METHOD_RENAME_DOCUMENT; +import static android.provider.DocumentsContract.buildDocumentUri; +import static android.provider.DocumentsContract.buildDocumentUriMaybeUsingTree; +import static android.provider.DocumentsContract.buildTreeDocumentUri; import static android.provider.DocumentsContract.getDocumentId; import static android.provider.DocumentsContract.getRootId; import static android.provider.DocumentsContract.getSearchDocumentsQuery; -import static android.provider.DocumentsContract.isViaUri; +import static android.provider.DocumentsContract.getTreeDocumentId; +import static android.provider.DocumentsContract.isTreeUri; import android.content.ContentProvider; import android.content.ContentResolver; @@ -117,6 +121,7 @@ import java.util.Objects; * </p> * * @see Intent#ACTION_OPEN_DOCUMENT + * @see Intent#ACTION_OPEN_DOCUMENT_TREE * @see Intent#ACTION_CREATE_DOCUMENT */ public abstract class DocumentsProvider extends ContentProvider { @@ -128,8 +133,8 @@ public abstract class DocumentsProvider extends ContentProvider { private static final int MATCH_SEARCH = 4; private static final int MATCH_DOCUMENT = 5; private static final int MATCH_CHILDREN = 6; - private static final int MATCH_DOCUMENT_VIA = 7; - private static final int MATCH_CHILDREN_VIA = 8; + private static final int MATCH_DOCUMENT_TREE = 7; + private static final int MATCH_CHILDREN_TREE = 8; private String mAuthority; @@ -149,8 +154,8 @@ public abstract class DocumentsProvider extends ContentProvider { mMatcher.addURI(mAuthority, "root/*/search", MATCH_SEARCH); mMatcher.addURI(mAuthority, "document/*", MATCH_DOCUMENT); mMatcher.addURI(mAuthority, "document/*/children", MATCH_CHILDREN); - mMatcher.addURI(mAuthority, "via/*/document/*", MATCH_DOCUMENT_VIA); - mMatcher.addURI(mAuthority, "via/*/document/*/children", MATCH_CHILDREN_VIA); + mMatcher.addURI(mAuthority, "tree/*/document/*", MATCH_DOCUMENT_TREE); + mMatcher.addURI(mAuthority, "tree/*/document/*/children", MATCH_CHILDREN_TREE); // Sanity check our setup if (!info.exported) { @@ -169,23 +174,24 @@ public abstract class DocumentsProvider extends ContentProvider { /** * Test if a document is descendant (child, grandchild, etc) from the given - * parent. Providers must override this to support directory selection. You - * should avoid making network requests to keep this request fast. + * parent. For example, providers must implement this to support + * {@link Intent#ACTION_OPEN_DOCUMENT_TREE}. You should avoid making network + * requests to keep this request fast. * * @param parentDocumentId parent to verify against. * @param documentId child to verify. * @return if given document is a descendant of the given parent. - * @see DocumentsContract.Root#FLAG_SUPPORTS_DIR_SELECTION + * @see DocumentsContract.Root#FLAG_SUPPORTS_IS_CHILD */ public boolean isChildDocument(String parentDocumentId, String documentId) { return false; } /** {@hide} */ - private void enforceVia(Uri documentUri) { - if (DocumentsContract.isViaUri(documentUri)) { - final String parent = DocumentsContract.getViaDocumentId(documentUri); - final String child = DocumentsContract.getDocumentId(documentUri); + private void enforceTree(Uri documentUri) { + if (isTreeUri(documentUri)) { + final String parent = getTreeDocumentId(documentUri); + final String child = getDocumentId(documentUri); if (Objects.equals(parent, child)) { return; } @@ -479,12 +485,12 @@ public abstract class DocumentsProvider extends ContentProvider { return querySearchDocuments( getRootId(uri), getSearchDocumentsQuery(uri), projection); case MATCH_DOCUMENT: - case MATCH_DOCUMENT_VIA: - enforceVia(uri); + case MATCH_DOCUMENT_TREE: + enforceTree(uri); return queryDocument(getDocumentId(uri), projection); case MATCH_CHILDREN: - case MATCH_CHILDREN_VIA: - enforceVia(uri); + case MATCH_CHILDREN_TREE: + enforceTree(uri); if (DocumentsContract.isManageMode(uri)) { return queryChildDocumentsForManage( getDocumentId(uri), projection, sortOrder); @@ -512,8 +518,8 @@ public abstract class DocumentsProvider extends ContentProvider { case MATCH_ROOT: return DocumentsContract.Root.MIME_TYPE_ITEM; case MATCH_DOCUMENT: - case MATCH_DOCUMENT_VIA: - enforceVia(uri); + case MATCH_DOCUMENT_TREE: + enforceTree(uri); return getDocumentType(getDocumentId(uri)); default: return null; @@ -530,21 +536,20 @@ public abstract class DocumentsProvider extends ContentProvider { * call the superclass. If the superclass returns {@code null}, the subclass * may implement custom behavior. * <p> - * This is typically used to resolve a "via" URI into a concrete document + * This is typically used to resolve a subtree URI into a concrete document * reference, issuing a narrower single-document URI permission grant along * the way. * - * @see DocumentsContract#buildDocumentViaUri(Uri, String) + * @see DocumentsContract#buildDocumentUriUsingTree(Uri, String) */ @Override public Uri canonicalize(Uri uri) { final Context context = getContext(); switch (mMatcher.match(uri)) { - case MATCH_DOCUMENT_VIA: - enforceVia(uri); + case MATCH_DOCUMENT_TREE: + enforceTree(uri); - final Uri narrowUri = DocumentsContract.buildDocumentUri(uri.getAuthority(), - DocumentsContract.getDocumentId(uri)); + final Uri narrowUri = buildDocumentUri(uri.getAuthority(), getDocumentId(uri)); // Caller may only have prefix grant, so extend them a grant to // the narrow URI. @@ -628,7 +633,7 @@ public abstract class DocumentsProvider extends ContentProvider { throw new SecurityException( "Requested authority " + authority + " doesn't match provider " + mAuthority); } - enforceVia(documentUri); + enforceTree(documentUri); final Bundle out = new Bundle(); try { @@ -641,8 +646,8 @@ public abstract class DocumentsProvider extends ContentProvider { // No need to issue new grants here, since caller either has // manage permission or a prefix grant. We might generate a - // "via" style URI if that's how they called us. - final Uri newDocumentUri = DocumentsContract.buildDocumentMaybeViaUri(documentUri, + // tree style URI if that's how they called us. + final Uri newDocumentUri = buildDocumentUriMaybeUsingTree(documentUri, newDocumentId); out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri); @@ -653,12 +658,12 @@ public abstract class DocumentsProvider extends ContentProvider { final String newDocumentId = renameDocument(documentId, displayName); if (newDocumentId != null) { - final Uri newDocumentUri = DocumentsContract.buildDocumentMaybeViaUri( - documentUri, newDocumentId); + final Uri newDocumentUri = buildDocumentUriMaybeUsingTree(documentUri, + newDocumentId); // If caller came in with a narrow grant, issue them a // narrow grant for the newly renamed document. - if (!isViaUri(newDocumentUri)) { + if (!isTreeUri(newDocumentUri)) { final int modeFlags = getCallingOrSelfUriPermissionModeFlags(context, documentUri); context.grantUriPermission(getCallingPackage(), newDocumentUri, modeFlags); @@ -694,8 +699,8 @@ public abstract class DocumentsProvider extends ContentProvider { */ public final void revokeDocumentPermission(String documentId) { final Context context = getContext(); - context.revokeUriPermission(DocumentsContract.buildDocumentUri(mAuthority, documentId), ~0); - context.revokeUriPermission(DocumentsContract.buildViaUri(mAuthority, documentId), ~0); + context.revokeUriPermission(buildDocumentUri(mAuthority, documentId), ~0); + context.revokeUriPermission(buildTreeDocumentUri(mAuthority, documentId), ~0); } /** @@ -705,7 +710,7 @@ public abstract class DocumentsProvider extends ContentProvider { */ @Override public final ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { - enforceVia(uri); + enforceTree(uri); return openDocument(getDocumentId(uri), mode, null); } @@ -717,7 +722,7 @@ public abstract class DocumentsProvider extends ContentProvider { @Override public final ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal) throws FileNotFoundException { - enforceVia(uri); + enforceTree(uri); return openDocument(getDocumentId(uri), mode, signal); } @@ -730,7 +735,7 @@ public abstract class DocumentsProvider extends ContentProvider { @SuppressWarnings("resource") public final AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { - enforceVia(uri); + enforceTree(uri); final ParcelFileDescriptor fd = openDocument(getDocumentId(uri), mode, null); return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null; } @@ -744,7 +749,7 @@ public abstract class DocumentsProvider extends ContentProvider { @SuppressWarnings("resource") public final AssetFileDescriptor openAssetFile(Uri uri, String mode, CancellationSignal signal) throws FileNotFoundException { - enforceVia(uri); + enforceTree(uri); final ParcelFileDescriptor fd = openDocument(getDocumentId(uri), mode, signal); return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null; } @@ -757,7 +762,7 @@ public abstract class DocumentsProvider extends ContentProvider { @Override public final AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts) throws FileNotFoundException { - enforceVia(uri); + enforceTree(uri); if (opts != null && opts.containsKey(EXTRA_THUMBNAIL_SIZE)) { final Point sizeHint = opts.getParcelable(EXTRA_THUMBNAIL_SIZE); return openDocumentThumbnail(getDocumentId(uri), sizeHint, null); @@ -775,7 +780,7 @@ public abstract class DocumentsProvider extends ContentProvider { public final AssetFileDescriptor openTypedAssetFile( Uri uri, String mimeTypeFilter, Bundle opts, CancellationSignal signal) throws FileNotFoundException { - enforceVia(uri); + enforceTree(uri); if (opts != null && opts.containsKey(EXTRA_THUMBNAIL_SIZE)) { final Point sizeHint = opts.getParcelable(EXTRA_THUMBNAIL_SIZE); return openDocumentThumbnail(getDocumentId(uri), sizeHint, signal); diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index 557f5a6..fd475cd 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -16,7 +16,7 @@ package android.service.notification; -import android.annotation.PrivateApi; +import android.annotation.SystemApi; import android.annotation.SdkConstant; import android.app.INotificationManager; import android.app.Service; @@ -279,7 +279,7 @@ public abstract class NotificationListenerService extends Service { * @param currentUser the user to use as the stream filter * @hide */ - @PrivateApi + @SystemApi public void registerAsSystemService(ComponentName componentName, int currentUser) throws RemoteException { if (mWrapper == null) { @@ -297,7 +297,7 @@ public abstract class NotificationListenerService extends Service { * with (@link registerAsService). * @hide */ - @PrivateApi + @SystemApi public void unregisterAsSystemService() throws RemoteException { if (mWrapper != null) { INotificationManager noMan = getNotificationInterface(); diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java index b3fb560..ed835e4 100644 --- a/core/java/android/service/trust/TrustAgentService.java +++ b/core/java/android/service/trust/TrustAgentService.java @@ -17,7 +17,7 @@ package android.service.trust; import android.Manifest; -import android.annotation.PrivateApi; +import android.annotation.SystemApi; import android.annotation.SdkConstant; import android.app.Service; import android.content.ComponentName; @@ -60,7 +60,7 @@ import android.util.Slog; * * @hide */ -@PrivateApi +@SystemApi public class TrustAgentService extends Service { private final String TAG = TrustAgentService.class.getSimpleName() + "[" + getClass().getSimpleName() + "]"; |
