Merge commit '745766e11e8bb7e8642be33be6bdf501af245074' into HEAD
* commit '745766e11e8bb7e8642be33be6bdf501af245074':
Forward package removed broadcast to KeyChainService
diff --git a/api/current.txt b/api/current.txt
index 06927c3..5018ecf 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4297,6 +4297,14 @@
field public java.lang.String serviceDetails;
}
+ public final class AuthenticationRequiredException extends java.lang.SecurityException implements android.os.Parcelable {
+ ctor public AuthenticationRequiredException(java.lang.Throwable, android.app.PendingIntent);
+ method public int describeContents();
+ method public android.app.PendingIntent getUserAction();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.AuthenticationRequiredException> CREATOR;
+ }
+
public final class AutomaticZenRule implements android.os.Parcelable {
ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean);
ctor public AutomaticZenRule(android.os.Parcel);
@@ -5708,17 +5716,6 @@
field public static final int STYLE_SPINNER = 0; // 0x0
}
- public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
- ctor public RecoverableSecurityException(java.lang.Throwable, java.lang.CharSequence, android.app.RemoteAction);
- method public int describeContents();
- method public android.app.RemoteAction getUserAction();
- method public java.lang.CharSequence getUserMessage();
- method public void showAsDialog(android.app.Activity);
- method public void showAsNotification(android.content.Context, java.lang.String);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.app.RecoverableSecurityException> CREATOR;
- }
-
public final class RemoteAction implements android.os.Parcelable {
ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
method public android.app.RemoteAction clone();
@@ -24621,6 +24618,7 @@
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+ field public static final java.lang.String COLUMN_LOCKED = "locked";
field public static final java.lang.String COLUMN_NETWORK_AFFILIATION = "network_affiliation";
field public static final java.lang.String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id";
field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
@@ -26280,16 +26278,6 @@
package android.net.wifi {
- public final class IconInfo implements android.os.Parcelable {
- ctor public IconInfo(java.lang.String, byte[]);
- ctor public IconInfo(android.net.wifi.IconInfo);
- method public int describeContents();
- method public byte[] getData();
- method public java.lang.String getFilename();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.wifi.IconInfo> CREATOR;
- }
-
public class ScanResult implements android.os.Parcelable {
method public int describeContents();
method public boolean is80211mcResponder();
@@ -26538,7 +26526,8 @@
field public static final java.lang.String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS";
- field public static final java.lang.String EXTRA_ICON_INFO = "android.net.wifi.extra.ICON_INFO";
+ field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
+ field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON";
field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
field public static final java.lang.String EXTRA_NEW_STATE = "newState";
@@ -31197,7 +31186,6 @@
method public final android.util.SizeF readSizeF();
method public final android.util.SparseArray readSparseArray(java.lang.ClassLoader);
method public final android.util.SparseBooleanArray readSparseBooleanArray();
- method public final android.util.SparseIntArray readSparseIntArray();
method public final java.lang.String readString();
method public final void readStringArray(java.lang.String[]);
method public final void readStringList(java.util.List<java.lang.String>);
@@ -31242,7 +31230,6 @@
method public final void writeSizeF(android.util.SizeF);
method public final void writeSparseArray(android.util.SparseArray<java.lang.Object>);
method public final void writeSparseBooleanArray(android.util.SparseBooleanArray);
- method public final void writeSparseIntArray(android.util.SparseIntArray);
method public final void writeString(java.lang.String);
method public final void writeStringArray(java.lang.String[]);
method public final void writeStringList(java.util.List<java.lang.String>);
diff --git a/api/system-current.txt b/api/system-current.txt
index c99ca68..2bf01d1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4441,6 +4441,14 @@
field public java.lang.String serviceDetails;
}
+ public final class AuthenticationRequiredException extends java.lang.SecurityException implements android.os.Parcelable {
+ ctor public AuthenticationRequiredException(java.lang.Throwable, android.app.PendingIntent);
+ method public int describeContents();
+ method public android.app.PendingIntent getUserAction();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.AuthenticationRequiredException> CREATOR;
+ }
+
public final class AutomaticZenRule implements android.os.Parcelable {
ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean);
ctor public AutomaticZenRule(android.os.Parcel);
@@ -5900,17 +5908,6 @@
field public static final int STYLE_SPINNER = 0; // 0x0
}
- public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
- ctor public RecoverableSecurityException(java.lang.Throwable, java.lang.CharSequence, android.app.RemoteAction);
- method public int describeContents();
- method public android.app.RemoteAction getUserAction();
- method public java.lang.CharSequence getUserMessage();
- method public void showAsDialog(android.app.Activity);
- method public void showAsNotification(android.content.Context, java.lang.String);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.app.RecoverableSecurityException> CREATOR;
- }
-
public final class RemoteAction implements android.os.Parcelable {
ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
method public android.app.RemoteAction clone();
@@ -28564,16 +28561,6 @@
field public boolean truncated;
}
- public final class IconInfo implements android.os.Parcelable {
- ctor public IconInfo(java.lang.String, byte[]);
- ctor public IconInfo(android.net.wifi.IconInfo);
- method public int describeContents();
- method public byte[] getData();
- method public java.lang.String getFilename();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.wifi.IconInfo> CREATOR;
- }
-
public class RttManager {
method public void disableResponder(android.net.wifi.RttManager.ResponderCallback);
method public void enableResponder(android.net.wifi.RttManager.ResponderCallback);
@@ -29069,7 +29056,8 @@
field public static final java.lang.String EXTRA_CHANGE_REASON = "changeReason";
field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS";
- field public static final java.lang.String EXTRA_ICON_INFO = "android.net.wifi.extra.ICON_INFO";
+ field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
+ field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON";
field public static final java.lang.String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
@@ -33925,7 +33913,6 @@
method public final android.util.SizeF readSizeF();
method public final android.util.SparseArray readSparseArray(java.lang.ClassLoader);
method public final android.util.SparseBooleanArray readSparseBooleanArray();
- method public final android.util.SparseIntArray readSparseIntArray();
method public final java.lang.String readString();
method public final void readStringArray(java.lang.String[]);
method public final void readStringList(java.util.List<java.lang.String>);
@@ -33970,7 +33957,6 @@
method public final void writeSizeF(android.util.SizeF);
method public final void writeSparseArray(android.util.SparseArray<java.lang.Object>);
method public final void writeSparseBooleanArray(android.util.SparseBooleanArray);
- method public final void writeSparseIntArray(android.util.SparseIntArray);
method public final void writeString(java.lang.String);
method public final void writeStringArray(java.lang.String[]);
method public final void writeStringList(java.util.List<java.lang.String>);
diff --git a/api/test-current.txt b/api/test-current.txt
index d1088dd..da25aa9 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -4307,6 +4307,14 @@
field public java.lang.String serviceDetails;
}
+ public final class AuthenticationRequiredException extends java.lang.SecurityException implements android.os.Parcelable {
+ ctor public AuthenticationRequiredException(java.lang.Throwable, android.app.PendingIntent);
+ method public int describeContents();
+ method public android.app.PendingIntent getUserAction();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.AuthenticationRequiredException> CREATOR;
+ }
+
public final class AutomaticZenRule implements android.os.Parcelable {
ctor public AutomaticZenRule(java.lang.String, android.content.ComponentName, android.net.Uri, int, boolean);
ctor public AutomaticZenRule(android.os.Parcel);
@@ -5719,17 +5727,6 @@
field public static final int STYLE_SPINNER = 0; // 0x0
}
- public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
- ctor public RecoverableSecurityException(java.lang.Throwable, java.lang.CharSequence, android.app.RemoteAction);
- method public int describeContents();
- method public android.app.RemoteAction getUserAction();
- method public java.lang.CharSequence getUserMessage();
- method public void showAsDialog(android.app.Activity);
- method public void showAsNotification(android.content.Context, java.lang.String);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.app.RecoverableSecurityException> CREATOR;
- }
-
public final class RemoteAction implements android.os.Parcelable {
ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
method public android.app.RemoteAction clone();
@@ -11751,6 +11748,15 @@
field protected final java.util.ArrayList<T> mObservers;
}
+ public final class PageViewCursor extends android.database.CursorWrapper implements android.database.CrossProcessCursor {
+ ctor public PageViewCursor(android.database.Cursor, int, int);
+ method public void fillWindow(int, android.database.CursorWindow);
+ method public android.database.CursorWindow getWindow();
+ method public boolean onMove(int, int);
+ method public static android.database.Cursor wrap(android.database.Cursor, android.os.Bundle);
+ field public static final java.lang.String EXTRA_AUTO_PAGED = "android.content.extra.AUTO_PAGED";
+ }
+
public class SQLException extends java.lang.RuntimeException {
ctor public SQLException();
ctor public SQLException(java.lang.String);
@@ -24723,6 +24729,7 @@
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+ field public static final java.lang.String COLUMN_LOCKED = "locked";
field public static final java.lang.String COLUMN_NETWORK_AFFILIATION = "network_affiliation";
field public static final java.lang.String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id";
field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
@@ -26382,16 +26389,6 @@
package android.net.wifi {
- public final class IconInfo implements android.os.Parcelable {
- ctor public IconInfo(java.lang.String, byte[]);
- ctor public IconInfo(android.net.wifi.IconInfo);
- method public int describeContents();
- method public byte[] getData();
- method public java.lang.String getFilename();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.net.wifi.IconInfo> CREATOR;
- }
-
public class ScanResult implements android.os.Parcelable {
method public int describeContents();
method public boolean is80211mcResponder();
@@ -26640,7 +26637,8 @@
field public static final java.lang.String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS";
- field public static final java.lang.String EXTRA_ICON_INFO = "android.net.wifi.extra.ICON_INFO";
+ field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
+ field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON";
field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
field public static final java.lang.String EXTRA_NEW_STATE = "newState";
@@ -31320,7 +31318,6 @@
method public final android.util.SizeF readSizeF();
method public final android.util.SparseArray readSparseArray(java.lang.ClassLoader);
method public final android.util.SparseBooleanArray readSparseBooleanArray();
- method public final android.util.SparseIntArray readSparseIntArray();
method public final java.lang.String readString();
method public final void readStringArray(java.lang.String[]);
method public final void readStringList(java.util.List<java.lang.String>);
@@ -31365,7 +31362,6 @@
method public final void writeSizeF(android.util.SizeF);
method public final void writeSparseArray(android.util.SparseArray<java.lang.Object>);
method public final void writeSparseBooleanArray(android.util.SparseBooleanArray);
- method public final void writeSparseIntArray(android.util.SparseIntArray);
method public final void writeString(java.lang.String);
method public final void writeStringArray(java.lang.String[]);
method public final void writeStringList(java.util.List<java.lang.String>);
diff --git a/core/java/android/app/AuthenticationRequiredException.java b/core/java/android/app/AuthenticationRequiredException.java
new file mode 100644
index 0000000..8960979
--- /dev/null
+++ b/core/java/android/app/AuthenticationRequiredException.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2017 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.ContentProvider;
+import android.content.ContentResolver;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Specialization of {@link SecurityException} that is thrown when authentication is needed from the
+ * end user before viewing the content.
+ * <p>
+ * This exception is only appropriate where there is a concrete action the user can take to
+ * authorize and make forward progress, such as confirming or entering authentication credentials,
+ * or granting access via other means.
+ * <p class="note">
+ * Note: legacy code that receives this exception may treat it as a general
+ * {@link SecurityException}, and thus there is no guarantee that the action contained will be
+ * invoked by the user.
+ * </p>
+ */
+public final class AuthenticationRequiredException extends SecurityException implements Parcelable {
+ private static final String TAG = "AuthenticationRequiredException";
+
+ private final PendingIntent mUserAction;
+
+ /** {@hide} */
+ public AuthenticationRequiredException(Parcel in) {
+ this(new SecurityException(in.readString()), PendingIntent.CREATOR.createFromParcel(in));
+ }
+
+ /**
+ * Create an instance ready to be thrown.
+ *
+ * @param cause original cause with details designed for engineering
+ * audiences.
+ * @param userAction primary action that will initiate the recovery. This
+ * must launch an activity that is expected to set
+ * {@link Activity#setResult(int)} before finishing to
+ * communicate the final status of the recovery. For example,
+ * apps that observe {@link Activity#RESULT_OK} may choose to
+ * immediately retry their operation. If this exception was
+ * thrown from a {@link ContentProvider}, you should also send
+ * any relevant {@link ContentResolver#notifyChange} events to
+ * trigger reloading of data.
+ */
+ public AuthenticationRequiredException(Throwable cause, PendingIntent userAction) {
+ super(cause.getMessage());
+ mUserAction = Preconditions.checkNotNull(userAction);
+ }
+
+ /**
+ * Return primary action that will initiate the authorization.
+ */
+ public PendingIntent getUserAction() {
+ return mUserAction;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(getMessage());
+ mUserAction.writeToParcel(dest, flags);
+ }
+
+ public static final Creator<AuthenticationRequiredException> CREATOR =
+ new Creator<AuthenticationRequiredException>() {
+ @Override
+ public AuthenticationRequiredException createFromParcel(Parcel source) {
+ return new AuthenticationRequiredException(source);
+ }
+
+ @Override
+ public AuthenticationRequiredException[] newArray(int size) {
+ return new AuthenticationRequiredException[size];
+ }
+ };
+}
diff --git a/core/java/android/app/RecoverableSecurityException.java b/core/java/android/app/RecoverableSecurityException.java
index 8612f18..a503a46 100644
--- a/core/java/android/app/RecoverableSecurityException.java
+++ b/core/java/android/app/RecoverableSecurityException.java
@@ -45,7 +45,8 @@
* Note: legacy code that receives this exception may treat it as a general
* {@link SecurityException}, and thus there is no guarantee that the messages
* contained will be shown to the end user.
- * </p>
+ *
+ * @hide
*/
public final class RecoverableSecurityException extends SecurityException implements Parcelable {
private static final String TAG = "RecoverableSecurityException";
diff --git a/core/java/android/database/PageViewCursor.java b/core/java/android/database/PageViewCursor.java
index 5f42f30..44727a0 100644
--- a/core/java/android/database/PageViewCursor.java
+++ b/core/java/android/database/PageViewCursor.java
@@ -18,13 +18,13 @@
import static com.android.internal.util.Preconditions.checkArgument;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.content.ContentResolver;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.util.MathUtils;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
/**
@@ -34,11 +34,10 @@
*
* @hide
*/
+@TestApi
public final class PageViewCursor extends CursorWrapper implements CrossProcessCursor {
- /**
- * An in internal extra added to results that are auto-paged using the wrapper.
- */
+ /** An extra added to results that are auto-paged using the wrapper. */
public static final String EXTRA_AUTO_PAGED = "android.content.extra.AUTO_PAGED";
private static final String TAG = "PageViewCursor";
@@ -56,7 +55,6 @@
/**
* @see PageViewCursor#wrap(Cursor, Bundle)
*/
- @VisibleForTesting
public PageViewCursor(Cursor cursor, int offset, int limit) {
super(cursor);
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 7a39d23..2e35a51 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -898,6 +898,9 @@
}
}
+ /**
+ * @hide
+ */
public final void writeSparseIntArray(SparseIntArray val) {
if (val == null) {
writeInt(-1);
@@ -2323,6 +2326,7 @@
/**
* Read and return a new SparseIntArray object from the parcel at the current
* dataPosition(). Returns null if the previously written array object was null.
+ * @hide
*/
public final SparseIntArray readSparseIntArray() {
int N = readInt();
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index f69c996..3137658 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -92,6 +92,12 @@
public static final int VPN_UID = 1016;
/**
+ * Defines the UID/GID for keystore.
+ * @hide
+ */
+ public static final int KEYSTORE_UID = 1017;
+
+ /**
* Defines the UID/GID for the NFC service process.
* @hide
*/
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 620d33a5..9e68afb 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -38,7 +38,7 @@
import android.Manifest;
import android.annotation.CallSuper;
import android.annotation.Nullable;
-import android.app.RecoverableSecurityException;
+import android.app.AuthenticationRequiredException;
import android.content.ClipDescription;
import android.content.ContentProvider;
import android.content.ContentResolver;
@@ -235,10 +235,6 @@
* {@link Document#COLUMN_DOCUMENT_ID}. You must allocate a new
* {@link Document#COLUMN_DOCUMENT_ID} to represent the document, which must
* not change once returned.
- * <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), but it is not guaranteed that
- * the client will handle this properly.
*
* @param parentDocumentId the parent directory to create the new document
* under.
@@ -247,6 +243,10 @@
* @param displayName the display name of the new document. The provider may
* alter this name to meet any internal constraints, such as
* avoiding conflicting names.
+
+ * @throws AuthenticationRequiredException If authentication is required from the user (such as
+ * login credentials), but it is not guaranteed that the client will handle this
+ * properly.
*/
@SuppressWarnings("unused")
public String createDocument(String parentDocumentId, String mimeType, String displayName)
@@ -262,15 +262,14 @@
* URI permission grants will be updated to point at the new document. If
* the original {@link Document#COLUMN_DOCUMENT_ID} is still valid after the
* rename, return {@code null}.
- * <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), but it is not guaranteed that
- * the client will handle this properly.
*
* @param documentId the document to rename.
* @param displayName the updated display name of the document. The provider
* may alter this name to meet any internal constraints, such as
* avoiding conflicting names.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
*/
@SuppressWarnings("unused")
public String renameDocument(String documentId, String displayName)
@@ -286,12 +285,11 @@
* call (such as documents inside a directory) the implementor is
* responsible for revoking those permissions using
* {@link #revokeDocumentPermission(String)}.
- * <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), but it is not guaranteed that
- * the client will handle this properly.
*
* @param documentId the document to delete.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
*/
@SuppressWarnings("unused")
public void deleteDocument(String documentId) throws FileNotFoundException {
@@ -305,13 +303,12 @@
* the same document provider. Upon completion returns the document id of
* the copied document at the target destination. {@code null} must never
* be returned.
- * <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), but it is not guaranteed that
- * the client will handle this properly.
*
* @param sourceDocumentId the document to copy.
* @param targetParentDocumentId the target document to be copied into as a child.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
*/
@SuppressWarnings("unused")
public String copyDocument(String sourceDocumentId, String targetParentDocumentId)
@@ -329,15 +326,14 @@
*
* <p>It's the responsibility of the provider to revoke grants if the document
* is no longer accessible using <code>sourceDocumentId</code>.
- * <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), but it is not guaranteed that
- * the client will handle this properly.
*
* @param sourceDocumentId the document to move.
* @param sourceParentDocumentId the parent of the document to move.
* @param targetParentDocumentId the target document to be a new parent of the
* source document.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
*/
@SuppressWarnings("unused")
public String moveDocument(String sourceDocumentId, String sourceParentDocumentId,
@@ -355,11 +351,11 @@
* <p>It's the responsibility of the provider to revoke grants if the document is
* removed from the last parent, and effectively the document is deleted.
*
- * <p>{@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), but it is not guaranteed that
- * the client will handle this properly.
* @param documentId the document to remove.
* @param parentDocumentId the parent of the document to move.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
*/
@SuppressWarnings("unused")
public void removeDocument(String documentId, String parentDocumentId)
@@ -377,9 +373,6 @@
* <p>This API assumes that document ID has enough info to infer the root.
* Different roots should use different document ID to refer to the same
* document.
- * <p>{@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), but it is not guaranteed that
- * the client will handle this properly.perly.
*
*
* @param parentDocumentId the document from which the path starts if not null,
@@ -388,6 +381,9 @@
* @return the path of the requested document. If parentDocumentId is null
* returned root ID must not be null. If parentDocumentId is not null
* returned root ID must be null.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
*/
public Path findDocumentPath(@Nullable String parentDocumentId, String childDocumentId)
throws FileNotFoundException {
@@ -397,7 +393,7 @@
/**
* Creates an intent sender for a web link, if the document is web linkable.
* <p>
- * {@link RecoverableSecurityException} can be thrown if user does not have
+ * {@link AuthenticationRequiredException} can be thrown if user does not have
* sufficient permission for the linked document. Before any new permissions
* are granted for the linked document, a visible UI must be shown, so the
* user can explicitly confirm whether the permission grants are expected.
@@ -414,6 +410,9 @@
*
* @param documentId the document to create a web link intent for.
* @param options additional information, such as list of recipients. Optional.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
*
* @see DocumentsContract.Document#FLAG_WEB_LINKABLE
* @see android.app.PendingIntent#getIntentSender
@@ -436,9 +435,6 @@
* android.database.ContentObserver, boolean)} with
* {@link DocumentsContract#buildRootsUri(String)} to notify the system.
* <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), or returned as part of
- * Cursor's bundle. It is not guaranteed that the client will handle this properly.
*
* @param projection list of {@link Root} columns to put into the cursor. If
* {@code null} all supported columns should be included.
@@ -452,10 +448,6 @@
* sorted by {@link Document#COLUMN_LAST_MODIFIED} in descending order, and
* limited to only return the 64 most recently modified documents.
* <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), or returned as part of
- * Cursor's bundle. It is not guaranteed that the client will handle this properly.
- * <p>
* Recent documents do not support change notifications.
*
* @param projection list of {@link Document} columns to put into the
@@ -472,16 +464,14 @@
/**
* Return metadata for the single requested document. You should avoid
* making network requests to keep this request fast.
- * <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), or returned as part of
- * Cursor's bundle. It is not guaranteed that the client will handle this properly.
- *
*
* @param documentId the document to return.
* @param projection list of {@link Document} columns to put into the
* cursor. If {@code null} all supported columns should be
* included.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
*/
public abstract Cursor queryDocument(String documentId, String[] projection)
throws FileNotFoundException;
@@ -509,11 +499,6 @@
* you can call {@link ContentResolver#notifyChange(Uri,
* android.database.ContentObserver, boolean)} with that Uri to send change
* notifications.
- * <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), or returned as part of
- * Cursor's bundle. It is not guaranteed that the client will handle this properly.
- *
*
* @param parentDocumentId the directory to return children for.
* @param projection list of {@link Document} columns to put into the
@@ -525,6 +510,9 @@
* may be unordered. This ordering is a hint that can be used to
* prioritize how data is fetched from the network, but UI may
* always enforce a specific ordering.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
* @see DocumentsContract#EXTRA_LOADING
* @see DocumentsContract#EXTRA_INFO
* @see DocumentsContract#EXTRA_ERROR
@@ -552,10 +540,6 @@
* you can call {@link ContentResolver#notifyChange(Uri,
* android.database.ContentObserver, boolean)} with that Uri to send change
* notifications.
- * <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), or returned as part of
- * Cursor's bundle. It is not guaranteed that the client will handle this properly.
*
* @param parentDocumentId the directory to return children for.
* @param projection list of {@link Document} columns to put into the
@@ -567,6 +551,9 @@
* will be used, which may be unordered. See
* {@link ContentResolver#QUERY_ARG_SORT_COLUMNS} for
* details.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
*
* @see DocumentsContract#EXTRA_LOADING
* @see DocumentsContract#EXTRA_INFO
@@ -609,16 +596,16 @@
* String, String)}. Then you can call {@link ContentResolver#notifyChange(Uri,
* android.database.ContentObserver, boolean)} with that Uri to send change
* notifications.
- * <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), or returned as part of
- * Cursor's bundle. It is not guaranteed that the client will handle this properly.
*
* @param rootId the root to search under.
* @param query string to match documents against.
* @param projection list of {@link Document} columns to put into the
* cursor. If {@code null} all supported columns should be
* included.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
+ *
* @see DocumentsContract#EXTRA_LOADING
* @see DocumentsContract#EXTRA_INFO
* @see DocumentsContract#EXTRA_ERROR
@@ -641,9 +628,9 @@
* implementation queries {@link #queryDocument(String, String[])}, so
* providers may choose to override this as an optimization.
* <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), but it is not guaranteed that
- * the client will handle this properly.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
*/
public String getDocumentType(String documentId) throws FileNotFoundException {
final Cursor cursor = queryDocument(documentId, null);
@@ -669,15 +656,14 @@
* <p>
* If you block while downloading content, you should periodically check
* {@link CancellationSignal#isCanceled()} to abort abandoned open requests.
- * <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), but it is not guaranteed that
- * the client will handle this properly.
*
* @param documentId the document to return.
* @param mode the mode to open with, such as 'r', 'w', or 'rw'.
* @param signal used by the caller to signal if the request should be
* cancelled. May be null.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
* @see ParcelFileDescriptor#open(java.io.File, int, android.os.Handler,
* OnCloseListener)
* @see ParcelFileDescriptor#createReliablePipe()
@@ -697,15 +683,14 @@
* If you perform expensive operations to download or generate a thumbnail,
* you should periodically check {@link CancellationSignal#isCanceled()} to
* abort abandoned thumbnail requests.
- * <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), but it is not guaranteed that
- * the client will handle this properly.
*
* @param documentId the document to return.
* @param sizeHint hint of the optimal thumbnail dimensions.
* @param signal used by the caller to signal if the request should be
* cancelled. May be null.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
* @see Document#FLAG_SUPPORTS_THUMBNAIL
*/
@SuppressWarnings("unused")
@@ -723,10 +708,6 @@
* matching the specified MIME type filter.
* <p>
* Virtual documents must have at least one streamable format.
- * <p>
- * {@link RecoverableSecurityException} can be thrown if more input is required
- * from the user (such as insufficient permission), but it is not guaranteed that
- * the client will handle this properly.
*
* @param documentId the document to return.
* @param mimeTypeFilter the MIME type filter for the requested format. May
@@ -735,6 +716,9 @@
* provider.
* @param signal used by the caller to signal if the request should be
* cancelled. May be null.
+ * @throws AuthenticationRequiredException If authentication is required from
+ * the user (such as login credentials), but it is not guaranteed
+ * that the client will handle this properly.
* @see #getDocumentStreamTypes(String, String)
*/
@SuppressWarnings("unused")
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 7b99d07..78d18fd 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -75,6 +75,7 @@
private int mDropDownWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
private boolean mDropDownVerticalOffsetSet;
private boolean mIsAnimatedFromAnchor = true;
+ private boolean mOverlapAnchor;
private int mDropDownGravity = Gravity.NO_GRAVITY;
@@ -672,6 +673,7 @@
mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
mPopup.setTouchInterceptor(mTouchInterceptor);
mPopup.setEpicenterBounds(mEpicenterBounds);
+ mPopup.setOverlapAnchor(mOverlapAnchor);
mPopup.showAsDropDown(getAnchorView(), mDropDownHorizontalOffset,
mDropDownVerticalOffset, mDropDownGravity);
mDropDownList.setSelection(ListView.INVALID_POSITION);
@@ -1245,6 +1247,13 @@
return listContent + otherHeights;
}
+ /**
+ * @hide
+ */
+ public void setOverlapAnchor(boolean overlap) {
+ mOverlapAnchor = overlap;
+ }
+
private class PopupDataSetObserver extends DataSetObserver {
@Override
public void onChanged() {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 26b3ae2..9f10531 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -55,6 +55,7 @@
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+import android.view.WindowManagerGlobal;
import com.android.internal.R;
@@ -137,6 +138,7 @@
private final int[] mTmpDrawingLocation = new int[2];
private final int[] mTmpScreenLocation = new int[2];
+ private final int[] mTmpAppLocation = new int[2];
private final Rect mTempRect = new Rect();
private Context mContext;
@@ -242,6 +244,9 @@
private final OnScrollChangedListener mOnScrollChangedListener = this::alignToAnchor;
+ private final View.OnLayoutChangeListener mOnLayoutChangeListener =
+ (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> alignToAnchor();
+
private int mAnchorXoff;
private int mAnchorYoff;
private int mAnchoredGravity;
@@ -1238,7 +1243,8 @@
mIsShowing = true;
mIsDropdown = true;
- final WindowManager.LayoutParams p = createPopupLayoutParams(anchor.getWindowToken());
+ final WindowManager.LayoutParams p =
+ createPopupLayoutParams(anchor.getApplicationWindowToken());
preparePopup(p);
final boolean aboveAnchor = findDropDownPosition(anchor, p, xoff, yoff,
@@ -1547,13 +1553,21 @@
}
// Initially, align to the bottom-left corner of the anchor plus offsets.
+ final int[] appScreenLocation = mTmpAppLocation;
+ final View appRootView = getAppRootView(anchor);
+ appRootView.getLocationOnScreen(appScreenLocation);
+
+ final int[] screenLocation = mTmpScreenLocation;
+ anchor.getLocationOnScreen(screenLocation);
+
final int[] drawingLocation = mTmpDrawingLocation;
- anchor.getLocationInWindow(drawingLocation);
+ drawingLocation[0] = screenLocation[0] - appScreenLocation[0];
+ drawingLocation[1] = screenLocation[1] - appScreenLocation[1];
outParams.x = drawingLocation[0] + xOffset;
outParams.y = drawingLocation[1] + anchorHeight + yOffset;
final Rect displayFrame = new Rect();
- anchor.getWindowVisibleDisplayFrame(displayFrame);
+ appRootView.getWindowVisibleDisplayFrame(displayFrame);
if (width == MATCH_PARENT) {
width = displayFrame.right - displayFrame.left;
}
@@ -1574,9 +1588,6 @@
outParams.x -= width - anchorWidth;
}
- final int[] screenLocation = mTmpScreenLocation;
- anchor.getLocationOnScreen(screenLocation);
-
// First, attempt to fit the popup vertically without resizing.
final boolean fitsVertical = tryFitVertical(outParams, yOffset, height,
anchorHeight, drawingLocation[1], screenLocation[1], displayFrame.top,
@@ -1595,7 +1606,9 @@
scrollY + height + anchorHeight + yOffset);
if (allowScroll && anchor.requestRectangleOnScreen(r, true)) {
// Reset for the new anchor position.
- anchor.getLocationInWindow(drawingLocation);
+ anchor.getLocationOnScreen(screenLocation);
+ drawingLocation[0] = screenLocation[0] - appScreenLocation[0];
+ drawingLocation[1] = screenLocation[1] - appScreenLocation[1];
outParams.x = drawingLocation[0] + xOffset;
outParams.y = drawingLocation[1] + anchorHeight + yOffset;
@@ -1793,7 +1806,8 @@
Rect displayFrame = null;
final Rect visibleDisplayFrame = new Rect();
- anchor.getWindowVisibleDisplayFrame(visibleDisplayFrame);
+ final View appView = getAppRootView(anchor);
+ appView.getWindowVisibleDisplayFrame(visibleDisplayFrame);
if (ignoreBottomDecorations) {
// In the ignore bottom decorations case we want to
// still respect all other decorations so we use the inset visible
@@ -2240,6 +2254,7 @@
final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
if (anchorRoot != null) {
anchorRoot.removeOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
+ anchorRoot.removeOnLayoutChangeListener(mOnLayoutChangeListener);
}
mAnchor = null;
@@ -2258,6 +2273,7 @@
final View anchorRoot = anchor.getRootView();
anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
+ anchorRoot.addOnLayoutChangeListener(mOnLayoutChangeListener);
mAnchor = new WeakReference<>(anchor);
mAnchorRoot = new WeakReference<>(anchorRoot);
@@ -2281,6 +2297,15 @@
}
}
+ private View getAppRootView(View anchor) {
+ final View appWindowView = WindowManagerGlobal.getInstance().getWindowView(
+ anchor.getApplicationWindowToken());
+ if (appWindowView != null) {
+ return appWindowView;
+ }
+ return anchor.getRootView();
+ }
+
private class PopupDecorView extends FrameLayout {
private TransitionListenerAdapter mPendingExitListener;
diff --git a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
index ebcec5c..6dff8b4 100644
--- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
@@ -381,6 +381,7 @@
if (parentView != null) {
// This menu is a cascading submenu anchored to a parent view.
+ popupWindow.setAnchorView(parentView);
popupWindow.setTouchModal(false);
popupWindow.setEnterTransition(null);
@@ -388,42 +389,30 @@
final boolean showOnRight = nextMenuPosition == HORIZ_POSITION_RIGHT;
mLastPosition = nextMenuPosition;
- // A popup anchored to mAnchorView with (0,0) offset would be shown at this position.
- final int[] offsetOrigin = new int[2];
- mAnchorView.getLocationOnScreen(offsetOrigin);
- offsetOrigin[1] += mAnchorView.getHeight();
-
- final int[] parentViewScreenLocation = new int[2];
- parentView.getLocationOnScreen(parentViewScreenLocation);
-
- // Translate the parent view location into the offset coordinate space.
- // If used as horizontal/vertical offsets, these values would position the submenu
- // at the exact same position as the parent item.
- final int parentOffsetLeft = parentViewScreenLocation[0] - offsetOrigin[0];
- final int parentOffsetTop = parentViewScreenLocation[1] - offsetOrigin[1];
-
- // Adjust the horizontal offset to display the submenu to the right or to the left
+ // Compute the horizontal offset to display the submenu to the right or to the left
// of the parent item.
// By now, mDropDownGravity is the resolved absolute gravity, so
// this should work in both LTR and RTL.
final int x;
if ((mDropDownGravity & Gravity.RIGHT) == Gravity.RIGHT) {
if (showOnRight) {
- x = parentOffsetLeft + menuWidth;
+ x = menuWidth;
} else {
- x = parentOffsetLeft - parentView.getWidth();
+ x = -parentView.getWidth();
}
} else {
if (showOnRight) {
- x = parentOffsetLeft + parentView.getWidth();
+ x = parentView.getWidth();
} else {
- x = parentOffsetLeft - menuWidth;
+ x = -menuWidth;
}
}
popupWindow.setHorizontalOffset(x);
- // Use the same vertical offset as the parent item.
- popupWindow.setVerticalOffset(parentOffsetTop);
+ // Align with the top edge of the parent view (or the bottom edge when the submenu is
+ // flipped vertically).
+ popupWindow.setOverlapAnchor(true);
+ popupWindow.setVerticalOffset(0);
} else {
if (mHasXOffset) {
popupWindow.setHorizontalOffset(mXOffset);
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index a8d6830..de5e505 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -621,7 +621,7 @@
const uint8_t* s = (const uint8_t*)src;
do {
uint8_t c = *s++;
- *dst++ = SkColorSetARGB(c, c, c, c);
+ *dst++ = SkColorSetARGB(c, 0, 0, 0);
} while (--width != 0);
}
@@ -727,6 +727,50 @@
return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
}
+static bool bitmapCopyTo(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src,
+ SkBitmap::Allocator* alloc) {
+ // Skia does not support copying from kAlpha8 to types that are not alpha only.
+ // We will handle this case here.
+ if (kAlpha_8_SkColorType == src.colorType() && kAlpha_8_SkColorType != dstCT) {
+ SkAutoPixmapUnlock srcUnlocker;
+ if (!src.requestLock(&srcUnlocker)) {
+ return false;
+ }
+ SkPixmap srcPixmap = srcUnlocker.pixmap();
+
+ SkImageInfo dstInfo = src.info().makeColorType(dstCT);
+ if (!dst->setInfo(dstInfo)) {
+ return false;
+ }
+ if (!dst->tryAllocPixels(alloc, nullptr)) {
+ return false;
+ }
+
+ switch (dstCT) {
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType: {
+ for (int y = 0; y < src.height(); y++) {
+ const uint8_t* srcRow = srcPixmap.addr8(0, y);
+ uint32_t* dstRow = dst->getAddr32(0, y);
+ ToColor_SA8(dstRow, srcRow, src.width(), nullptr);
+ }
+ return true;
+ }
+ case kRGB_565_SkColorType: {
+ for (int y = 0; y < src.height(); y++) {
+ uint16_t* dstRow = dst->getAddr16(0, y);
+ memset(dstRow, 0, sizeof(uint16_t) * src.width());
+ }
+ return true;
+ }
+ default:
+ return false;
+ }
+ }
+
+ return src.copyTo(dst, dstCT, alloc);
+}
+
static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
jint dstConfigHandle, jboolean isMutable) {
SkBitmap src;
@@ -743,7 +787,7 @@
SkBitmap result;
HeapAllocator allocator;
- if (!src.copyTo(&result, dstCT, &allocator)) {
+ if (!bitmapCopyTo(&result, dstCT, src, &allocator)) {
return NULL;
}
auto bitmap = allocator.getStorageObjAndReset();
@@ -754,7 +798,7 @@
SkBitmap result;
AshmemPixelAllocator allocator(env);
- if (!src.copyTo(&result, dstCT, &allocator)) {
+ if (!bitmapCopyTo(&result, dstCT, src, &allocator)) {
return NULL;
}
auto bitmap = allocator.getStorageObjAndReset();
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index c28aa5e..6808b57 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -1971,10 +1971,11 @@
* channel is not locked thus the user is not prompted to enter passcode If not specified,
* this value is set to 0 (not locked) by default.
*
+ * <p>This column can only be set by applications having proper system permission to
+ * modify parental control settings. For other applications, this is a read-only column.
+
* <p>Type: INTEGER (boolean)
- * @hide
*/
- @SystemApi
public static final String COLUMN_LOCKED = "locked";
/**
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8dc694c..d6d01d8a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1382,11 +1382,15 @@
of notifications. Replaces the channel name and only appears when there is more than one channel. -->
<string name="notification_num_channels"> <xliff:g id="number">%d</xliff:g> notification categories</string>
+ <!-- Notification: Control panel: Label that shows when an app has not upgraded to use channels.
+ Hints that the user's only option is to block all of the app's notifications. -->
+ <string name="notification_default_channel_desc">This app doesn\'t have notification categories</string>
+
<!-- Notification: Control panel: Label that shows how many channels this application has
- defined, describing the current notification channel as "1 out of n categories from this app". -->
+ defined, describing the current notification channel as "1 out of n notification categories from this app". -->
<plurals name="notification_num_channels_desc">
- <item quantity="one">1 out of <xliff:g id="number">%d</xliff:g> category from this app</item>
- <item quantity="other">1 out of <xliff:g id="number">%d</xliff:g> categories from this app</item>
+ <item quantity="one">1 out of <xliff:g id="number">%d</xliff:g> notification category from this app</item>
+ <item quantity="other">1 out of <xliff:g id="number">%d</xliff:g> notification categories from this app</item>
</plurals>
<!-- Notification: Control panel: For bundles of notifications, this label that lists the
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index a9043e4..54921a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -99,11 +99,14 @@
mINotificationManager = iNotificationManager;
mPkg = pkg;
mNotificationChannels = notificationChannels;
+ boolean isSingleDefaultChannel = false;
if (mNotificationChannels.isEmpty()) {
throw new IllegalArgumentException("bindNotification requires at least one channel");
} else if (mNotificationChannels.size() == 1) {
mSingleNotificationChannel = mNotificationChannels.get(0);
mStartingUserImportance = mSingleNotificationChannel.getImportance();
+ isSingleDefaultChannel = mSingleNotificationChannel.getId()
+ .equals(NotificationChannel.DEFAULT_CHANNEL_ID);
} else {
mSingleNotificationChannel = null;
}
@@ -135,24 +138,30 @@
String channelsDescText;
mNumChannelsView = (TextView) (findViewById(R.id.num_channels_desc));
- switch (mNotificationChannels.size()) {
- case 1:
- channelsDescText = String.format(mContext.getResources().getQuantityString(
- R.plurals.notification_num_channels_desc, numChannels), numChannels);
- break;
- case 2:
- channelsDescText = mContext.getString(R.string.notification_channels_list_desc_2,
- mNotificationChannels.get(0).getName(),
- mNotificationChannels.get(1).getName());
- break;
- default:
- final int numOthers = mNotificationChannels.size() - 2;
- channelsDescText = String.format(
- mContext.getResources().getQuantityString(
- R.plurals.notification_channels_list_desc_2_and_others, numOthers),
- mNotificationChannels.get(0).getName(),
- mNotificationChannels.get(1).getName(),
- numOthers);
+ if (isSingleDefaultChannel) {
+ channelsDescText = mContext.getString(R.string.notification_default_channel_desc);
+ } else {
+ switch (mNotificationChannels.size()) {
+ case 1:
+ channelsDescText = String.format(mContext.getResources().getQuantityString(
+ R.plurals.notification_num_channels_desc, numChannels), numChannels);
+ break;
+ case 2:
+ channelsDescText = mContext.getString(
+ R.string.notification_channels_list_desc_2,
+ mNotificationChannels.get(0).getName(),
+ mNotificationChannels.get(1).getName());
+ break;
+ default:
+ final int numOthers = mNotificationChannels.size() - 2;
+ channelsDescText = String.format(
+ mContext.getResources().getQuantityString(
+ R.plurals.notification_channels_list_desc_2_and_others,
+ numOthers),
+ mNotificationChannels.get(0).getName(),
+ mNotificationChannels.get(1).getName(),
+ numOthers);
+ }
}
mNumChannelsView.setText(channelsDescText);
@@ -160,9 +169,8 @@
// Multiple channels don't use a channel name for the title.
channelNameText = mContext.getString(R.string.notification_num_channels,
mNotificationChannels.size());
- } else if (mSingleNotificationChannel.getId()
- .equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
- // If this is the placeholder channel, don't use our channel-specific text.
+ } else if (isSingleDefaultChannel) {
+ // If this is the default channel, don't use our channel-specific text.
channelNameText = mContext.getString(R.string.notification_header_default_channel);
} else {
channelNameText = mSingleNotificationChannel.getName();
@@ -282,15 +290,9 @@
}
private void updateSecondaryText() {
- final boolean defaultChannel = mSingleNotificationChannel != null &&
- mSingleNotificationChannel.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID);
final boolean disabled = mSingleNotificationChannel != null &&
getSelectedImportance() == NotificationManager.IMPORTANCE_NONE;
- if (defaultChannel) {
- // Don't show any secondary text if this is from the default channel.
- mChannelDisabledView.setVisibility(View.GONE);
- mNumChannelsView.setVisibility(View.GONE);
- } else if (disabled) {
+ if (disabled) {
mChannelDisabledView.setVisibility(View.VISIBLE);
mNumChannelsView.setVisibility(View.GONE);
} else {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 8aca546..5632b71 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -260,12 +260,14 @@
}
@Test
- public void testBindNotification_NumChannelsTextHiddenWhenDefaultChannel() throws Exception {
+ public void testBindNotification_NumChannelsTextUniqueWhenDefaultChannel() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, Arrays.asList(mDefaultNotificationChannel), null, null, null);
final TextView numChannelsView =
(TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
- assertTrue(numChannelsView.getVisibility() != View.VISIBLE);
+ assertEquals(View.VISIBLE, numChannelsView.getVisibility());
+ assertEquals(mContext.getString(R.string.notification_default_channel_desc),
+ numChannelsView.getText());
}
@Test
@@ -390,13 +392,14 @@
@Test
@UiThreadTest
- public void testBindNotification_ChannelDisabledTextHiddenWhenDefaultChannel()
+ public void testBindNotification_ChannelDisabledTextShowsForDefaultChannel()
throws Exception {
+ mDefaultNotificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, Arrays.asList(mDefaultNotificationChannel), null, null, null);
final TextView channelDisabledView =
(TextView) mNotificationInfo.findViewById(R.id.channel_disabled);
- assertTrue(channelDisabledView.getVisibility() != View.VISIBLE);
+ assertEquals(View.VISIBLE, channelDisabledView.getVisibility());
}
@Test
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 3d18160..ede5a5e 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -179,6 +179,7 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -3116,8 +3117,19 @@
+ " - notification=" + notification);
return;
}
- throw new IllegalArgumentException("No Channel found for channelId=" + channelId
- + ", notification=" + notification);
+ final String noChannelStr = "No Channel found for "
+ + "pkg=" + pkg
+ + ", channelId=" + channelId
+ + ", opPkg=" + opPkg
+ + ", callingUid=" + callingUid
+ + ", userId=" + userId
+ + ", incomingUserId=" + incomingUserId
+ + ", notificationUid=" + notificationUid
+ + ", notification=" + notification;
+ // STOPSHIP TODO: should throw instead of logging.
+ // throw new IllegalArgumentException(noChannelStr);
+ Log.e(TAG, noChannelStr);
+ return;
}
final StatusBarNotification n = new StatusBarNotification(
pkg, opPkg, id, tag, notificationUid, callingPid, notification,
@@ -3640,6 +3652,10 @@
mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
effect, record.getAudioAttributes());
return true;
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Error creating vibration waveform with pattern: " +
+ Arrays.toString(vibration));
+ return false;
} finally{
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java
index db23a6a..342ec4b 100644
--- a/services/core/java/com/android/server/policy/GlobalActions.java
+++ b/services/core/java/com/android/server/policy/GlobalActions.java
@@ -29,9 +29,10 @@
private static final boolean DEBUG = false;
private final Context mContext;
- private final LegacyGlobalActions mLegacyGlobalActions;
private final StatusBarManagerInternal mStatusBarInternal;
private final Handler mHandler;
+ private final WindowManagerFuncs mWindowManagerFuncs;
+ private LegacyGlobalActions mLegacyGlobalActions;
private boolean mKeyguardShowing;
private boolean mDeviceProvisioned;
private boolean mStatusBarConnected;
@@ -40,8 +41,7 @@
public GlobalActions(Context context, WindowManagerFuncs windowManagerFuncs) {
mContext = context;
mHandler = new Handler();
- mLegacyGlobalActions = new LegacyGlobalActions(context, windowManagerFuncs,
- this::onGlobalActionsDismissed);
+ mWindowManagerFuncs = windowManagerFuncs;
mStatusBarInternal = LocalServices.getService(StatusBarManagerInternal.class);
// Some form factors do not have a status bar.
@@ -50,6 +50,12 @@
}
}
+ private void ensureLegacyCreated() {
+ if (mLegacyGlobalActions != null) return;
+ mLegacyGlobalActions = new LegacyGlobalActions(mContext, mWindowManagerFuncs,
+ this::onGlobalActionsDismissed);
+ }
+
public void showDialog(boolean keyguardShowing, boolean deviceProvisioned) {
if (DEBUG) Slog.d(TAG, "showDialog " + keyguardShowing + " " + deviceProvisioned);
mKeyguardShowing = keyguardShowing;
@@ -60,6 +66,7 @@
mHandler.postDelayed(mShowTimeout, 5000);
} else {
// SysUI isn't alive, show legacy menu.
+ ensureLegacyCreated();
mLegacyGlobalActions.showDialog(mKeyguardShowing, mDeviceProvisioned);
}
}
@@ -83,6 +90,7 @@
mStatusBarConnected = connected;
if (mShowing && !mStatusBarConnected) {
// Status bar died but we need to be showing global actions still, show the legacy.
+ ensureLegacyCreated();
mLegacyGlobalActions.showDialog(mKeyguardShowing, mDeviceProvisioned);
}
}
@@ -92,6 +100,7 @@
public void run() {
if (DEBUG) Slog.d(TAG, "Global actions timeout");
// We haven't heard from sysui, show the legacy dialog.
+ ensureLegacyCreated();
mLegacyGlobalActions.showDialog(mKeyguardShowing, mDeviceProvisioned);
}
};
diff --git a/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java b/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java
index 0b80d81..ab9ab67 100644
--- a/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java
+++ b/services/core/java/com/android/server/security/KeyAttestationApplicationIdProviderService.java
@@ -21,6 +21,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Binder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.security.keymaster.KeyAttestationPackageInfo;
@@ -45,14 +46,19 @@
public KeyAttestationApplicationId getKeyAttestationApplicationId(int uid)
throws RemoteException {
- String[] packageNames = mPackageManager.getPackagesForUid(uid);
- if (packageNames == null) {
- throw new RemoteException("No packages for uid");
+ if (Binder.getCallingUid() != android.os.Process.KEYSTORE_UID) {
+ throw new SecurityException("This service can only be used by Keystore");
}
- int userId = UserHandle.getUserId(uid);
- KeyAttestationPackageInfo[] keyAttestationPackageInfos =
- new KeyAttestationPackageInfo[packageNames.length];
+ KeyAttestationPackageInfo[] keyAttestationPackageInfos = null;
+ final long token = Binder.clearCallingIdentity();
try {
+ String[] packageNames = mPackageManager.getPackagesForUid(uid);
+ if (packageNames == null) {
+ throw new RemoteException("No packages for uid");
+ }
+ int userId = UserHandle.getUserId(uid);
+ keyAttestationPackageInfos = new KeyAttestationPackageInfo[packageNames.length];
+
for (int i = 0; i < packageNames.length; ++i) {
PackageInfo packageInfo = mPackageManager.getPackageInfoAsUser(packageNames[i],
PackageManager.GET_SIGNATURES, userId);
@@ -61,6 +67,8 @@
}
} catch (NameNotFoundException nnfe) {
throw new RemoteException(nnfe.getMessage());
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
return new KeyAttestationApplicationId(keyAttestationPackageInfos);
}
diff --git a/wifi/java/android/net/wifi/IconInfo.aidl b/wifi/java/android/net/wifi/IconInfo.aidl
deleted file mode 100644
index a7bb2ef..0000000
--- a/wifi/java/android/net/wifi/IconInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2017, 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.net.wifi;
-
-parcelable IconInfo;
diff --git a/wifi/java/android/net/wifi/IconInfo.java b/wifi/java/android/net/wifi/IconInfo.java
deleted file mode 100644
index 0eae363..0000000
--- a/wifi/java/android/net/wifi/IconInfo.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2017 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.net.wifi;
-
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.os.Parcel;
-
-import java.util.Arrays;
-import java.util.Objects;
-
-/**
- * A class representing icon information.
- */
-public final class IconInfo implements Parcelable {
- /**
- * Name of the icon file.
- */
- private final String mFilename;
-
- /**
- * Raw binary data of the icon.
- */
- private final byte[] mData;
-
- public IconInfo(String filename, byte[] data) {
- mFilename = filename;
- mData = data;
- }
-
- public IconInfo(IconInfo source) {
- if (source == null) {
- mFilename = null;
- mData = null;
- return;
- }
-
- mFilename = source.mFilename;
- if (source.mData != null) {
- mData = Arrays.copyOf(source.mData, source.mData.length);
- } else {
- mData = null;
- }
- }
-
- public String getFilename() {
- return mFilename;
- }
-
- public byte[] getData() {
- return mData;
- }
-
- @Override
- public boolean equals(Object thatObject) {
- if (this == thatObject) {
- return true;
- }
- if (!(thatObject instanceof IconInfo)) {
- return false;
- }
- IconInfo that = (IconInfo) thatObject;
- return TextUtils.equals(mFilename, that.mFilename)
- && Arrays.equals(mData, that.mData);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mFilename, mData);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mFilename);
- dest.writeByteArray(mData);
- }
-
- public static final Creator<IconInfo> CREATOR =
- new Creator<IconInfo>() {
- @Override
- public IconInfo createFromParcel(Parcel in) {
- String filename = in.readString();
- byte[] data = in.createByteArray();
- return new IconInfo(filename, data);
- }
-
- @Override
- public IconInfo[] newArray(int size) {
- return new IconInfo[size];
- }
- };
-}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 4f2881b..824c436 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -120,7 +120,8 @@
*
* Included extras:
* {@link #EXTRA_BSSID_LONG}
- * {@link #EXTRA_ICON_INFO}
+ * {@link #EXTRA_FILENAME}
+ * {@link #EXTRA_ICON}
*
* Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
*
@@ -136,12 +137,18 @@
*/
public static final String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
/**
- * Icon information.
+ * Icon data.
*
* Retrieve with {@link android.content.Intent#getParcelableExtra(String)} and cast into
- * {@link IconInfo}.
+ * {@link android.graphics.drawable.Icon}.
*/
- public static final String EXTRA_ICON_INFO = "android.net.wifi.extra.ICON_INFO";
+ public static final String EXTRA_ICON = "android.net.wifi.extra.ICON";
+ /**
+ * Name of a file.
+ *
+ * Retrieve with {@link android.content.Intent#getStringExtra(String)}.
+ */
+ public static final String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
/**
* Broadcast intent action indicating a Passpoint OSU Providers List element has been received.
@@ -984,9 +991,9 @@
/**
* Query for a Hotspot 2.0 release 2 OSU icon file. An {@link #ACTION_PASSPOINT_ICON} intent
- * will be broadcasted once the request is completed. The return value of
- * {@link IconInfo#getData} from the intent extra will indicate the result of the request.
- * A value of {@code null} will indicate a failure.
+ * will be broadcasted once the request is completed. The presence of the intent extra
+ * {@link #EXTRA_ICON} will indicate the result of the request.
+ * A missing intent extra {@link #EXTRA_ICON} will indicate a failure.
*
* @param bssid The BSSID of the AP
* @param fileName Name of the icon file (remote file) to query from the AP
diff --git a/wifi/tests/src/android/net/wifi/IconInfoTest.java b/wifi/tests/src/android/net/wifi/IconInfoTest.java
deleted file mode 100644
index 2fdb484..0000000
--- a/wifi/tests/src/android/net/wifi/IconInfoTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2017 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.net.wifi;
-
-import static org.junit.Assert.assertEquals;
-
-import android.net.wifi.IconInfo;
-import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Unit tests for {@link android.net.wifi.IconInfo}.
- */
-@SmallTest
-public class IconInfoTest {
- private static final String TEST_FILENAME = "testIcon";
- private static final byte[] TEST_DATA = new byte[] {0x12, 0x23, 0x34, 0x45, 0x56, 0x67};
-
- /**
- * Verify parcel write and read consistency for the given {@link IconInfo}
- *
- * @param writeIcon the {@link IconInfo} to write and verify
- * @throws Exception
- */
- private static void verifyParcel(IconInfo writeIcon) throws Exception {
- Parcel parcel = Parcel.obtain();
- writeIcon.writeToParcel(parcel, 0);
-
- parcel.setDataPosition(0); // Rewind data position back to the beginning for read.
- IconInfo readIcon = IconInfo.CREATOR.createFromParcel(parcel);
- assertEquals(writeIcon, readIcon);
- }
-
- /**
- * Verify parcel serialization for a {@link IconInfo} with null data.
- *
- * @throws Exception
- */
- @Test
- public void verifyParcelWithNullData() throws Exception {
- verifyParcel(new IconInfo(TEST_FILENAME, (byte[]) null));
- }
-
- /**
- * Verify parcel serialization for a {@link IconInfo} with zero length data.
- *
- * @throws Exception
- */
- @Test
- public void verifyParcelWithZeroLengthData() throws Exception {
- verifyParcel(new IconInfo(TEST_FILENAME, new byte[0]));
- }
-
- /**
- * Verify parcel serialization for a {@link IconInfo} with non-zero length data.
- *
- * @throws Exception
- */
- @Test
- public void verifyParcelWithNonZeroLengthData() throws Exception {
- verifyParcel(new IconInfo(TEST_FILENAME, TEST_DATA));
- }
-
- /**
- * Verify parcel serialization for a {@link IconInfo} with a null filename.
- *
- * @throws Exception
- */
- @Test
- public void verifyParcelWithNullFilename() throws Exception {
- verifyParcel(new IconInfo(null, TEST_DATA));
- }
-
- /**
- * Verify the copy constructor with non-null filename and data.
- *
- * @throws Exception
- */
- @Test
- public void verifyCopyConstructor() throws Exception {
- IconInfo source = new IconInfo(TEST_FILENAME, TEST_DATA);
- assertEquals(source, new IconInfo(source));
- }
-
- /**
- * Verify the copy constructor with null data.
- *
- * @throws Exception
- */
- @Test
- public void verifyCopyConstructorWithNullData() throws Exception {
- IconInfo source = new IconInfo(TEST_FILENAME, (byte[]) null);
- assertEquals(source, new IconInfo(source));
- }
-
- /**
- * Verify the copy constructor with null file name.
- *
- * @throws Exception
- */
- @Test
- public void verifyCopyConstructorWithNullFilename() throws Exception {
- IconInfo source = new IconInfo(null, TEST_DATA);
- assertEquals(source, new IconInfo(source));
- }
-}