summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt512
-rw-r--r--api/system-current.txt2
-rw-r--r--cmds/statsd/src/external/StatsCompanionServicePuller.cpp4
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp3
-rw-r--r--cmds/statsd/src/guardrail/StatsdStats.cpp59
-rw-r--r--cmds/statsd/src/guardrail/StatsdStats.h68
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.cpp12
-rw-r--r--cmds/statsd/src/stats_log.proto14
-rw-r--r--cmds/statsd/src/stats_log_util.cpp38
-rw-r--r--cmds/statsd/src/stats_log_util.h4
-rw-r--r--core/java/android/app/ActivityView.java53
-rw-r--r--core/java/android/content/rollback/PackageRollbackInfo.java69
-rw-r--r--core/java/android/content/rollback/RollbackInfo.java2
-rw-r--r--core/java/android/provider/Settings.java2
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java82
-rw-r--r--core/java/android/view/InputWindowHandle.java8
-rw-r--r--core/java/android/view/ViewRootImpl.java9
-rw-r--r--core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl2
-rw-r--r--core/java/com/android/internal/os/AppZygoteInit.java3
-rw-r--r--core/java/com/android/internal/os/WebViewZygoteInit.java13
-rw-r--r--core/java/com/android/internal/os/Zygote.java22
-rw-r--r--core/jni/android_hardware_input_InputWindowHandle.cpp6
-rw-r--r--core/proto/android/providers/settings/global.proto2
-rw-r--r--core/tests/coretests/AndroidManifest.xml8
-rw-r--r--core/tests/coretests/res/layout/accessibility_test.xml30
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java1
-rw-r--r--core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java220
-rw-r--r--core/tests/coretests/src/android/view/accessibility/AccessibilityTestActivity.java45
-rw-r--r--media/Android.bp2
-rw-r--r--media/apex/java/android/media/MediaDescription.aidl (renamed from media/java/android/media/MediaDescription.aidl)0
-rw-r--r--media/apex/java/android/media/MediaDescription.java (renamed from media/java/android/media/MediaDescription.java)23
-rw-r--r--media/apex/java/android/media/Rating.aidl (renamed from media/java/android/media/Rating.aidl)0
-rw-r--r--media/apex/java/android/media/Rating.java (renamed from media/java/android/media/Rating.java)29
-rw-r--r--packages/ExtServices/AndroidManifest.xml1
-rw-r--r--packages/SettingsLib/res/values/strings.xml4
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java5
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java16
-rw-r--r--services/core/java/com/android/server/PackageWatchdog.java18
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java8
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java14
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java55
-rw-r--r--services/core/java/com/android/server/rollback/AppDataRollbackHelper.java236
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerService.java5
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java140
-rw-r--r--services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java15
-rw-r--r--services/core/java/com/android/server/rollback/RollbackStore.java76
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java70
-rw-r--r--services/core/java/com/android/server/wm/TapExcludeRegionHolder.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskTapPointerEventListener.java15
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java55
-rw-r--r--services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java176
-rw-r--r--telephony/java/android/telephony/ServiceState.java2
-rw-r--r--tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java69
55 files changed, 1881 insertions, 462 deletions
diff --git a/api/current.txt b/api/current.txt
index 358911c76d40..fa05e56d483d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -58125,13 +58125,13 @@ package java.io {
ctor public ByteArrayOutputStream(int);
method public void reset();
method public int size();
- method public byte[] toByteArray();
+ method @NonNull public byte[] toByteArray();
method @NonNull public String toString(@NonNull String) throws java.io.UnsupportedEncodingException;
method @Deprecated @NonNull public String toString(int);
method public void write(int);
- method public void write(byte[], int, int);
+ method public void write(@NonNull byte[], int, int);
method public void writeTo(@NonNull java.io.OutputStream) throws java.io.IOException;
- field protected byte[] buf;
+ field @NonNull protected byte[] buf;
field protected int count;
}
@@ -58302,12 +58302,12 @@ package java.io {
method public boolean isHidden();
method public long lastModified();
method public long length();
- method public String[] list();
- method public String[] list(@Nullable java.io.FilenameFilter);
- method public java.io.File[] listFiles();
- method public java.io.File[] listFiles(@Nullable java.io.FilenameFilter);
- method public java.io.File[] listFiles(@Nullable java.io.FileFilter);
- method public static java.io.File[] listRoots();
+ method @Nullable public String[] list();
+ method @Nullable public String[] list(@Nullable java.io.FilenameFilter);
+ method @Nullable public java.io.File[] listFiles();
+ method @Nullable public java.io.File[] listFiles(@Nullable java.io.FilenameFilter);
+ method @Nullable public java.io.File[] listFiles(@Nullable java.io.FileFilter);
+ method @NonNull public static java.io.File[] listRoots();
method public boolean mkdir();
method public boolean mkdirs();
method public boolean renameTo(@NonNull java.io.File);
@@ -58796,8 +58796,8 @@ package java.io {
method protected void clearError();
method public void close();
method public void flush();
- method @NonNull public java.io.PrintWriter format(@NonNull String, java.lang.Object...);
- method @NonNull public java.io.PrintWriter format(@Nullable java.util.Locale, @NonNull String, java.lang.Object...);
+ method @NonNull public java.io.PrintWriter format(@NonNull String, @NonNull java.lang.Object...);
+ method @NonNull public java.io.PrintWriter format(@Nullable java.util.Locale, @NonNull String, @NonNull java.lang.Object...);
method public void print(boolean);
method public void print(char);
method public void print(int);
@@ -58807,8 +58807,8 @@ package java.io {
method public void print(char[]);
method public void print(@Nullable String);
method public void print(@Nullable Object);
- method @NonNull public java.io.PrintWriter printf(@NonNull String, java.lang.Object...);
- method @NonNull public java.io.PrintWriter printf(@Nullable java.util.Locale, @NonNull String, java.lang.Object...);
+ method @NonNull public java.io.PrintWriter printf(@NonNull String, @NonNull java.lang.Object...);
+ method @NonNull public java.io.PrintWriter printf(@Nullable java.util.Locale, @NonNull String, @NonNull java.lang.Object...);
method public void println();
method public void println(boolean);
method public void println(char);
@@ -59634,45 +59634,45 @@ package java.lang {
method @NonNull public static Class<?> forName(@NonNull String) throws java.lang.ClassNotFoundException;
method @NonNull public static Class<?> forName(@NonNull String, boolean, @Nullable ClassLoader) throws java.lang.ClassNotFoundException;
method @Nullable public <A extends java.lang.annotation.Annotation> A getAnnotation(@NonNull Class<A>);
- method public java.lang.annotation.Annotation[] getAnnotations();
+ method @NonNull public java.lang.annotation.Annotation[] getAnnotations();
method @NonNull public <A extends java.lang.annotation.Annotation> A[] getAnnotationsByType(@NonNull Class<A>);
method @Nullable public String getCanonicalName();
method @Nullable public ClassLoader getClassLoader();
- method public Class<?>[] getClasses();
+ method @NonNull public Class<?>[] getClasses();
method @Nullable public Class<?> getComponentType();
- method @NonNull public java.lang.reflect.Constructor<T> getConstructor(Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
- method public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
+ method @NonNull public java.lang.reflect.Constructor<T> getConstructor(@Nullable Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
+ method @NonNull public java.lang.reflect.Constructor<?>[] getConstructors() throws java.lang.SecurityException;
method @Nullable public <A extends java.lang.annotation.Annotation> A getDeclaredAnnotation(@NonNull Class<A>);
- method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
- method public Class<?>[] getDeclaredClasses();
- method @NonNull public java.lang.reflect.Constructor<T> getDeclaredConstructor(Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
- method public java.lang.reflect.Constructor<?>[] getDeclaredConstructors() throws java.lang.SecurityException;
+ method @NonNull public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+ method @NonNull public Class<?>[] getDeclaredClasses();
+ method @NonNull public java.lang.reflect.Constructor<T> getDeclaredConstructor(@Nullable Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
+ method @NonNull public java.lang.reflect.Constructor<?>[] getDeclaredConstructors() throws java.lang.SecurityException;
method @NonNull public java.lang.reflect.Field getDeclaredField(@NonNull String) throws java.lang.NoSuchFieldException;
- method public java.lang.reflect.Field[] getDeclaredFields();
- method @NonNull public java.lang.reflect.Method getDeclaredMethod(@NonNull String, Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
- method public java.lang.reflect.Method[] getDeclaredMethods() throws java.lang.SecurityException;
+ method @NonNull public java.lang.reflect.Field[] getDeclaredFields();
+ method @NonNull public java.lang.reflect.Method getDeclaredMethod(@NonNull String, @Nullable Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
+ method @NonNull public java.lang.reflect.Method[] getDeclaredMethods() throws java.lang.SecurityException;
method @Nullable public Class<?> getDeclaringClass();
method @Nullable public Class<?> getEnclosingClass();
method @Nullable public java.lang.reflect.Constructor<?> getEnclosingConstructor();
method @Nullable public java.lang.reflect.Method getEnclosingMethod();
- method public T[] getEnumConstants();
+ method @Nullable public T[] getEnumConstants();
method @NonNull public java.lang.reflect.Field getField(@NonNull String) throws java.lang.NoSuchFieldException;
- method public java.lang.reflect.Field[] getFields() throws java.lang.SecurityException;
- method public java.lang.reflect.Type[] getGenericInterfaces();
+ method @NonNull public java.lang.reflect.Field[] getFields() throws java.lang.SecurityException;
+ method @NonNull public java.lang.reflect.Type[] getGenericInterfaces();
method @Nullable public java.lang.reflect.Type getGenericSuperclass();
- method public Class<?>[] getInterfaces();
- method @NonNull public java.lang.reflect.Method getMethod(@NonNull String, Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
- method public java.lang.reflect.Method[] getMethods() throws java.lang.SecurityException;
+ method @NonNull public Class<?>[] getInterfaces();
+ method @NonNull public java.lang.reflect.Method getMethod(@NonNull String, @Nullable Class<?>...) throws java.lang.NoSuchMethodException, java.lang.SecurityException;
+ method @NonNull public java.lang.reflect.Method[] getMethods() throws java.lang.SecurityException;
method public int getModifiers();
method @NonNull public String getName();
method @Nullable public Package getPackage();
method @Nullable public java.security.ProtectionDomain getProtectionDomain();
method @Nullable public java.net.URL getResource(@NonNull String);
method @Nullable public java.io.InputStream getResourceAsStream(@NonNull String);
- method public Object[] getSigners();
+ method @Nullable public Object[] getSigners();
method @NonNull public String getSimpleName();
method @Nullable public Class<? super T> getSuperclass();
- method public java.lang.reflect.TypeVariable<java.lang.Class<T>>[] getTypeParameters();
+ method @NonNull public java.lang.reflect.TypeVariable<java.lang.Class<T>>[] getTypeParameters();
method public boolean isAnnotation();
method public boolean isAnonymousClass();
method public boolean isArray();
@@ -60559,8 +60559,8 @@ package java.lang {
method @NonNull public static String copyValueOf(char[]);
method public boolean endsWith(@NonNull String);
method public boolean equalsIgnoreCase(@Nullable String);
- method @NonNull public static String format(@NonNull String, java.lang.Object...);
- method @NonNull public static String format(@NonNull java.util.Locale, @NonNull String, java.lang.Object...);
+ method @NonNull public static String format(@NonNull String, @NonNull java.lang.Object...);
+ method @NonNull public static String format(@NonNull java.util.Locale, @NonNull String, @NonNull java.lang.Object...);
method @Deprecated public void getBytes(int, int, byte[], int);
method public byte[] getBytes(@NonNull String) throws java.io.UnsupportedEncodingException;
method public byte[] getBytes(@NonNull java.nio.charset.Charset);
@@ -60572,7 +60572,7 @@ package java.lang {
method public int indexOf(@NonNull String, int);
method @NonNull public String intern();
method public boolean isEmpty();
- method @NonNull public static String join(@NonNull CharSequence, java.lang.CharSequence...);
+ method @NonNull public static String join(@NonNull CharSequence, @Nullable java.lang.CharSequence...);
method @NonNull public static String join(@NonNull CharSequence, @NonNull Iterable<? extends java.lang.CharSequence>);
method public int lastIndexOf(int);
method public int lastIndexOf(int, int);
@@ -60587,8 +60587,8 @@ package java.lang {
method @NonNull public String replace(@NonNull CharSequence, @NonNull CharSequence);
method @NonNull public String replaceAll(@NonNull String, @NonNull String);
method @NonNull public String replaceFirst(@NonNull String, @NonNull String);
- method public String[] split(@NonNull String, int);
- method public String[] split(@NonNull String);
+ method @NonNull public String[] split(@NonNull String, int);
+ method @NonNull public String[] split(@NonNull String);
method public boolean startsWith(@NonNull String, int);
method public boolean startsWith(@NonNull String);
method @NonNull public CharSequence subSequence(int, int);
@@ -60789,7 +60789,7 @@ package java.lang {
method public long getId();
method @NonNull public final String getName();
method public final int getPriority();
- method public StackTraceElement[] getStackTrace();
+ method @NonNull public StackTraceElement[] getStackTrace();
method @NonNull public java.lang.Thread.State getState();
method @Nullable public final ThreadGroup getThreadGroup();
method @Nullable public java.lang.Thread.UncaughtExceptionHandler getUncaughtExceptionHandler();
@@ -60887,13 +60887,13 @@ package java.lang {
method @Nullable public Throwable getCause();
method @Nullable public String getLocalizedMessage();
method @Nullable public String getMessage();
- method public StackTraceElement[] getStackTrace();
- method public final Throwable[] getSuppressed();
+ method @NonNull public StackTraceElement[] getStackTrace();
+ method @NonNull public final Throwable[] getSuppressed();
method @NonNull public Throwable initCause(@Nullable Throwable);
method public void printStackTrace();
method public void printStackTrace(@NonNull java.io.PrintStream);
method public void printStackTrace(@NonNull java.io.PrintWriter);
- method public void setStackTrace(StackTraceElement[]);
+ method public void setStackTrace(@NonNull StackTraceElement[]);
}
public class TypeNotPresentException extends java.lang.RuntimeException {
@@ -61216,8 +61216,8 @@ package java.lang.reflect {
public class AccessibleObject implements java.lang.reflect.AnnotatedElement {
ctor protected AccessibleObject();
method @Nullable public <T extends java.lang.annotation.Annotation> T getAnnotation(@NonNull Class<T>);
- method public java.lang.annotation.Annotation[] getAnnotations();
- method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+ method @NonNull public java.lang.annotation.Annotation[] getAnnotations();
+ method @NonNull public java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public boolean isAccessible();
method public static void setAccessible(java.lang.reflect.AccessibleObject[], boolean) throws java.lang.SecurityException;
method public void setAccessible(boolean) throws java.lang.SecurityException;
@@ -61225,10 +61225,10 @@ package java.lang.reflect {
public interface AnnotatedElement {
method @Nullable public <T extends java.lang.annotation.Annotation> T getAnnotation(@NonNull Class<T>);
- method public java.lang.annotation.Annotation[] getAnnotations();
+ method @NonNull public java.lang.annotation.Annotation[] getAnnotations();
method public default <T extends java.lang.annotation.Annotation> T[] getAnnotationsByType(@NonNull Class<T>);
method @Nullable public default <T extends java.lang.annotation.Annotation> T getDeclaredAnnotation(@NonNull Class<T>);
- method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+ method @NonNull public java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public default <T extends java.lang.annotation.Annotation> T[] getDeclaredAnnotationsByType(@NonNull Class<T>);
method public default boolean isAnnotationPresent(@NonNull Class<? extends java.lang.annotation.Annotation>);
}
@@ -61263,20 +61263,20 @@ package java.lang.reflect {
method public int getModifiers();
method @NonNull public String getName();
method public java.lang.annotation.Annotation[][] getParameterAnnotations();
- method public Class<?>[] getParameterTypes();
+ method @NonNull public Class<?>[] getParameterTypes();
method public java.lang.reflect.TypeVariable<java.lang.reflect.Constructor<T>>[] getTypeParameters();
method @NonNull public T newInstance(java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException;
method @NonNull public String toGenericString();
}
public abstract class Executable extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
- method public abstract Class<?>[] getExceptionTypes();
- method public java.lang.reflect.Type[] getGenericExceptionTypes();
- method public java.lang.reflect.Type[] getGenericParameterTypes();
- method public abstract java.lang.annotation.Annotation[][] getParameterAnnotations();
+ method @NonNull public abstract Class<?>[] getExceptionTypes();
+ method @NonNull public java.lang.reflect.Type[] getGenericExceptionTypes();
+ method @NonNull public java.lang.reflect.Type[] getGenericParameterTypes();
+ method @NonNull public abstract java.lang.annotation.Annotation[][] getParameterAnnotations();
method public int getParameterCount();
- method public abstract Class<?>[] getParameterTypes();
- method public java.lang.reflect.Parameter[] getParameters();
+ method @NonNull public abstract Class<?>[] getParameterTypes();
+ method @NonNull public java.lang.reflect.Parameter[] getParameters();
method public final boolean isAnnotationPresent(@NonNull Class<? extends java.lang.annotation.Annotation>);
method public boolean isSynthetic();
method public boolean isVarArgs();
@@ -61365,7 +61365,7 @@ package java.lang.reflect {
method @NonNull public Class<?>[] getParameterTypes();
method @NonNull public Class<?> getReturnType();
method @NonNull public java.lang.reflect.TypeVariable<java.lang.reflect.Method>[] getTypeParameters();
- method @Nullable public Object invoke(@Nullable Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
+ method @Nullable public Object invoke(@Nullable Object, @Nullable java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
method public boolean isBridge();
method public boolean isDefault();
method @NonNull public String toGenericString();
@@ -61408,8 +61408,8 @@ package java.lang.reflect {
public final class Parameter implements java.lang.reflect.AnnotatedElement {
method @Nullable public <T extends java.lang.annotation.Annotation> T getAnnotation(@NonNull Class<T>);
- method public java.lang.annotation.Annotation[] getAnnotations();
- method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
+ method @NonNull public java.lang.annotation.Annotation[] getAnnotations();
+ method @NonNull public java.lang.annotation.Annotation[] getDeclaredAnnotations();
method @NonNull public java.lang.reflect.Executable getDeclaringExecutable();
method public int getModifiers();
method @NonNull public String getName();
@@ -61422,7 +61422,7 @@ package java.lang.reflect {
}
public interface ParameterizedType extends java.lang.reflect.Type {
- method public java.lang.reflect.Type[] getActualTypeArguments();
+ method @NonNull public java.lang.reflect.Type[] getActualTypeArguments();
method @Nullable public java.lang.reflect.Type getOwnerType();
method @NonNull public java.lang.reflect.Type getRawType();
}
@@ -61430,9 +61430,9 @@ package java.lang.reflect {
public class Proxy implements java.io.Serializable {
ctor protected Proxy(@NonNull java.lang.reflect.InvocationHandler);
method @NonNull public static java.lang.reflect.InvocationHandler getInvocationHandler(@NonNull Object) throws java.lang.IllegalArgumentException;
- method @NonNull public static Class<?> getProxyClass(@Nullable ClassLoader, Class<?>...) throws java.lang.IllegalArgumentException;
+ method @NonNull public static Class<?> getProxyClass(@Nullable ClassLoader, @NonNull Class<?>...) throws java.lang.IllegalArgumentException;
method public static boolean isProxyClass(@NonNull Class<?>);
- method @NonNull public static Object newProxyInstance(@Nullable ClassLoader, Class<?>[], @NonNull java.lang.reflect.InvocationHandler) throws java.lang.IllegalArgumentException;
+ method @NonNull public static Object newProxyInstance(@Nullable ClassLoader, @NonNull Class<?>[], @NonNull java.lang.reflect.InvocationHandler) throws java.lang.IllegalArgumentException;
field protected java.lang.reflect.InvocationHandler h;
}
@@ -61446,7 +61446,7 @@ package java.lang.reflect {
}
public interface TypeVariable<D extends java.lang.reflect.GenericDeclaration> extends java.lang.reflect.Type {
- method public java.lang.reflect.Type[] getBounds();
+ method @NonNull public java.lang.reflect.Type[] getBounds();
method @NonNull public D getGenericDeclaration();
method @NonNull public String getName();
}
@@ -61458,8 +61458,8 @@ package java.lang.reflect {
}
public interface WildcardType extends java.lang.reflect.Type {
- method public java.lang.reflect.Type[] getLowerBounds();
- method public java.lang.reflect.Type[] getUpperBounds();
+ method @NonNull public java.lang.reflect.Type[] getLowerBounds();
+ method @NonNull public java.lang.reflect.Type[] getUpperBounds();
}
}
@@ -62503,7 +62503,7 @@ package java.nio {
public abstract class ByteBuffer extends java.nio.Buffer implements java.lang.Comparable<java.nio.ByteBuffer> {
method @NonNull public static java.nio.ByteBuffer allocate(int);
method @NonNull public static java.nio.ByteBuffer allocateDirect(int);
- method public final byte[] array();
+ method @NonNull public final byte[] array();
method public final int arrayOffset();
method @NonNull public abstract java.nio.CharBuffer asCharBuffer();
method @NonNull public abstract java.nio.DoubleBuffer asDoubleBuffer();
@@ -62517,8 +62517,8 @@ package java.nio {
method @NonNull public abstract java.nio.ByteBuffer duplicate();
method public abstract byte get();
method public abstract byte get(int);
- method @NonNull public java.nio.ByteBuffer get(byte[], int, int);
- method @NonNull public java.nio.ByteBuffer get(byte[]);
+ method @NonNull public java.nio.ByteBuffer get(@NonNull byte[], int, int);
+ method @NonNull public java.nio.ByteBuffer get(@NonNull byte[]);
method public abstract char getChar();
method public abstract char getChar(int);
method public abstract double getDouble();
@@ -62537,8 +62537,8 @@ package java.nio {
method @NonNull public abstract java.nio.ByteBuffer put(byte);
method @NonNull public abstract java.nio.ByteBuffer put(int, byte);
method @NonNull public java.nio.ByteBuffer put(@NonNull java.nio.ByteBuffer);
- method @NonNull public java.nio.ByteBuffer put(byte[], int, int);
- method @NonNull public final java.nio.ByteBuffer put(byte[]);
+ method @NonNull public java.nio.ByteBuffer put(@NonNull byte[], int, int);
+ method @NonNull public final java.nio.ByteBuffer put(@NonNull byte[]);
method @NonNull public abstract java.nio.ByteBuffer putChar(char);
method @NonNull public abstract java.nio.ByteBuffer putChar(int, char);
method @NonNull public abstract java.nio.ByteBuffer putDouble(double);
@@ -62552,8 +62552,8 @@ package java.nio {
method @NonNull public abstract java.nio.ByteBuffer putShort(short);
method @NonNull public abstract java.nio.ByteBuffer putShort(int, short);
method @NonNull public abstract java.nio.ByteBuffer slice();
- method @NonNull public static java.nio.ByteBuffer wrap(byte[], int, int);
- method @NonNull public static java.nio.ByteBuffer wrap(byte[]);
+ method @NonNull public static java.nio.ByteBuffer wrap(@NonNull byte[], int, int);
+ method @NonNull public static java.nio.ByteBuffer wrap(@NonNull byte[]);
}
public final class ByteOrder {
@@ -64386,20 +64386,20 @@ package java.security {
public abstract class MessageDigest extends java.security.MessageDigestSpi {
ctor protected MessageDigest(@NonNull String);
- method public byte[] digest();
- method public int digest(byte[], int, int) throws java.security.DigestException;
- method public byte[] digest(byte[]);
+ method @NonNull public byte[] digest();
+ method public int digest(@NonNull byte[], int, int) throws java.security.DigestException;
+ method @NonNull public byte[] digest(@NonNull byte[]);
method @NonNull public final String getAlgorithm();
method public final int getDigestLength();
method @NonNull public static java.security.MessageDigest getInstance(@NonNull String) throws java.security.NoSuchAlgorithmException;
method @NonNull public static java.security.MessageDigest getInstance(@NonNull String, @NonNull String) throws java.security.NoSuchAlgorithmException, java.security.NoSuchProviderException;
method @NonNull public static java.security.MessageDigest getInstance(@NonNull String, @NonNull java.security.Provider) throws java.security.NoSuchAlgorithmException;
method @NonNull public final java.security.Provider getProvider();
- method public static boolean isEqual(byte[], byte[]);
+ method public static boolean isEqual(@Nullable byte[], @Nullable byte[]);
method public void reset();
method public void update(byte);
- method public void update(byte[], int, int);
- method public void update(byte[]);
+ method public void update(@NonNull byte[], int, int);
+ method public void update(@NonNull byte[]);
method public final void update(@NonNull java.nio.ByteBuffer);
}
@@ -67006,7 +67006,7 @@ package java.text {
method @NonNull public final StringBuffer format(@NonNull Object, @NonNull StringBuffer, @NonNull java.text.FieldPosition);
method @NonNull public abstract StringBuffer format(@NonNull java.util.Date, @NonNull StringBuffer, @NonNull java.text.FieldPosition);
method @NonNull public final String format(@NonNull java.util.Date);
- method public static java.util.Locale[] getAvailableLocales();
+ method @NonNull public static java.util.Locale[] getAvailableLocales();
method @NonNull public java.util.Calendar getCalendar();
method @NonNull public static final java.text.DateFormat getDateInstance();
method @NonNull public static final java.text.DateFormat getDateInstance(int);
@@ -67246,7 +67246,7 @@ package java.text {
method @NonNull public final String format(long);
method @NonNull public abstract StringBuffer format(double, @NonNull StringBuffer, @NonNull java.text.FieldPosition);
method @NonNull public abstract StringBuffer format(long, @NonNull StringBuffer, @NonNull java.text.FieldPosition);
- method public static java.util.Locale[] getAvailableLocales();
+ method @NonNull public static java.util.Locale[] getAvailableLocales();
method @Nullable public java.util.Currency getCurrency();
method @NonNull public static final java.text.NumberFormat getCurrencyInstance();
method @NonNull public static java.text.NumberFormat getCurrencyInstance(@NonNull java.util.Locale);
@@ -68900,8 +68900,8 @@ package java.util {
method public boolean remove(@Nullable Object);
method public boolean removeAll(@NonNull java.util.Collection<?>);
method public boolean retainAll(@NonNull java.util.Collection<?>);
- method public Object[] toArray();
- method public <T> T[] toArray(T[]);
+ method @NonNull public Object[] toArray();
+ method @NonNull public <T> T[] toArray(@NonNull T[]);
}
public abstract class AbstractList<E> extends java.util.AbstractCollection<E> implements java.util.List<E> {
@@ -69010,161 +69010,161 @@ package java.util {
}
public class Arrays {
- method @NonNull @java.lang.SafeVarargs public static <T> java.util.List<T> asList(T...);
- method public static int binarySearch(long[], long);
- method public static int binarySearch(long[], int, int, long);
- method public static int binarySearch(int[], int);
- method public static int binarySearch(int[], int, int, int);
- method public static int binarySearch(short[], short);
- method public static int binarySearch(short[], int, int, short);
- method public static int binarySearch(char[], char);
- method public static int binarySearch(char[], int, int, char);
- method public static int binarySearch(byte[], byte);
- method public static int binarySearch(byte[], int, int, byte);
- method public static int binarySearch(double[], double);
- method public static int binarySearch(double[], int, int, double);
- method public static int binarySearch(float[], float);
- method public static int binarySearch(float[], int, int, float);
- method public static int binarySearch(Object[], @NonNull Object);
- method public static int binarySearch(Object[], int, int, @NonNull Object);
- method public static <T> int binarySearch(T[], T, @Nullable java.util.Comparator<? super T>);
- method public static <T> int binarySearch(T[], int, int, T, @Nullable java.util.Comparator<? super T>);
- method public static <T> T[] copyOf(T[], int);
- method public static <T, U> T[] copyOf(U[], int, @NonNull Class<? extends T[]>);
- method public static byte[] copyOf(byte[], int);
- method public static short[] copyOf(short[], int);
- method public static int[] copyOf(int[], int);
- method public static long[] copyOf(long[], int);
- method public static char[] copyOf(char[], int);
- method public static float[] copyOf(float[], int);
- method public static double[] copyOf(double[], int);
- method public static boolean[] copyOf(boolean[], int);
- method public static <T> T[] copyOfRange(T[], int, int);
- method public static <T, U> T[] copyOfRange(U[], int, int, @NonNull Class<? extends T[]>);
- method public static byte[] copyOfRange(byte[], int, int);
- method public static short[] copyOfRange(short[], int, int);
- method public static int[] copyOfRange(int[], int, int);
- method public static long[] copyOfRange(long[], int, int);
- method public static char[] copyOfRange(char[], int, int);
- method public static float[] copyOfRange(float[], int, int);
- method public static double[] copyOfRange(double[], int, int);
- method public static boolean[] copyOfRange(boolean[], int, int);
- method public static boolean deepEquals(Object[], Object[]);
- method public static int deepHashCode(Object[]);
- method @NonNull public static String deepToString(Object[]);
- method public static boolean equals(long[], long[]);
- method public static boolean equals(int[], int[]);
- method public static boolean equals(short[], short[]);
- method public static boolean equals(char[], char[]);
- method public static boolean equals(byte[], byte[]);
- method public static boolean equals(boolean[], boolean[]);
- method public static boolean equals(double[], double[]);
- method public static boolean equals(float[], float[]);
- method public static boolean equals(Object[], Object[]);
- method public static void fill(long[], long);
- method public static void fill(long[], int, int, long);
- method public static void fill(int[], int);
- method public static void fill(int[], int, int, int);
- method public static void fill(short[], short);
- method public static void fill(short[], int, int, short);
- method public static void fill(char[], char);
- method public static void fill(char[], int, int, char);
- method public static void fill(byte[], byte);
- method public static void fill(byte[], int, int, byte);
- method public static void fill(boolean[], boolean);
- method public static void fill(boolean[], int, int, boolean);
- method public static void fill(double[], double);
- method public static void fill(double[], int, int, double);
- method public static void fill(float[], float);
- method public static void fill(float[], int, int, float);
- method public static void fill(Object[], @Nullable Object);
- method public static void fill(Object[], int, int, @Nullable Object);
- method public static int hashCode(long[]);
- method public static int hashCode(int[]);
- method public static int hashCode(short[]);
- method public static int hashCode(char[]);
- method public static int hashCode(byte[]);
- method public static int hashCode(boolean[]);
- method public static int hashCode(float[]);
- method public static int hashCode(double[]);
- method public static int hashCode(Object[]);
- method public static <T> void parallelPrefix(T[], @NonNull java.util.function.BinaryOperator<T>);
- method public static <T> void parallelPrefix(T[], int, int, @NonNull java.util.function.BinaryOperator<T>);
- method public static void parallelPrefix(long[], @NonNull java.util.function.LongBinaryOperator);
- method public static void parallelPrefix(long[], int, int, @NonNull java.util.function.LongBinaryOperator);
- method public static void parallelPrefix(double[], @NonNull java.util.function.DoubleBinaryOperator);
- method public static void parallelPrefix(double[], int, int, @NonNull java.util.function.DoubleBinaryOperator);
- method public static void parallelPrefix(int[], @NonNull java.util.function.IntBinaryOperator);
- method public static void parallelPrefix(int[], int, int, @NonNull java.util.function.IntBinaryOperator);
- method public static <T> void parallelSetAll(T[], @NonNull java.util.function.IntFunction<? extends T>);
- method public static void parallelSetAll(int[], @NonNull java.util.function.IntUnaryOperator);
- method public static void parallelSetAll(long[], @NonNull java.util.function.IntToLongFunction);
- method public static void parallelSetAll(double[], @NonNull java.util.function.IntToDoubleFunction);
- method public static void parallelSort(byte[]);
- method public static void parallelSort(byte[], int, int);
- method public static void parallelSort(char[]);
- method public static void parallelSort(char[], int, int);
- method public static void parallelSort(short[]);
- method public static void parallelSort(short[], int, int);
- method public static void parallelSort(int[]);
- method public static void parallelSort(int[], int, int);
- method public static void parallelSort(long[]);
- method public static void parallelSort(long[], int, int);
- method public static void parallelSort(float[]);
- method public static void parallelSort(float[], int, int);
- method public static void parallelSort(double[]);
- method public static void parallelSort(double[], int, int);
- method public static <T extends java.lang.Comparable<? super T>> void parallelSort(T[]);
- method public static <T extends java.lang.Comparable<? super T>> void parallelSort(T[], int, int);
- method public static <T> void parallelSort(T[], @Nullable java.util.Comparator<? super T>);
- method public static <T> void parallelSort(T[], int, int, @Nullable java.util.Comparator<? super T>);
- method public static <T> void setAll(T[], @NonNull java.util.function.IntFunction<? extends T>);
- method public static void setAll(int[], @NonNull java.util.function.IntUnaryOperator);
- method public static void setAll(long[], @NonNull java.util.function.IntToLongFunction);
- method public static void setAll(double[], @NonNull java.util.function.IntToDoubleFunction);
- method public static void sort(int[]);
- method public static void sort(int[], int, int);
- method public static void sort(long[]);
- method public static void sort(long[], int, int);
- method public static void sort(short[]);
- method public static void sort(short[], int, int);
- method public static void sort(char[]);
- method public static void sort(char[], int, int);
- method public static void sort(byte[]);
- method public static void sort(byte[], int, int);
- method public static void sort(float[]);
- method public static void sort(float[], int, int);
- method public static void sort(double[]);
- method public static void sort(double[], int, int);
- method public static void sort(Object[]);
- method public static void sort(Object[], int, int);
- method public static <T> void sort(T[], @Nullable java.util.Comparator<? super T>);
- method public static <T> void sort(T[], int, int, @Nullable java.util.Comparator<? super T>);
- method @NonNull public static <T> java.util.Spliterator<T> spliterator(T[]);
- method @NonNull public static <T> java.util.Spliterator<T> spliterator(T[], int, int);
- method @NonNull public static java.util.Spliterator.OfInt spliterator(int[]);
- method @NonNull public static java.util.Spliterator.OfInt spliterator(int[], int, int);
- method @NonNull public static java.util.Spliterator.OfLong spliterator(long[]);
- method @NonNull public static java.util.Spliterator.OfLong spliterator(long[], int, int);
- method @NonNull public static java.util.Spliterator.OfDouble spliterator(double[]);
- method @NonNull public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
- method @NonNull public static <T> java.util.stream.Stream<T> stream(T[]);
- method @NonNull public static <T> java.util.stream.Stream<T> stream(T[], int, int);
- method @NonNull public static java.util.stream.IntStream stream(int[]);
- method @NonNull public static java.util.stream.IntStream stream(int[], int, int);
- method @NonNull public static java.util.stream.LongStream stream(long[]);
- method @NonNull public static java.util.stream.LongStream stream(long[], int, int);
- method @NonNull public static java.util.stream.DoubleStream stream(double[]);
- method @NonNull public static java.util.stream.DoubleStream stream(double[], int, int);
- method @NonNull public static String toString(long[]);
- method @NonNull public static String toString(int[]);
- method @NonNull public static String toString(short[]);
- method @NonNull public static String toString(char[]);
- method @NonNull public static String toString(byte[]);
- method @NonNull public static String toString(boolean[]);
- method @NonNull public static String toString(float[]);
- method @NonNull public static String toString(double[]);
- method @NonNull public static String toString(Object[]);
+ method @NonNull @java.lang.SafeVarargs public static <T> java.util.List<T> asList(@NonNull T...);
+ method public static int binarySearch(@NonNull long[], long);
+ method public static int binarySearch(@NonNull long[], int, int, long);
+ method public static int binarySearch(@NonNull int[], int);
+ method public static int binarySearch(@NonNull int[], int, int, int);
+ method public static int binarySearch(@NonNull short[], short);
+ method public static int binarySearch(@NonNull short[], int, int, short);
+ method public static int binarySearch(@NonNull char[], char);
+ method public static int binarySearch(@NonNull char[], int, int, char);
+ method public static int binarySearch(@NonNull byte[], byte);
+ method public static int binarySearch(@NonNull byte[], int, int, byte);
+ method public static int binarySearch(@NonNull double[], double);
+ method public static int binarySearch(@NonNull double[], int, int, double);
+ method public static int binarySearch(@NonNull float[], float);
+ method public static int binarySearch(@NonNull float[], int, int, float);
+ method public static int binarySearch(@NonNull Object[], @NonNull Object);
+ method public static int binarySearch(@NonNull Object[], int, int, @NonNull Object);
+ method public static <T> int binarySearch(@NonNull T[], T, @Nullable java.util.Comparator<? super T>);
+ method public static <T> int binarySearch(@NonNull T[], int, int, T, @Nullable java.util.Comparator<? super T>);
+ method @NonNull public static <T> T[] copyOf(@NonNull T[], int);
+ method @NonNull public static <T, U> T[] copyOf(@NonNull U[], int, @NonNull Class<? extends T[]>);
+ method @NonNull public static byte[] copyOf(@NonNull byte[], int);
+ method @NonNull public static short[] copyOf(@NonNull short[], int);
+ method @NonNull public static int[] copyOf(@NonNull int[], int);
+ method @NonNull public static long[] copyOf(@NonNull long[], int);
+ method @NonNull public static char[] copyOf(@NonNull char[], int);
+ method @NonNull public static float[] copyOf(@NonNull float[], int);
+ method @NonNull public static double[] copyOf(@NonNull double[], int);
+ method @NonNull public static boolean[] copyOf(@NonNull boolean[], int);
+ method @NonNull public static <T> T[] copyOfRange(@NonNull T[], int, int);
+ method @NonNull public static <T, U> T[] copyOfRange(@NonNull U[], int, int, @NonNull Class<? extends T[]>);
+ method @NonNull public static byte[] copyOfRange(@NonNull byte[], int, int);
+ method @NonNull public static short[] copyOfRange(@NonNull short[], int, int);
+ method @NonNull public static int[] copyOfRange(@NonNull int[], int, int);
+ method @NonNull public static long[] copyOfRange(@NonNull long[], int, int);
+ method @NonNull public static char[] copyOfRange(@NonNull char[], int, int);
+ method @NonNull public static float[] copyOfRange(@NonNull float[], int, int);
+ method @NonNull public static double[] copyOfRange(@NonNull double[], int, int);
+ method @NonNull public static boolean[] copyOfRange(@NonNull boolean[], int, int);
+ method public static boolean deepEquals(@Nullable Object[], @Nullable Object[]);
+ method public static int deepHashCode(@Nullable Object[]);
+ method @NonNull public static String deepToString(@Nullable Object[]);
+ method public static boolean equals(@Nullable long[], @Nullable long[]);
+ method public static boolean equals(@Nullable int[], @Nullable int[]);
+ method public static boolean equals(@Nullable short[], @Nullable short[]);
+ method public static boolean equals(@Nullable char[], @Nullable char[]);
+ method public static boolean equals(@Nullable byte[], @Nullable byte[]);
+ method public static boolean equals(@Nullable boolean[], @Nullable boolean[]);
+ method public static boolean equals(@Nullable double[], @Nullable double[]);
+ method public static boolean equals(@Nullable float[], @Nullable float[]);
+ method public static boolean equals(@Nullable Object[], @Nullable Object[]);
+ method public static void fill(@NonNull long[], long);
+ method public static void fill(@NonNull long[], int, int, long);
+ method public static void fill(@NonNull int[], int);
+ method public static void fill(@NonNull int[], int, int, int);
+ method public static void fill(@NonNull short[], short);
+ method public static void fill(@NonNull short[], int, int, short);
+ method public static void fill(@NonNull char[], char);
+ method public static void fill(@NonNull char[], int, int, char);
+ method public static void fill(@NonNull byte[], byte);
+ method public static void fill(@NonNull byte[], int, int, byte);
+ method public static void fill(@NonNull boolean[], boolean);
+ method public static void fill(@NonNull boolean[], int, int, boolean);
+ method public static void fill(@NonNull double[], double);
+ method public static void fill(@NonNull double[], int, int, double);
+ method public static void fill(@NonNull float[], float);
+ method public static void fill(@NonNull float[], int, int, float);
+ method public static void fill(@NonNull Object[], @Nullable Object);
+ method public static void fill(@NonNull Object[], int, int, @Nullable Object);
+ method public static int hashCode(@Nullable long[]);
+ method public static int hashCode(@Nullable int[]);
+ method public static int hashCode(@Nullable short[]);
+ method public static int hashCode(@Nullable char[]);
+ method public static int hashCode(@Nullable byte[]);
+ method public static int hashCode(@Nullable boolean[]);
+ method public static int hashCode(@Nullable float[]);
+ method public static int hashCode(@Nullable double[]);
+ method public static int hashCode(@Nullable Object[]);
+ method public static <T> void parallelPrefix(@NonNull T[], @NonNull java.util.function.BinaryOperator<T>);
+ method public static <T> void parallelPrefix(@NonNull T[], int, int, @NonNull java.util.function.BinaryOperator<T>);
+ method public static void parallelPrefix(@NonNull long[], @NonNull java.util.function.LongBinaryOperator);
+ method public static void parallelPrefix(@NonNull long[], int, int, @NonNull java.util.function.LongBinaryOperator);
+ method public static void parallelPrefix(@NonNull double[], @NonNull java.util.function.DoubleBinaryOperator);
+ method public static void parallelPrefix(@NonNull double[], int, int, @NonNull java.util.function.DoubleBinaryOperator);
+ method public static void parallelPrefix(@NonNull int[], @NonNull java.util.function.IntBinaryOperator);
+ method public static void parallelPrefix(@NonNull int[], int, int, @NonNull java.util.function.IntBinaryOperator);
+ method public static <T> void parallelSetAll(@NonNull T[], @NonNull java.util.function.IntFunction<? extends T>);
+ method public static void parallelSetAll(@NonNull int[], @NonNull java.util.function.IntUnaryOperator);
+ method public static void parallelSetAll(@NonNull long[], @NonNull java.util.function.IntToLongFunction);
+ method public static void parallelSetAll(@NonNull double[], @NonNull java.util.function.IntToDoubleFunction);
+ method public static void parallelSort(@NonNull byte[]);
+ method public static void parallelSort(@NonNull byte[], int, int);
+ method public static void parallelSort(@NonNull char[]);
+ method public static void parallelSort(@NonNull char[], int, int);
+ method public static void parallelSort(@NonNull short[]);
+ method public static void parallelSort(@NonNull short[], int, int);
+ method public static void parallelSort(@NonNull int[]);
+ method public static void parallelSort(@NonNull int[], int, int);
+ method public static void parallelSort(@NonNull long[]);
+ method public static void parallelSort(@NonNull long[], int, int);
+ method public static void parallelSort(@NonNull float[]);
+ method public static void parallelSort(@NonNull float[], int, int);
+ method public static void parallelSort(@NonNull double[]);
+ method public static void parallelSort(@NonNull double[], int, int);
+ method public static <T extends java.lang.Comparable<? super T>> void parallelSort(@NonNull T[]);
+ method public static <T extends java.lang.Comparable<? super T>> void parallelSort(@NonNull T[], int, int);
+ method public static <T> void parallelSort(@NonNull T[], @Nullable java.util.Comparator<? super T>);
+ method public static <T> void parallelSort(@NonNull T[], int, int, @Nullable java.util.Comparator<? super T>);
+ method public static <T> void setAll(@NonNull T[], @NonNull java.util.function.IntFunction<? extends T>);
+ method public static void setAll(@NonNull int[], @NonNull java.util.function.IntUnaryOperator);
+ method public static void setAll(@NonNull long[], @NonNull java.util.function.IntToLongFunction);
+ method public static void setAll(@NonNull double[], @NonNull java.util.function.IntToDoubleFunction);
+ method public static void sort(@NonNull int[]);
+ method public static void sort(@NonNull int[], int, int);
+ method public static void sort(@NonNull long[]);
+ method public static void sort(@NonNull long[], int, int);
+ method public static void sort(@NonNull short[]);
+ method public static void sort(@NonNull short[], int, int);
+ method public static void sort(@NonNull char[]);
+ method public static void sort(@NonNull char[], int, int);
+ method public static void sort(@NonNull byte[]);
+ method public static void sort(@NonNull byte[], int, int);
+ method public static void sort(@NonNull float[]);
+ method public static void sort(@NonNull float[], int, int);
+ method public static void sort(@NonNull double[]);
+ method public static void sort(@NonNull double[], int, int);
+ method public static void sort(@NonNull Object[]);
+ method public static void sort(@NonNull Object[], int, int);
+ method public static <T> void sort(@NonNull T[], @Nullable java.util.Comparator<? super T>);
+ method public static <T> void sort(@NonNull T[], int, int, @Nullable java.util.Comparator<? super T>);
+ method @NonNull public static <T> java.util.Spliterator<T> spliterator(@NonNull T[]);
+ method @NonNull public static <T> java.util.Spliterator<T> spliterator(@NonNull T[], int, int);
+ method @NonNull public static java.util.Spliterator.OfInt spliterator(@NonNull int[]);
+ method @NonNull public static java.util.Spliterator.OfInt spliterator(@NonNull int[], int, int);
+ method @NonNull public static java.util.Spliterator.OfLong spliterator(@NonNull long[]);
+ method @NonNull public static java.util.Spliterator.OfLong spliterator(@NonNull long[], int, int);
+ method @NonNull public static java.util.Spliterator.OfDouble spliterator(@NonNull double[]);
+ method @NonNull public static java.util.Spliterator.OfDouble spliterator(@NonNull double[], int, int);
+ method @NonNull public static <T> java.util.stream.Stream<T> stream(@NonNull T[]);
+ method @NonNull public static <T> java.util.stream.Stream<T> stream(@NonNull T[], int, int);
+ method @NonNull public static java.util.stream.IntStream stream(@NonNull int[]);
+ method @NonNull public static java.util.stream.IntStream stream(@NonNull int[], int, int);
+ method @NonNull public static java.util.stream.LongStream stream(@NonNull long[]);
+ method @NonNull public static java.util.stream.LongStream stream(@NonNull long[], int, int);
+ method @NonNull public static java.util.stream.DoubleStream stream(@NonNull double[]);
+ method @NonNull public static java.util.stream.DoubleStream stream(@NonNull double[], int, int);
+ method @NonNull public static String toString(@Nullable long[]);
+ method @NonNull public static String toString(@Nullable int[]);
+ method @NonNull public static String toString(@Nullable short[]);
+ method @NonNull public static String toString(@Nullable char[]);
+ method @NonNull public static String toString(@Nullable byte[]);
+ method @NonNull public static String toString(@Nullable boolean[]);
+ method @NonNull public static String toString(@Nullable float[]);
+ method @NonNull public static String toString(@Nullable double[]);
+ method @NonNull public static String toString(@Nullable Object[]);
}
public class Base64 {
@@ -69248,7 +69248,7 @@ package java.util {
method public int getActualMaximum(int);
method public int getActualMinimum(int);
method @NonNull public static java.util.Set<java.lang.String> getAvailableCalendarTypes();
- method public static java.util.Locale[] getAvailableLocales();
+ method @NonNull public static java.util.Locale[] getAvailableLocales();
method @NonNull public String getCalendarType();
method @Nullable public String getDisplayName(int, int, @NonNull java.util.Locale);
method @Nullable public java.util.Map<java.lang.String,java.lang.Integer> getDisplayNames(int, int, @NonNull java.util.Locale);
@@ -69336,8 +69336,8 @@ package java.util {
field public static final int YEAR = 1; // 0x1
field public static final int ZONE_OFFSET = 15; // 0xf
field protected boolean areFieldsSet;
- field protected int[] fields;
- field protected boolean[] isSet;
+ field @NonNull protected int[] fields;
+ field @NonNull protected boolean[] isSet;
field protected boolean isTimeSet;
field protected long time;
}
@@ -69348,7 +69348,7 @@ package java.util {
method @NonNull public java.util.Calendar.Builder set(int, int);
method @NonNull public java.util.Calendar.Builder setCalendarType(@NonNull String);
method @NonNull public java.util.Calendar.Builder setDate(int, int, int);
- method @NonNull public java.util.Calendar.Builder setFields(int...);
+ method @NonNull public java.util.Calendar.Builder setFields(@NonNull int...);
method @NonNull public java.util.Calendar.Builder setInstant(long);
method @NonNull public java.util.Calendar.Builder setInstant(@NonNull java.util.Date);
method @NonNull public java.util.Calendar.Builder setLenient(boolean);
@@ -69378,12 +69378,12 @@ package java.util {
method public int size();
method @NonNull public default java.util.Spliterator<E> spliterator();
method @NonNull public default java.util.stream.Stream<E> stream();
- method public Object[] toArray();
- method public <T> T[] toArray(T[]);
+ method @NonNull public Object[] toArray();
+ method @NonNull public <T> T[] toArray(@NonNull T[]);
}
public class Collections {
- method @java.lang.SafeVarargs public static <T> boolean addAll(@NonNull java.util.Collection<? super T>, T...);
+ method @java.lang.SafeVarargs public static <T> boolean addAll(@NonNull java.util.Collection<? super T>, @NonNull T...);
method @NonNull public static <T> java.util.Queue<T> asLifoQueue(@NonNull java.util.Deque<T>);
method public static <T> int binarySearch(@NonNull java.util.List<? extends java.lang.Comparable<? super T>>, @NonNull T);
method public static <T> int binarySearch(@NonNull java.util.List<? extends T>, T, @Nullable java.util.Comparator<? super T>);
@@ -69901,7 +69901,7 @@ package java.util {
method @NonNull public static java.util.List<java.lang.String> filterTags(@NonNull java.util.List<java.util.Locale.LanguageRange>, @NonNull java.util.Collection<java.lang.String>, @NonNull java.util.Locale.FilteringMode);
method @NonNull public static java.util.List<java.lang.String> filterTags(@NonNull java.util.List<java.util.Locale.LanguageRange>, @NonNull java.util.Collection<java.lang.String>);
method @NonNull public static java.util.Locale forLanguageTag(@NonNull String);
- method public static java.util.Locale[] getAvailableLocales();
+ method @NonNull public static java.util.Locale[] getAvailableLocales();
method @NonNull public String getCountry();
method @NonNull public static java.util.Locale getDefault();
method @NonNull public static java.util.Locale getDefault(@NonNull java.util.Locale.Category);
@@ -69919,8 +69919,8 @@ package java.util {
method @NonNull public java.util.Set<java.lang.Character> getExtensionKeys();
method @NonNull public String getISO3Country() throws java.util.MissingResourceException;
method @NonNull public String getISO3Language() throws java.util.MissingResourceException;
- method public static String[] getISOCountries();
- method public static String[] getISOLanguages();
+ method @NonNull public static String[] getISOCountries();
+ method @NonNull public static String[] getISOLanguages();
method @NonNull public String getLanguage();
method @NonNull public String getScript();
method @NonNull public java.util.Set<java.lang.String> getUnicodeLocaleAttributes();
@@ -70114,7 +70114,7 @@ package java.util {
method public static <T> int compare(T, T, @NonNull java.util.Comparator<? super T>);
method public static boolean deepEquals(@Nullable Object, @Nullable Object);
method public static boolean equals(@Nullable Object, @Nullable Object);
- method public static int hash(java.lang.Object...);
+ method public static int hash(@Nullable java.lang.Object...);
method public static int hashCode(@Nullable Object);
method public static boolean isNull(@Nullable Object);
method public static boolean nonNull(@Nullable Object);
@@ -70779,7 +70779,7 @@ package java.util {
method public void addElement(E);
method public int capacity();
method @NonNull public Object clone();
- method public void copyInto(Object[]);
+ method public void copyInto(@NonNull Object[]);
method public E elementAt(int);
method @NonNull public java.util.Enumeration<E> elements();
method public void ensureCapacity(int);
@@ -70799,7 +70799,7 @@ package java.util {
method public void trimToSize();
field protected int capacityIncrement;
field protected int elementCount;
- field protected Object[] elementData;
+ field @NonNull protected Object[] elementData;
}
public class WeakHashMap<K, V> extends java.util.AbstractMap<K,V> implements java.util.Map<K,V> {
@@ -71190,7 +71190,7 @@ package java.util.concurrent {
public class CopyOnWriteArrayList<E> implements java.lang.Cloneable java.util.List<E> java.util.RandomAccess java.io.Serializable {
ctor public CopyOnWriteArrayList();
ctor public CopyOnWriteArrayList(@NonNull java.util.Collection<? extends E>);
- ctor public CopyOnWriteArrayList(E[]);
+ ctor public CopyOnWriteArrayList(@NonNull E[]);
method public boolean add(E);
method public void add(int, E);
method public boolean addAll(@NonNull java.util.Collection<? extends E>);
@@ -71218,8 +71218,8 @@ package java.util.concurrent {
method public E set(int, E);
method public int size();
method @NonNull public java.util.List<E> subList(int, int);
- method public Object[] toArray();
- method public <T> T[] toArray(T[]);
+ method @NonNull public Object[] toArray();
+ method @NonNull public <T> T[] toArray(@NonNull T[]);
}
public class CopyOnWriteArraySet<E> extends java.util.AbstractSet<E> implements java.io.Serializable {
@@ -72971,7 +72971,7 @@ package java.util.logging {
method public void config(@NonNull java.util.function.Supplier<java.lang.String>);
method public void entering(@Nullable String, @Nullable String);
method public void entering(@Nullable String, @Nullable String, @Nullable Object);
- method public void entering(@Nullable String, @Nullable String, Object[]);
+ method public void entering(@Nullable String, @Nullable String, @Nullable Object[]);
method public void exiting(@Nullable String, @Nullable String);
method public void exiting(@Nullable String, @Nullable String, @Nullable Object);
method public void fine(@Nullable String);
@@ -72984,7 +72984,7 @@ package java.util.logging {
method @NonNull public static java.util.logging.Logger getAnonymousLogger(@Nullable String);
method @Nullable public java.util.logging.Filter getFilter();
method @NonNull public static final java.util.logging.Logger getGlobal();
- method public java.util.logging.Handler[] getHandlers();
+ method @NonNull public java.util.logging.Handler[] getHandlers();
method @Nullable public java.util.logging.Level getLevel();
method @NonNull public static java.util.logging.Logger getLogger(@NonNull String);
method @NonNull public static java.util.logging.Logger getLogger(@NonNull String, @Nullable String);
@@ -73000,7 +73000,7 @@ package java.util.logging {
method public void log(@NonNull java.util.logging.Level, @Nullable String);
method public void log(@NonNull java.util.logging.Level, @NonNull java.util.function.Supplier<java.lang.String>);
method public void log(@NonNull java.util.logging.Level, @Nullable String, @Nullable Object);
- method public void log(@NonNull java.util.logging.Level, @Nullable String, Object[]);
+ method public void log(@NonNull java.util.logging.Level, @Nullable String, @Nullable Object[]);
method public void log(@NonNull java.util.logging.Level, @Nullable String, @Nullable Throwable);
method public void log(@NonNull java.util.logging.Level, @Nullable Throwable, @NonNull java.util.function.Supplier<java.lang.String>);
method public void logp(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String);
@@ -73011,8 +73011,8 @@ package java.util.logging {
method public void logp(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable Throwable, @NonNull java.util.function.Supplier<java.lang.String>);
method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String);
method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String, @Nullable Object);
- method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String, Object[]);
- method public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable java.util.ResourceBundle, @Nullable String, java.lang.Object...);
+ method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String, @Nullable Object[]);
+ method public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable java.util.ResourceBundle, @Nullable String, @Nullable java.lang.Object...);
method @Deprecated public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable String, @Nullable String, @Nullable Throwable);
method public void logrb(@NonNull java.util.logging.Level, @Nullable String, @Nullable String, @Nullable java.util.ResourceBundle, @Nullable String, @Nullable Throwable);
method public void removeHandler(@Nullable java.util.logging.Handler) throws java.lang.SecurityException;
@@ -73274,8 +73274,8 @@ package java.util.regex {
method public static boolean matches(@NonNull String, @NonNull CharSequence);
method @NonNull public String pattern();
method @NonNull public static String quote(@NonNull String);
- method public String[] split(@NonNull CharSequence, int);
- method public String[] split(@NonNull CharSequence);
+ method @NonNull public String[] split(@NonNull CharSequence, int);
+ method @NonNull public String[] split(@NonNull CharSequence);
method @NonNull public java.util.stream.Stream<java.lang.String> splitAsStream(@NonNull CharSequence);
field public static final int CANON_EQ = 128; // 0x80
field public static final int CASE_INSENSITIVE = 2; // 0x2
diff --git a/api/system-current.txt b/api/system-current.txt
index 88725e128e8b..19b3f0e6cae2 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1718,9 +1718,9 @@ package android.content.rollback {
public final class RollbackInfo implements android.os.Parcelable {
method public int describeContents();
method public java.util.List<android.content.pm.VersionedPackage> getCausePackages();
+ method public int getCommittedSessionId();
method public java.util.List<android.content.rollback.PackageRollbackInfo> getPackages();
method public int getRollbackId();
- method public int getSessionId();
method public boolean isStaged();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.rollback.RollbackInfo> CREATOR;
diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
index 4e4b8f35726d..f37d2bedf8c2 100644
--- a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
+++ b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
@@ -55,6 +55,10 @@ bool StatsCompanionServicePuller::PullInternal(vector<shared_ptr<LogEvent> >* da
Status status = statsCompanionServiceCopy->pullData(mTagId, &returned_value);
if (!status.isOk()) {
ALOGW("StatsCompanionServicePuller::pull failed for %d", mTagId);
+ StatsdStats::getInstance().noteStatsCompanionPullFailed(mTagId);
+ if (status.exceptionCode() == Status::Exception::EX_TRANSACTION_FAILED) {
+ StatsdStats::getInstance().noteStatsCompanionPullBinderTransactionFailed(mTagId);
+ }
return false;
}
data->clear();
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index ba7bcc437d74..a6ba2cae2889 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -231,6 +231,9 @@ bool StatsPullerManager::Pull(int tagId, vector<shared_ptr<LogEvent>>* data) {
if (kAllPullAtomInfo.find(tagId) != kAllPullAtomInfo.end()) {
bool ret = kAllPullAtomInfo.find(tagId)->second.puller->Pull(data);
VLOG("pulled %d items", (int)data->size());
+ if (!ret) {
+ StatsdStats::getInstance().notePullFailed(tagId);
+ }
return ret;
} else {
VLOG("Unknown tagId %d", tagId);
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index f4d0144e8878..37ccad5f4a49 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -403,6 +403,60 @@ void StatsdStats::noteSystemServerRestart(int32_t timeSec) {
mSystemServerRestartSec.push_back(timeSec);
}
+void StatsdStats::notePullFailed(int atomId) {
+ lock_guard<std::mutex> lock(mLock);
+ mPulledAtomStats[atomId].pullFailed++;
+}
+
+void StatsdStats::noteStatsCompanionPullFailed(int atomId) {
+ lock_guard<std::mutex> lock(mLock);
+ mPulledAtomStats[atomId].statsCompanionPullFailed++;
+}
+
+void StatsdStats::noteStatsCompanionPullBinderTransactionFailed(int atomId) {
+ lock_guard<std::mutex> lock(mLock);
+ mPulledAtomStats[atomId].statsCompanionPullBinderTransactionFailed++;
+}
+
+void StatsdStats::noteEmptyData(int atomId) {
+ lock_guard<std::mutex> lock(mLock);
+ mPulledAtomStats[atomId].emptyData++;
+}
+
+void StatsdStats::noteHardDimensionLimitReached(int metricId) {
+ lock_guard<std::mutex> lock(mLock);
+ getAtomMetricStats(metricId).hardDimensionLimitReached++;
+}
+
+void StatsdStats::noteLateLogEventSkipped(int metricId) {
+ lock_guard<std::mutex> lock(mLock);
+ getAtomMetricStats(metricId).lateLogEventSkipped++;
+}
+
+void StatsdStats::noteSkippedForwardBuckets(int metricId) {
+ lock_guard<std::mutex> lock(mLock);
+ getAtomMetricStats(metricId).skippedForwardBuckets++;
+}
+
+void StatsdStats::noteBadValueType(int metricId) {
+ lock_guard<std::mutex> lock(mLock);
+ getAtomMetricStats(metricId).badValueType++;
+}
+
+void StatsdStats::noteConditionChangeInNextBucket(int metricId) {
+ lock_guard<std::mutex> lock(mLock);
+ getAtomMetricStats(metricId).conditionChangeInNextBucket++;
+}
+
+StatsdStats::AtomMetricStats& StatsdStats::getAtomMetricStats(int metricId) {
+ auto atomMetricStatsIter = mAtomMetricStats.find(metricId);
+ if (atomMetricStatsIter != mAtomMetricStats.end()) {
+ return atomMetricStatsIter->second;
+ }
+ auto emplaceResult = mAtomMetricStats.emplace(metricId, AtomMetricStats());
+ return emplaceResult.first->second;
+}
+
void StatsdStats::reset() {
lock_guard<std::mutex> lock(mLock);
resetInternalLocked();
@@ -442,6 +496,7 @@ void StatsdStats::resetInternalLocked() {
pullStats.second.pullTimeout = 0;
pullStats.second.pullExceedMaxDelay = 0;
}
+ mAtomMetricStats.clear();
}
string buildTimeString(int64_t timeSec) {
@@ -713,6 +768,10 @@ void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) {
android::os::statsd::writePullerStatsToStream(pair, &proto);
}
+ for (const auto& pair : mAtomMetricStats) {
+ android::os::statsd::writeAtomMetricStatsToStream(pair, &proto);
+ }
+
if (mAnomalyAlarmRegisteredStats > 0) {
uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ANOMALY_ALARM_STATS);
proto.write(FIELD_TYPE_INT32 | FIELD_ID_ANOMALY_ALARMS_REGISTERED,
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index dc647f888b6f..01e9ca17e5fd 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -318,6 +318,53 @@ public:
void noteLogLost(int32_t wallClockTimeSec, int32_t count, int lastError);
/**
+ * Records that the pull of an atom has failed
+ */
+ void notePullFailed(int atomId);
+
+ /**
+ * Records that the pull of StatsCompanionService atom has failed
+ */
+ void noteStatsCompanionPullFailed(int atomId);
+
+ /**
+ * Records that the pull of a StatsCompanionService atom has failed due to a failed binder
+ * transaction. This can happen when StatsCompanionService returns too
+ * much data (the max Binder parcel size is 1MB)
+ */
+ void noteStatsCompanionPullBinderTransactionFailed(int atomId);
+
+ /**
+ * A pull with no data occurred
+ */
+ void noteEmptyData(int atomId);
+
+ /**
+ * Hard limit was reached in the cardinality of an atom
+ */
+ void noteHardDimensionLimitReached(int atomId);
+
+ /**
+ * A log event was too late, arrived in the wrong bucket and was skipped
+ */
+ void noteLateLogEventSkipped(int atomId);
+
+ /**
+ * Buckets were skipped as time elapsed without any data for them
+ */
+ void noteSkippedForwardBuckets(int atomId);
+
+ /**
+ * An unsupported value type was received
+ */
+ void noteBadValueType(int atomId);
+
+ /**
+ * A condition change was too late, arrived in the wrong bucket and was skipped
+ */
+ void noteConditionChangeInNextBucket(int atomId);
+
+ /**
* Reset the historical stats. Including all stats in icebox, and the tracked stats about
* metrics, matchers, and atoms. The active configs will be kept and StatsdStats will continue
* to collect stats after reset() has been called.
@@ -349,8 +396,20 @@ public:
long dataError = 0;
long pullTimeout = 0;
long pullExceedMaxDelay = 0;
+ long pullFailed = 0;
+ long statsCompanionPullFailed = 0;
+ long statsCompanionPullBinderTransactionFailed = 0;
+ long emptyData = 0;
} PulledAtomStats;
+ typedef struct {
+ long hardDimensionLimitReached = 0;
+ long lateLogEventSkipped = 0;
+ long skippedForwardBuckets = 0;
+ long badValueType = 0;
+ long conditionChangeInNextBucket = 0;
+ } AtomMetricStats;
+
private:
StatsdStats();
@@ -378,6 +437,9 @@ private:
// Maps PullAtomId to its stats. The size is capped by the puller atom counts.
std::map<int, PulledAtomStats> mPulledAtomStats;
+ // Maps metric ID to its stats. The size is capped by the number of metrics.
+ std::map<int, AtomMetricStats> mAtomMetricStats;
+
struct LogLossStats {
LogLossStats(int32_t sec, int32_t count, int32_t error)
: mWallClockSec(sec), mCount(count), mLastError(error) {
@@ -414,6 +476,12 @@ private:
void addToIceBoxLocked(std::shared_ptr<ConfigStats>& stats);
+ /**
+ * Get a reference to AtomMetricStats for a metric. If none exists, create it. The reference
+ * will live as long as `this`.
+ */
+ StatsdStats::AtomMetricStats& getAtomMetricStats(int metricId);
+
FRIEND_TEST(StatsdStatsTest, TestValidConfigAdd);
FRIEND_TEST(StatsdStatsTest, TestInvalidConfigAdd);
FRIEND_TEST(StatsdStatsTest, TestConfigRemove);
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 5645461cc3ab..6aa8e842b021 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -322,6 +322,7 @@ void ValueMetricProducer::onConditionChangedLocked(const bool condition,
if (eventTimeNs < mCurrentBucketStartTimeNs) {
VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
(long long)mCurrentBucketStartTimeNs);
+ StatsdStats::getInstance().noteConditionChangeInNextBucket(mMetricId);
return;
}
@@ -359,6 +360,12 @@ void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
}
StatsdStats::getInstance().notePullDelay(mPullTagId, pullDelayNs);
+ if (timestampNs < mCurrentBucketStartTimeNs) {
+ // The data will be skipped in onMatchedLogEventInternalLocked, but we don't want to report
+ // for every event, just the pull
+ StatsdStats::getInstance().noteLateLogEventSkipped(mMetricId);
+ }
+
for (const auto& data : allData) {
// make a copy before doing and changes
LogEvent localCopy = data->makeCopy();
@@ -380,6 +387,7 @@ void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEven
if (mCondition) {
if (allData.size() == 0) {
VLOG("Data pulled is empty");
+ StatsdStats::getInstance().noteEmptyData(mPullTagId);
return;
}
// For scheduled pulled data, the effective event time is snap to the nearest
@@ -394,6 +402,7 @@ void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEven
if (bucketEndTime < mCurrentBucketStartTimeNs) {
VLOG("Skip bucket end pull due to late arrival: %lld vs %lld", (long long)bucketEndTime,
(long long)mCurrentBucketStartTimeNs);
+ StatsdStats::getInstance().noteLateLogEventSkipped(mMetricId);
return;
}
for (const auto& data : allData) {
@@ -442,6 +451,7 @@ bool ValueMetricProducer::hitGuardRailLocked(const MetricDimensionKey& newKey) {
if (newTupleCount > mDimensionHardLimit) {
ALOGE("ValueMetric %lld dropping data for dimension key %s", (long long)mMetricId,
newKey.toString().c_str());
+ StatsdStats::getInstance().noteHardDimensionLimitReached(mMetricId);
return true;
}
}
@@ -539,6 +549,7 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIn
Value value;
if (!getDoubleOrLong(event, matcher, value)) {
VLOG("Failed to get value %d from event %s", i, event.ToString().c_str());
+ StatsdStats::getInstance().noteBadValueType(mMetricId);
return;
}
interval.seenNewData = true;
@@ -656,6 +667,7 @@ void ValueMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) {
if (numBucketsForward > 1) {
VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
+ StatsdStats::getInstance().noteSkippedForwardBuckets(mMetricId);
// take base again in future good bucket.
resetBase();
}
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index e8de875a461b..cca09ac017a3 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -403,9 +403,23 @@ message StatsdStatsReport {
optional int64 data_error = 9;
optional int64 pull_timeout = 10;
optional int64 pull_exceed_max_delay = 11;
+ optional int64 pull_failed = 12;
+ optional int64 stats_companion_pull_failed = 13;
+ optional int64 stats_companion_pull_binder_transaction_failed = 14;
+ optional int64 empty_data = 15;
}
repeated PulledAtomStats pulled_atom_stats = 10;
+ message AtomMetricStats {
+ optional int64 metric_id = 1;
+ optional int64 hard_dimension_limit_reached = 2;
+ optional int64 late_log_event_skipped = 3;
+ optional int64 skipped_forward_buckets = 4;
+ optional int64 bad_value_type = 5;
+ optional int64 condition_change_in_next_bucket = 6;
+ }
+ repeated AtomMetricStats atom_metric_stats = 17;
+
message LoggerErrorStats {
optional int32 logger_disconnection_sec = 1;
optional int32 error_code = 2;
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index 7de0bb3290a7..9c9985ed271c 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -66,6 +66,18 @@ const int FIELD_ID_MAX_PULL_DELAY_NANOS = 8;
const int FIELD_ID_DATA_ERROR = 9;
const int FIELD_ID_PULL_TIMEOUT = 10;
const int FIELD_ID_PULL_EXCEED_MAX_DELAY = 11;
+const int FIELD_ID_PULL_FAILED = 12;
+const int FIELD_ID_STATS_COMPANION_FAILED = 13;
+const int FIELD_ID_STATS_COMPANION_BINDER_TRANSACTION_FAILED = 14;
+const int FIELD_ID_EMPTY_DATA = 15;
+// for AtomMetricStats proto
+const int FIELD_ID_ATOM_METRIC_STATS = 17;
+const int FIELD_ID_METRIC_ID = 1;
+const int FIELD_ID_HARD_DIMENSION_LIMIT_REACHED = 2;
+const int FIELD_ID_LATE_LOG_EVENT_SKIPPED = 3;
+const int FIELD_ID_SKIPPED_FORWARD_BUCKETS = 4;
+const int FIELD_ID_BAD_VALUE_TYPE = 5;
+const int FIELD_ID_CONDITION_CHANGE_IN_NEXT_BUCKET = 6;
namespace {
@@ -456,6 +468,32 @@ void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>
(long long)pair.second.pullTimeout);
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_EXCEED_MAX_DELAY,
(long long)pair.second.pullExceedMaxDelay);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_PULL_FAILED,
+ (long long)pair.second.pullFailed);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_STATS_COMPANION_FAILED,
+ (long long)pair.second.statsCompanionPullFailed);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_STATS_COMPANION_BINDER_TRANSACTION_FAILED,
+ (long long)pair.second.statsCompanionPullBinderTransactionFailed);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_EMPTY_DATA,
+ (long long)pair.second.emptyData);
+ protoOutput->end(token);
+}
+
+void writeAtomMetricStatsToStream(const std::pair<int, StatsdStats::AtomMetricStats> &pair,
+ util::ProtoOutputStream *protoOutput) {
+ uint64_t token = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOM_METRIC_STATS |
+ FIELD_COUNT_REPEATED);
+ protoOutput->write(FIELD_TYPE_INT32 | FIELD_ID_METRIC_ID, (int32_t)pair.first);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_HARD_DIMENSION_LIMIT_REACHED,
+ (long long)pair.second.hardDimensionLimitReached);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_LATE_LOG_EVENT_SKIPPED,
+ (long long)pair.second.lateLogEventSkipped);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_SKIPPED_FORWARD_BUCKETS,
+ (long long)pair.second.skippedForwardBuckets);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BAD_VALUE_TYPE,
+ (long long)pair.second.badValueType);
+ protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_CONDITION_CHANGE_IN_NEXT_BUCKET,
+ (long long)pair.second.conditionChangeInNextBucket);
protoOutput->end(token);
}
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index 61f31eb3fa17..dcea0e653e22 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -73,6 +73,10 @@ int64_t MillisToNano(const int64_t millis);
void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>& pair,
util::ProtoOutputStream* protoOutput);
+// Helper function to write AtomMetricStats to ProtoOutputStream
+void writeAtomMetricStatsToStream(const std::pair<int, StatsdStats::AtomMetricStats> &pair,
+ util::ProtoOutputStream *protoOutput);
+
template<class T>
bool parseProtoOutputStream(util::ProtoOutputStream& protoOutput, T* message) {
std::string pbBytes;
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index ce5d8a5cfeb2..eae7d6b79f67 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -28,15 +28,12 @@ import android.content.Context;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
-import android.hardware.input.InputManager;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.IWindowManager;
-import android.view.InputDevice;
-import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceSession;
@@ -51,9 +48,7 @@ import dalvik.system.CloseGuard;
import java.util.List;
/**
- * Activity container that allows launching activities into itself and does input forwarding.
- * <p>Creation of this view is only allowed to callers who have
- * {@link android.Manifest.permission#INJECT_EVENTS} permission.
+ * Activity container that allows launching activities into itself.
* <p>Activity launching into this container is restricted by the same rules that apply to launching
* on VirtualDisplays.
* @hide
@@ -76,9 +71,8 @@ public class ActivityView extends ViewGroup {
private StateCallback mActivityViewCallback;
private IActivityTaskManager mActivityTaskManager;
- private IInputForwarder mInputForwarder;
- // Temp container to store view coordinates on screen.
- private final int[] mLocationOnScreen = new int[2];
+ // Temp container to store view coordinates in window.
+ private final int[] mLocationInWindow = new int[2];
private TaskStackListener mTaskStackListener;
@@ -280,7 +274,7 @@ public class ActivityView extends ViewGroup {
}
/**
- * Triggers an update of {@link ActivityView}'s location on screen to properly set touch exclude
+ * Triggers an update of {@link ActivityView}'s location in window to properly set touch exclude
* regions and avoid focus switches by touches on this view.
*/
public void onLocationChanged() {
@@ -295,45 +289,14 @@ public class ActivityView extends ViewGroup {
/** Send current location and size to the WM to set tap exclude region for this view. */
private void updateLocation() {
try {
- getLocationOnScreen(mLocationOnScreen);
+ getLocationInWindow(mLocationInWindow);
WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
- mLocationOnScreen[0], mLocationOnScreen[1], getWidth(), getHeight());
+ mLocationInWindow[0], mLocationInWindow[1], getWidth(), getHeight());
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
}
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- return injectInputEvent(event) || super.onTouchEvent(event);
- }
-
- @Override
- public boolean onGenericMotionEvent(MotionEvent event) {
- if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
- if (injectInputEvent(event)) {
- return true;
- }
- }
- return super.onGenericMotionEvent(event);
- }
-
- private boolean injectInputEvent(MotionEvent event) {
- if (mInputForwarder != null) {
- try {
- // The touch event that the ActivityView gets is in View space, but the event needs
- // to get forwarded in screen space. This offsets the touch event by the location
- // the ActivityView is on screen and sends it to the input forwarder.
- getLocationOnScreen(mLocationOnScreen);
- event.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]);
- return mInputForwarder.forwardEvent(event);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- }
- return false;
- }
-
private class SurfaceCallback implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
@@ -416,7 +379,6 @@ public class ActivityView extends ViewGroup {
}
mTmpTransaction.show(mRootSurfaceControl).apply();
- mInputForwarder = InputManager.getInstance().createInputForwarder(displayId);
mTaskStackListener = new TaskStackListenerImpl();
try {
mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
@@ -432,9 +394,6 @@ public class ActivityView extends ViewGroup {
mSurfaceView.getHolder().removeCallback(mSurfaceCallback);
- if (mInputForwarder != null) {
- mInputForwarder = null;
- }
cleanTapExcludeRegion();
if (mTaskStackListener != null) {
diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java
index 4644a83de462..d4ed35a9cb71 100644
--- a/core/java/android/content/rollback/PackageRollbackInfo.java
+++ b/core/java/android/content/rollback/PackageRollbackInfo.java
@@ -16,10 +16,14 @@
package android.content.rollback;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.content.pm.VersionedPackage;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.IntArray;
+
+import java.util.ArrayList;
/**
* Information about a rollback available for a particular package.
@@ -33,6 +37,38 @@ public final class PackageRollbackInfo implements Parcelable {
private final VersionedPackage mVersionRolledBackTo;
/**
+ * Encapsulates information required to restore a snapshot of an app's userdata.
+ *
+ * @hide
+ */
+ public static class RestoreInfo {
+ public final int userId;
+ public final int appId;
+ public final String seInfo;
+
+ public RestoreInfo(int userId, int appId, String seInfo) {
+ this.userId = userId;
+ this.appId = appId;
+ this.seInfo = seInfo;
+ }
+ }
+
+ /*
+ * The list of users for which we need to backup userdata for this package. Backups of
+ * credential encrypted data are listed as pending if the user hasn't unlocked their device
+ * with credentials yet.
+ */
+ // NOTE: Not a part of the Parcelable representation of this object.
+ private final IntArray mPendingBackups;
+
+ /**
+ * The list of users for which we need to restore userdata for this package. This field is
+ * non-null only after a rollback for this package has been committed.
+ */
+ // NOTE: Not a part of the Parcelable representation of this object.
+ private final ArrayList<RestoreInfo> mPendingRestores;
+
+ /**
* Returns the name of the package to roll back from.
*/
public String getPackageName() {
@@ -54,15 +90,46 @@ public final class PackageRollbackInfo implements Parcelable {
}
/** @hide */
+ public IntArray getPendingBackups() {
+ return mPendingBackups;
+ }
+
+ /** @hide */
+ public ArrayList<RestoreInfo> getPendingRestores() {
+ return mPendingRestores;
+ }
+
+ /** @hide */
+ public RestoreInfo getRestoreInfo(int userId) {
+ for (RestoreInfo ri : mPendingRestores) {
+ if (ri.userId == userId) {
+ return ri;
+ }
+ }
+
+ return null;
+ }
+
+ /** @hide */
+ public void removeRestoreInfo(RestoreInfo ri) {
+ mPendingRestores.remove(ri);
+ }
+
+ /** @hide */
public PackageRollbackInfo(VersionedPackage packageRolledBackFrom,
- VersionedPackage packageRolledBackTo) {
+ VersionedPackage packageRolledBackTo,
+ @NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores) {
this.mVersionRolledBackFrom = packageRolledBackFrom;
this.mVersionRolledBackTo = packageRolledBackTo;
+ this.mPendingBackups = pendingBackups;
+ this.mPendingRestores = pendingRestores;
}
private PackageRollbackInfo(Parcel in) {
this.mVersionRolledBackFrom = VersionedPackage.CREATOR.createFromParcel(in);
this.mVersionRolledBackTo = VersionedPackage.CREATOR.createFromParcel(in);
+ this.mPendingRestores = null;
+ this.mPendingBackups = null;
}
@Override
diff --git a/core/java/android/content/rollback/RollbackInfo.java b/core/java/android/content/rollback/RollbackInfo.java
index 1111b4320eb9..3fd247670a9d 100644
--- a/core/java/android/content/rollback/RollbackInfo.java
+++ b/core/java/android/content/rollback/RollbackInfo.java
@@ -83,7 +83,7 @@ public final class RollbackInfo implements Parcelable {
* Returns the session ID for the committed rollback for staged rollbacks.
* Only applicable for rollbacks that have been committed.
*/
- public int getSessionId() {
+ public int getCommittedSessionId() {
// TODO: Support rollback of staged installs.
return PackageInstaller.SessionInfo.INVALID_ID;
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 794c2f1b991b..5151e29e97ff 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10521,8 +10521,10 @@ public final class Settings {
/**
* Setting to enable connected MAC randomization in Wi-Fi; disabled by default, and
* setting to 1 will enable it. In the future, additional values may be supported.
+ * @deprecated MAC randomization is now a per-network setting
* @hide
*/
+ @Deprecated
public static final String WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED =
"wifi_connected_mac_randomization_enabled";
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index eb41e078e59f..59e562fe8071 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -41,12 +41,14 @@ import android.view.View.AttachInfo;
import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.accessibility.AccessibilityNodeProvider;
import android.view.accessibility.AccessibilityRequestPreparer;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import java.util.ArrayList;
@@ -64,8 +66,11 @@ import java.util.function.Predicate;
* called from the interaction connection ViewAncestor gives the system to
* talk to it and a corresponding *UiThread method that is executed on the
* UI thread.
+ *
+ * @hide
*/
-final class AccessibilityInteractionController {
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public final class AccessibilityInteractionController {
private static final String LOG_TAG = "AccessibilityInteractionController";
@@ -85,7 +90,7 @@ final class AccessibilityInteractionController {
private final Object mLock = new Object();
- private final Handler mHandler;
+ private final PrivateHandler mHandler;
private final ViewRootImpl mViewRootImpl;
@@ -131,11 +136,19 @@ final class AccessibilityInteractionController {
// thread in this process, set the message as a static reference so
// after this call completes the same thread but in the interrogating
// client can handle the message to generate the result.
- if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
+ if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId
+ && mHandler.hasAccessibilityCallback(message)) {
AccessibilityInteractionClient.getInstanceForThread(
interrogatingTid).setSameThreadMessage(message);
} else {
- mHandler.sendMessage(message);
+ // For messages without callback of interrogating client, just handle the
+ // message immediately if this is UI thread.
+ if (!mHandler.hasAccessibilityCallback(message)
+ && Thread.currentThread().getId() == mMyLooperThreadId) {
+ mHandler.handleMessage(message);
+ } else {
+ mHandler.sendMessage(message);
+ }
}
}
}
@@ -731,6 +744,52 @@ final class AccessibilityInteractionController {
}
}
+ /**
+ * Finds the accessibility focused node in the root, and clears the accessibility focus.
+ */
+ public void clearAccessibilityFocusClientThread() {
+ final Message message = mHandler.obtainMessage();
+ message.what = PrivateHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS;
+
+ // Don't care about pid and tid because there's no interrogating client for this message.
+ scheduleMessage(message, 0, 0, CONSIDER_REQUEST_PREPARERS);
+ }
+
+ private void clearAccessibilityFocusUiThread() {
+ if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
+ return;
+ }
+ try {
+ mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags =
+ AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+ final View root = mViewRootImpl.mView;
+ if (root != null && isShown(root)) {
+ final View host = mViewRootImpl.mAccessibilityFocusedHost;
+ // If there is no accessibility focus host or it is not a descendant
+ // of the root from which to start the search, then the search failed.
+ if (host == null || !ViewRootImpl.isViewDescendantOf(host, root)) {
+ return;
+ }
+ final AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
+ final AccessibilityNodeInfo focusNode =
+ mViewRootImpl.mAccessibilityFocusedVirtualView;
+ if (provider != null && focusNode != null) {
+ final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
+ focusNode.getSourceNodeId());
+ provider.performAction(virtualNodeId,
+ AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS.getId(),
+ null);
+ } else {
+ host.performAccessibilityAction(
+ AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS.getId(),
+ null);
+ }
+ }
+ } finally {
+ mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+ }
+ }
+
private View findViewByAccessibilityId(int accessibilityId) {
View root = mViewRootImpl.mView;
if (root == null) {
@@ -1294,6 +1353,12 @@ final class AccessibilityInteractionController {
private static final int MSG_APP_PREPARATION_FINISHED = 8;
private static final int MSG_APP_PREPARATION_TIMEOUT = 9;
+ // Uses FIRST_NO_ACCESSIBILITY_CALLBACK_MSG for messages that don't need to call back
+ // results to interrogating client.
+ private static final int FIRST_NO_ACCESSIBILITY_CALLBACK_MSG = 100;
+ private static final int MSG_CLEAR_ACCESSIBILITY_FOCUS =
+ FIRST_NO_ACCESSIBILITY_CALLBACK_MSG + 1;
+
public PrivateHandler(Looper looper) {
super(looper);
}
@@ -1320,6 +1385,8 @@ final class AccessibilityInteractionController {
return "MSG_APP_PREPARATION_FINISHED";
case MSG_APP_PREPARATION_TIMEOUT:
return "MSG_APP_PREPARATION_TIMEOUT";
+ case MSG_CLEAR_ACCESSIBILITY_FOCUS:
+ return "MSG_CLEAR_ACCESSIBILITY_FOCUS";
default:
throw new IllegalArgumentException("Unknown message type: " + type);
}
@@ -1356,10 +1423,17 @@ final class AccessibilityInteractionController {
case MSG_APP_PREPARATION_TIMEOUT: {
requestPreparerTimeoutUiThread();
} break;
+ case MSG_CLEAR_ACCESSIBILITY_FOCUS: {
+ clearAccessibilityFocusUiThread();
+ } break;
default:
throw new IllegalArgumentException("Unknown message type: " + type);
}
}
+
+ boolean hasAccessibilityCallback(Message message) {
+ return message.what < FIRST_NO_ACCESSIBILITY_CALLBACK_MSG ? true : false;
+ }
}
private final class AddNodeInfosForViewId implements Predicate<View> {
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index 92e0009bc21a..ec79eea45ee6 100644
--- a/core/java/android/view/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -16,10 +16,10 @@
package android.view;
+import static android.view.Display.INVALID_DISPLAY;
+
import android.graphics.Region;
import android.os.IBinder;
-import android.view.IWindow;
-import android.view.InputChannel;
/**
* Functions as a handle for a window that can receive input.
@@ -94,6 +94,10 @@ public final class InputWindowHandle {
// Display this input is on.
public int displayId;
+ // If this value is set to a valid display ID, it indicates this window is a portal which
+ // transports the touch of this window to the display indicated by portalToDisplayId.
+ public int portalToDisplayId = INVALID_DISPLAY;
+
private native void nativeDispose();
public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f47eb10efd29..9213f32326b4 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -8718,6 +8718,15 @@ public final class ViewRootImpl implements ViewParent,
}
}
}
+
+ @Override
+ public void clearAccessibilityFocus() {
+ ViewRootImpl viewRootImpl = mViewRootImpl.get();
+ if (viewRootImpl != null && viewRootImpl.mView != null) {
+ viewRootImpl.getAccessibilityInteractionController()
+ .clearAccessibilityFocusClientThread();
+ }
+ }
}
private class SendWindowContentChangedAccessibilityEvent implements Runnable {
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index 4c0fdfd5afdf..947ff056627e 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -55,4 +55,6 @@ oneway interface IAccessibilityInteractionConnection {
void performAccessibilityAction(long accessibilityNodeId, int action, in Bundle arguments,
int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
int interrogatingPid, long interrogatingTid);
+
+ void clearAccessibilityFocus();
}
diff --git a/core/java/com/android/internal/os/AppZygoteInit.java b/core/java/com/android/internal/os/AppZygoteInit.java
index afe6dade62ac..6ba584d76ee8 100644
--- a/core/java/com/android/internal/os/AppZygoteInit.java
+++ b/core/java/com/android/internal/os/AppZygoteInit.java
@@ -73,6 +73,9 @@ class AppZygoteInit {
Log.i(TAG, "Beginning application preload for " + appInfo.packageName);
LoadedApk loadedApk = new LoadedApk(null, appInfo, null, null, false, true, false);
ClassLoader loader = loadedApk.getClassLoader();
+
+ Zygote.allowAppFilesAcrossFork(appInfo);
+
Class<?> cl;
Method m;
try {
diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java
index c8d30b27d4dc..9ed738406707 100644
--- a/core/java/com/android/internal/os/WebViewZygoteInit.java
+++ b/core/java/com/android/internal/os/WebViewZygoteInit.java
@@ -78,18 +78,7 @@ class WebViewZygoteInit {
ClassLoader loader = loadedApk.getClassLoader();
doPreload(loader, WebViewFactory.getWebViewLibrary(appInfo));
- // Add the APK to the Zygote's list of allowed files for children.
- Zygote.nativeAllowFileAcrossFork(appInfo.sourceDir);
- if (appInfo.splitSourceDirs != null) {
- for (String path : appInfo.splitSourceDirs) {
- Zygote.nativeAllowFileAcrossFork(path);
- }
- }
- if (appInfo.sharedLibraryFiles != null) {
- for (String path : appInfo.sharedLibraryFiles) {
- Zygote.nativeAllowFileAcrossFork(path);
- }
- }
+ Zygote.allowAppFilesAcrossFork(appInfo);
Log.i(TAG, "Application preload done");
}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index bc7cf8755786..474d4d7cd90e 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -20,6 +20,7 @@ import static android.system.OsConstants.O_CLOEXEC;
import static com.android.internal.os.ZygoteConnectionConstants.MAX_ZYGOTE_ARGC;
+import android.content.pm.ApplicationInfo;
import android.net.Credentials;
import android.net.LocalServerSocket;
import android.net.LocalSocket;
@@ -370,6 +371,27 @@ public final class Zygote {
protected static native void nativeAllowFileAcrossFork(String path);
/**
+ * Lets children of the zygote inherit open file descriptors that belong to the
+ * ApplicationInfo that is passed in.
+ *
+ * @param appInfo ApplicationInfo of the application
+ */
+ protected static void allowAppFilesAcrossFork(ApplicationInfo appInfo) {
+ Zygote.nativeAllowFileAcrossFork(appInfo.sourceDir);
+ if (appInfo.splitSourceDirs != null) {
+ for (String path : appInfo.splitSourceDirs) {
+ Zygote.nativeAllowFileAcrossFork(path);
+ }
+ }
+ // As well as its shared libs
+ if (appInfo.sharedLibraryFiles != null) {
+ for (String path : appInfo.sharedLibraryFiles) {
+ Zygote.nativeAllowFileAcrossFork(path);
+ }
+ }
+ }
+
+ /**
* Installs a seccomp filter that limits setresuid()/setresgid() to the passed-in range
* @param uidGidMin The smallest allowed uid/gid
* @param uidGidMax The largest allowed uid/gid
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index c0e45b12cf76..67a74419e771 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -55,6 +55,7 @@ static struct {
jfieldID ownerUid;
jfieldID inputFeatures;
jfieldID displayId;
+ jfieldID portalToDisplayId;
} gInputWindowHandleClassInfo;
static Mutex gHandleMutex;
@@ -154,6 +155,8 @@ bool NativeInputWindowHandle::updateInfo() {
gInputWindowHandleClassInfo.inputFeatures);
mInfo.displayId = env->GetIntField(obj,
gInputWindowHandleClassInfo.displayId);
+ mInfo.portalToDisplayId = env->GetIntField(obj,
+ gInputWindowHandleClassInfo.portalToDisplayId);
jobject inputApplicationHandleObj = env->GetObjectField(obj,
gInputWindowHandleClassInfo.inputApplicationHandle);
@@ -307,6 +310,9 @@ int register_android_view_InputWindowHandle(JNIEnv* env) {
GET_FIELD_ID(gInputWindowHandleClassInfo.displayId, clazz,
"displayId", "I");
+
+ GET_FIELD_ID(gInputWindowHandleClassInfo.portalToDisplayId, clazz,
+ "portalToDisplayId", "I");
return 0;
}
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index e0eaf14d24c8..712994bb0d14 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -999,7 +999,7 @@ message GlobalSettingsProto {
optional SettingProto watchdog_poor_network_test_enabled = 22 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto suspend_optimizations_enabled = 23 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto verbose_logging_enabled = 24 [ (android.privacy).dest = DEST_AUTOMATIC ];
- optional SettingProto connected_mac_randomization_enabled = 25 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ reserved 25; // connected_mac_randomization_enabled
optional SettingProto max_dhcp_retry_count = 26 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto mobile_data_transition_wakelock_timeout_ms = 27 [ (android.privacy).dest = DEST_AUTOMATIC ];
// Controls whether WiFi configurations created by a Device Owner app should
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 86818c611c1f..fffee903b3f0 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1144,6 +1144,14 @@
</intent-filter>
</activity>
+ <activity android:name="android.view.accessibility.AccessibilityTestActivity"
+ android:label="AccessibilityTestActivity" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
<!-- Activity-level metadata -->
<meta-data android:name="com.android.frameworks.coretests.isApp" android:value="true" />
<meta-data android:name="com.android.frameworks.coretests.string" android:value="foo" />
diff --git a/core/tests/coretests/res/layout/accessibility_test.xml b/core/tests/coretests/res/layout/accessibility_test.xml
new file mode 100644
index 000000000000..1bdd21b2acc8
--- /dev/null
+++ b/core/tests/coretests/res/layout/accessibility_test.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <Button android:id="@+id/appNameBtn"
+ android:text="@string/app_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="60dp"
+ android:bufferType="normal">
+ </Button>
+</LinearLayout>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 0b5bde767ac9..e32b41223d94 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -509,7 +509,6 @@ public class SettingsBackupTest {
Settings.Global.WIFI_ALWAYS_REQUESTED,
Settings.Global.WIFI_BADGING_THRESHOLDS,
Settings.Global.WIFI_BOUNCE_DELAY_OVERRIDE_MS,
- Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED,
Settings.Global.WIFI_COUNTRY_CODE,
Settings.Global.WIFI_DATA_STALL_MIN_TX_BAD,
Settings.Global.WIFI_DATA_STALL_MIN_TX_SUCCESS_WITHOUT_RX,
diff --git a/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java b/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java
new file mode 100644
index 000000000000..d0719cbea86e
--- /dev/null
+++ b/core/tests/coretests/src/android/view/AccessibilityInteractionControllerTest.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2018 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.view;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.Service;
+import android.app.UiAutomation;
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.text.TextUtils;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityTestActivity;
+import android.view.accessibility.AccessibilityWindowInfo;
+
+import com.android.compatibility.common.util.TestUtils;
+import com.android.frameworks.coretests.R;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class AccessibilityInteractionControllerTest {
+ static final long TIMEOUT_DEFAULT = 10000; // 10 seconds
+
+ private static Instrumentation sInstrumentation;
+ private static UiAutomation sUiAutomation;
+
+ @Rule
+ public ActivityTestRule<AccessibilityTestActivity> mActivityRule = new ActivityTestRule<>(
+ AccessibilityTestActivity.class, false, false);
+
+ private AccessibilityInteractionController mAccessibilityInteractionController;
+ private ViewRootImpl mViewRootImpl;
+ private View mButton;
+
+ @BeforeClass
+ public static void oneTimeSetup() {
+ sInstrumentation = InstrumentationRegistry.getInstrumentation();
+ sUiAutomation = sInstrumentation.getUiAutomation();
+ }
+
+ @AfterClass
+ public static void postTestTearDown() {
+ sUiAutomation.destroy();
+ }
+
+ @Before
+ public void setUp() throws Throwable {
+ launchActivity();
+ enableTouchExploration(true);
+ mActivityRule.runOnUiThread(() -> {
+ mViewRootImpl = mActivityRule.getActivity().getWindow().getDecorView()
+ .getViewRootImpl();
+ mButton = mActivityRule.getActivity().findViewById(R.id.appNameBtn);
+ });
+ mAccessibilityInteractionController =
+ mViewRootImpl.getAccessibilityInteractionController();
+ }
+
+ @After
+ public void tearDown() {
+ enableTouchExploration(false);
+ }
+
+ @Test
+ public void clearAccessibilityFocus_shouldClearFocus() throws Exception {
+ performAccessibilityFocus("com.android.frameworks.coretests:id/appNameBtn");
+ assertTrue("Button should have a11y focus",
+ mButton.isAccessibilityFocused());
+ mAccessibilityInteractionController.clearAccessibilityFocusClientThread();
+ sInstrumentation.waitForIdleSync();
+ assertFalse("Button should not have a11y focus",
+ mButton.isAccessibilityFocused());
+ }
+
+ @Test
+ public void clearAccessibilityFocus_uiThread_shouldClearFocus() throws Exception {
+ performAccessibilityFocus("com.android.frameworks.coretests:id/appNameBtn");
+ assertTrue("Button should have a11y focus",
+ mButton.isAccessibilityFocused());
+ sInstrumentation.runOnMainSync(() -> {
+ mAccessibilityInteractionController.clearAccessibilityFocusClientThread();
+ });
+ assertFalse("Button should not have a11y focus",
+ mButton.isAccessibilityFocused());
+ }
+
+ private void launchActivity() {
+ final Object waitObject = new Object();
+ final int[] location = new int[2];
+ final StringBuilder activityPackage = new StringBuilder();
+ final Rect bounds = new Rect();
+ final StringBuilder activityTitle = new StringBuilder();
+ try {
+ final long executionStartTimeMillis = SystemClock.uptimeMillis();
+ sUiAutomation.setOnAccessibilityEventListener((event) -> {
+ if (event.getEventTime() < executionStartTimeMillis) {
+ return;
+ }
+ synchronized (waitObject) {
+ waitObject.notifyAll();
+ }
+ });
+ enableRetrieveAccessibilityWindows();
+
+ final Activity activity = mActivityRule.launchActivity(null);
+ sInstrumentation.runOnMainSync(() -> {
+ activity.getWindow().getDecorView().getLocationOnScreen(location);
+ activityPackage.append(activity.getPackageName());
+ activityTitle.append(activity.getTitle());
+ });
+ sInstrumentation.waitForIdleSync();
+
+ TestUtils.waitOn(waitObject, () -> {
+ final AccessibilityWindowInfo window = findWindowByTitle(activityTitle);
+ if (window == null) return false;
+ window.getBoundsInScreen(bounds);
+ activity.getWindow().getDecorView().getLocationOnScreen(location);
+ if (bounds.isEmpty()) {
+ return false;
+ }
+ return (!bounds.isEmpty())
+ && (bounds.left == location[0]) && (bounds.top == location[1]);
+ }, TIMEOUT_DEFAULT, "Launch Activity");
+ } finally {
+ sUiAutomation.setOnAccessibilityEventListener(null);
+ }
+ }
+
+ private void enableRetrieveAccessibilityWindows() {
+ AccessibilityServiceInfo info = sUiAutomation.getServiceInfo();
+ info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
+ sUiAutomation.setServiceInfo(info);
+ }
+
+ private void enableTouchExploration(boolean enabled) {
+ final Object waitObject = new Object();
+ final AccessibilityManager accessibilityManager =
+ (AccessibilityManager) sInstrumentation.getContext().getSystemService(
+ Service.ACCESSIBILITY_SERVICE);
+ final AccessibilityManager.TouchExplorationStateChangeListener listener = status -> {
+ synchronized (waitObject) {
+ waitObject.notifyAll();
+ }
+ };
+ try {
+ accessibilityManager.addTouchExplorationStateChangeListener(listener);
+ final AccessibilityServiceInfo info = sUiAutomation.getServiceInfo();
+ if (enabled) {
+ info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
+ } else {
+ info.flags &= ~AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
+ }
+ sUiAutomation.setServiceInfo(info);
+ TestUtils.waitOn(waitObject,
+ () -> accessibilityManager.isTouchExplorationEnabled() == enabled,
+ TIMEOUT_DEFAULT,
+ (enabled ? "Enable" : "Disable") + "touch exploration");
+ } finally {
+ accessibilityManager.removeTouchExplorationStateChangeListener(listener);
+ }
+ }
+
+ private void performAccessibilityFocus(String viewId) throws TimeoutException {
+ final AccessibilityNodeInfo node = sUiAutomation.getRootInActiveWindow()
+ .findAccessibilityNodeInfosByViewId(viewId).get(0);
+ // Perform an action and wait for an event
+ sUiAutomation.executeAndWaitForEvent(
+ () -> node.performAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS),
+ event -> event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED,
+ TIMEOUT_DEFAULT);
+ node.refresh();
+ }
+
+ private AccessibilityWindowInfo findWindowByTitle(CharSequence title) {
+ final List<AccessibilityWindowInfo> windows = sUiAutomation.getWindows();
+ AccessibilityWindowInfo returnValue = null;
+ for (int i = 0; i < windows.size(); i++) {
+ final AccessibilityWindowInfo window = windows.get(i);
+ if (TextUtils.equals(title, window.getTitle())) {
+ returnValue = window;
+ } else {
+ window.recycle();
+ }
+ }
+ return returnValue;
+ }
+}
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityTestActivity.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityTestActivity.java
new file mode 100644
index 000000000000..a17fa7326a5d
--- /dev/null
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityTestActivity.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 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.view.accessibility;
+
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.frameworks.coretests.R;
+
+/**
+ * An activity for accessibility test.
+ */
+public class AccessibilityTestActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ turnOnScreen();
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.accessibility_test);
+ }
+
+ private void turnOnScreen() {
+ setTurnScreenOn(true);
+ setShowWhenLocked(true);
+ KeyguardManager keyguardManager = (KeyguardManager) getSystemService(
+ Context.KEYGUARD_SERVICE);
+ keyguardManager.requestDismissKeyguard(this, null);
+ }
+}
diff --git a/media/Android.bp b/media/Android.bp
index 3181a2988d99..e7d5faf52d69 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -66,7 +66,9 @@ filegroup {
filegroup {
name: "media1-srcs",
srcs: [
+ "apex/java/android/media/MediaDescription.java",
"apex/java/android/media/MediaParceledListSlice.java",
+ "apex/java/android/media/Rating.java",
"apex/java/android/media/VolumeProvider.java",
"apex/java/android/media/browse/MediaBrowser.java",
"apex/java/android/media/browse/MediaBrowserUtils.java",
diff --git a/media/java/android/media/MediaDescription.aidl b/media/apex/java/android/media/MediaDescription.aidl
index 6f934f75aa28..6f934f75aa28 100644
--- a/media/java/android/media/MediaDescription.aidl
+++ b/media/apex/java/android/media/MediaDescription.aidl
diff --git a/media/java/android/media/MediaDescription.java b/media/apex/java/android/media/MediaDescription.java
index 31079e5c54d4..39eeb3eae49f 100644
--- a/media/java/android/media/MediaDescription.java
+++ b/media/apex/java/android/media/MediaDescription.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2019 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.media;
import android.annotation.Nullable;
@@ -226,7 +242,7 @@ public class MediaDescription implements Parcelable {
return false;
}
- if (!(o instanceof MediaDescription)){
+ if (!(o instanceof MediaDescription)) {
return false;
}
@@ -375,6 +391,11 @@ public class MediaDescription implements Parcelable {
return this;
}
+ /**
+ * Build {@link MediaDescription}.
+ *
+ * @return a new media description.
+ */
public MediaDescription build() {
return new MediaDescription(mMediaId, mTitle, mSubtitle, mDescription, mIcon, mIconUri,
mExtras, mMediaUri);
diff --git a/media/java/android/media/Rating.aidl b/media/apex/java/android/media/Rating.aidl
index 1dc336aeb79d..1dc336aeb79d 100644
--- a/media/java/android/media/Rating.aidl
+++ b/media/apex/java/android/media/Rating.aidl
diff --git a/media/java/android/media/Rating.java b/media/apex/java/android/media/Rating.java
index 04d5364f7c81..ffe7e48f25e4 100644
--- a/media/java/android/media/Rating.java
+++ b/media/apex/java/android/media/Rating.java
@@ -33,7 +33,7 @@ import java.lang.annotation.RetentionPolicy;
* through one of the factory methods.
*/
public final class Rating implements Parcelable {
- private final static String TAG = "Rating";
+ private static final String TAG = "Rating";
/**
* @hide
@@ -55,40 +55,40 @@ public final class Rating implements Parcelable {
* type, but can be used by other classes to indicate they do not support
* Rating.
*/
- public final static int RATING_NONE = 0;
+ public static final int RATING_NONE = 0;
/**
* A rating style with a single degree of rating, "heart" vs "no heart". Can be used to
* indicate the content referred to is a favorite (or not).
*/
- public final static int RATING_HEART = 1;
+ public static final int RATING_HEART = 1;
/**
* A rating style for "thumb up" vs "thumb down".
*/
- public final static int RATING_THUMB_UP_DOWN = 2;
+ public static final int RATING_THUMB_UP_DOWN = 2;
/**
* A rating style with 0 to 3 stars.
*/
- public final static int RATING_3_STARS = 3;
+ public static final int RATING_3_STARS = 3;
/**
* A rating style with 0 to 4 stars.
*/
- public final static int RATING_4_STARS = 4;
+ public static final int RATING_4_STARS = 4;
/**
* A rating style with 0 to 5 stars.
*/
- public final static int RATING_5_STARS = 5;
+ public static final int RATING_5_STARS = 5;
/**
* A rating style expressed as a percentage.
*/
- public final static int RATING_PERCENTAGE = 6;
+ public static final int RATING_PERCENTAGE = 6;
- private final static float RATING_NOT_RATED = -1.0f;
+ private static final float RATING_NOT_RATED = -1.0f;
private final int mRatingStyle;
@@ -116,8 +116,7 @@ public final class Rating implements Parcelable {
dest.writeFloat(mRatingValue);
}
- public static final Parcelable.Creator<Rating> CREATOR
- = new Parcelable.Creator<Rating>() {
+ public static final Parcelable.Creator<Rating> CREATOR = new Parcelable.Creator<Rating>() {
/**
* Rebuilds a Rating previously stored with writeToParcel().
* @param p Parcel object to read the Rating from
@@ -205,7 +204,7 @@ public final class Rating implements Parcelable {
break;
default:
Log.e(TAG, "Invalid rating style (" + starRatingStyle + ") for a star rating");
- return null;
+ return null;
}
if ((starRating < 0.0f) || (starRating > maxRating)) {
Log.e(TAG, "Trying to set out of range star-based rating");
@@ -281,16 +280,16 @@ public final class Rating implements Parcelable {
* not star-based, or if it is unrated.
*/
public float getStarRating() {
+ float ratingValue = -1.0f;
switch (mRatingStyle) {
case RATING_3_STARS:
case RATING_4_STARS:
case RATING_5_STARS:
if (isRated()) {
- return mRatingValue;
+ ratingValue = mRatingValue;
}
- default:
- return -1.0f;
}
+ return ratingValue;
}
/**
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index 010a810cd791..7fb51b9496b9 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -22,6 +22,7 @@
coreApp="true">
<uses-permission android:name="android.permission.PROVIDE_RESOLVER_RANKER_SERVICE" />
+ <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<application android:label="@string/app_name"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index f523481e61d4..ec70f8c32bcb 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -618,8 +618,6 @@
<string name="wifi_display_certification">Wireless display certification</string>
<!-- Setting Checkbox title whether to enable WiFi Verbose Logging. [CHAR LIMIT=40] -->
<string name="wifi_verbose_logging">Enable Wi\u2011Fi Verbose Logging</string>
- <!-- Setting Checkbox title whether to enable connected MAC randomization -->
- <string name="wifi_connected_mac_randomization">Connected MAC Randomization</string>
<!-- Setting Checkbox title whether to always keep mobile data active. [CHAR LIMIT=80] -->
<string name="mobile_data_always_on">Mobile data always active</string>
<!-- Setting Checkbox title whether to enable hardware acceleration for tethering. [CHAR LIMIT=80] -->
@@ -675,8 +673,6 @@
<string name="wifi_display_certification_summary">Show options for wireless display certification</string>
<!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR LIMIT=80] -->
<string name="wifi_verbose_logging_summary">Increase Wi\u2011Fi logging level, show per SSID RSSI in Wi\u2011Fi Picker</string>
- <!-- Setting Checkbox title whether to enable connected MAC randomization -->
- <string name="wifi_connected_mac_randomization_summary">Randomize MAC address when connecting to Wi\u2011Fi networks</string>
<!-- Label indicating network has been manually marked as metered -->
<string name="wifi_metered_label">Metered</string>
<!-- Label indicating network has been manually marked as unmetered -->
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 3877c90fee23..6ca8261ac4f9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1511,9 +1511,6 @@ class SettingsProtoDumpUtil {
Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED,
GlobalSettingsProto.Wifi.VERBOSE_LOGGING_ENABLED);
dumpSetting(s, p,
- Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED,
- GlobalSettingsProto.Wifi.CONNECTED_MAC_RANDOMIZATION_ENABLED);
- dumpSetting(s, p,
Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
GlobalSettingsProto.Wifi.MAX_DHCP_RETRY_COUNT);
dumpSetting(s, p,
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
index 968bd283c4b1..60dceef23f7c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
@@ -165,6 +165,11 @@ public class PipAccessibilityInteractionConnection
}
}
+ @Override
+ public void clearAccessibilityFocus() {
+ // We should not be here.
+ }
+
public static AccessibilityNodeInfo obtainRootAccessibilityNodeInfo() {
AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
info.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID,
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index f88d5217ab2f..47cd917bf84e 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3024,9 +3024,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
public void clearAccessibilityFocusNotLocked(int windowId) {
- AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(windowId);
- if (focus != null) {
- focus.performAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+ RemoteAccessibilityConnection connection;
+ synchronized (mLock) {
+ connection = getConnectionLocked(windowId);
+ if (connection == null) {
+ return;
+ }
+ }
+ try {
+ connection.getRemote().clearAccessibilityFocus();
+ } catch (RemoteException re) {
+ if (DEBUG) {
+ Slog.e(LOG_TAG, "Error calling clearAccessibilityFocus()");
+ }
}
}
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 84577f125f1d..4507193a5aff 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -21,6 +21,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.pm.VersionedPackage;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
@@ -230,7 +231,6 @@ public class PackageWatchdog {
return null;
}
- // TODO(zezeozue:) Accept current versionCodes of failing packages?
/**
* Called when a process fails either due to a crash or ANR.
*
@@ -239,15 +239,16 @@ public class PackageWatchdog {
*
* <p>This method could be called frequently if there is a severe problem on the device.
*/
- public void onPackageFailure(String[] packages) {
+ public void onPackageFailure(List<VersionedPackage> packages) {
mWorkerHandler.post(() -> {
synchronized (mLock) {
if (mAllObservers.isEmpty()) {
return;
}
- for (int pIndex = 0; pIndex < packages.length; pIndex++) {
- String packageToReport = packages[pIndex];
+ for (int pIndex = 0; pIndex < packages.size(); pIndex++) {
+ String packageToReport = packages.get(pIndex).getPackageName();
+ long packageVersionCode = packages.get(pIndex).getVersionCode();
// Observer that will receive failure for packageToReport
PackageHealthObserver currentObserverToNotify = null;
int currentObserverImpact = Integer.MAX_VALUE;
@@ -258,7 +259,8 @@ public class PackageWatchdog {
PackageHealthObserver registeredObserver = observer.mRegisteredObserver;
if (registeredObserver != null
&& observer.onPackageFailure(packageToReport)) {
- int impact = registeredObserver.onHealthCheckFailed(packageToReport);
+ int impact = registeredObserver.onHealthCheckFailed(packageToReport,
+ packageVersionCode);
if (impact != PackageHealthObserverImpact.USER_IMPACT_NONE
&& impact < currentObserverImpact) {
currentObserverToNotify = registeredObserver;
@@ -269,7 +271,7 @@ public class PackageWatchdog {
// Execute action with least user impact
if (currentObserverToNotify != null) {
- currentObserverToNotify.execute(packageToReport);
+ currentObserverToNotify.execute(packageToReport, packageVersionCode);
}
}
}
@@ -313,14 +315,14 @@ public class PackageWatchdog {
* @return any one of {@link PackageHealthObserverImpact} to express the impact
* to the user on {@link #execute}
*/
- @PackageHealthObserverImpact int onHealthCheckFailed(String packageName);
+ @PackageHealthObserverImpact int onHealthCheckFailed(String packageName, long versionCdoe);
/**
* Executes mitigation for {@link #onHealthCheckFailed}.
*
* @return {@code true} if action was executed successfully, {@code false} otherwise
*/
- boolean execute(String packageName);
+ boolean execute(String packageName, long versionCode);
// TODO(zezeozue): Ensure uniqueness?
/**
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index a634b577f506..f153ab9cfa9e 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -34,6 +34,7 @@ import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.content.pm.VersionedPackage;
import android.net.Uri;
import android.os.Binder;
import android.os.Message;
@@ -60,6 +61,7 @@ import com.android.server.wm.WindowProcessController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collections;
+import java.util.List;
/**
* Controls error conditions in applications.
@@ -411,7 +413,7 @@ class AppErrors {
} else {
// If a non-persistent app is stuck in crash loop, we want to inform
// the package watchdog, maybe an update or experiment can be rolled back.
- mPackageWatchdog.onPackageFailure(r.getPackageList());
+ mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode());
}
}
@@ -830,7 +832,7 @@ class AppErrors {
void handleShowAnrUi(Message msg) {
Dialog dialogToShow = null;
- String[] packageList = null;
+ List<VersionedPackage> packageList = null;
synchronized (mService) {
AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
final ProcessRecord proc = data.proc;
@@ -839,7 +841,7 @@ class AppErrors {
return;
}
if (!proc.isPersistent()) {
- packageList = proc.getPackageList();
+ packageList = proc.getPackageListWithVersionCode();
}
if (proc.anrDialog != null) {
Slog.e(TAG, "App already has anr dialog: " + proc);
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 580d6882a82e..7ae77d5f09dd 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -32,6 +32,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ServiceInfo;
+import android.content.pm.VersionedPackage;
import android.content.res.CompatibilityInfo;
import android.os.Binder;
import android.os.Debug;
@@ -66,6 +67,7 @@ import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
/**
* Full information about a particular process that
@@ -974,6 +976,18 @@ final class ProcessRecord implements WindowProcessListener {
return list;
}
+ public List<VersionedPackage> getPackageListWithVersionCode() {
+ int size = pkgList.size();
+ if (size == 0) {
+ return null;
+ }
+ List<VersionedPackage> list = new ArrayList<>();
+ for (int i = 0; i < pkgList.size(); i++) {
+ list.add(new VersionedPackage(pkgList.keyAt(i), pkgList.valueAt(i).appVersion));
+ }
+ return list;
+ }
+
WindowProcessController getWindowProcessController() {
return mWindowProcessController;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 6f1eeeb7de7a..dc18dfcf8613 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -61,6 +61,10 @@ import android.content.pm.dex.DexMetadataHelper;
import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
import android.content.res.AssetManager;
import android.content.res.Resources;
+import android.content.rollback.IRollbackManager;
+import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.RollbackInfo;
+import android.content.rollback.RollbackManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -263,6 +267,8 @@ class PackageManagerShellCommand extends ShellCommand {
return getStagedSessions();
case "uninstall-system-updates":
return uninstallSystemUpdates();
+ case "rollback-app":
+ return runRollbackApp();
default: {
String nextArg = getNextArg();
if (nextArg == null) {
@@ -348,6 +354,55 @@ class PackageManagerShellCommand extends ShellCommand {
return 1;
}
+ private int runRollbackApp() {
+ final PrintWriter pw = getOutPrintWriter();
+
+ final String packageName = getNextArgRequired();
+ if (packageName == null) {
+ pw.println("Error: package name not specified");
+ return 1;
+ }
+
+ final LocalIntentReceiver receiver = new LocalIntentReceiver();
+ try {
+ IRollbackManager rm = IRollbackManager.Stub.asInterface(
+ ServiceManager.getService(Context.ROLLBACK_SERVICE));
+
+ RollbackInfo rollback = null;
+ for (RollbackInfo r : (List<RollbackInfo>) rm.getAvailableRollbacks().getList()) {
+ for (PackageRollbackInfo info : r.getPackages()) {
+ if (packageName.equals(info.getPackageName())) {
+ rollback = r;
+ break;
+ }
+ }
+ }
+
+ if (rollback == null) {
+ pw.println("No available rollbacks for: " + packageName);
+ return 1;
+ }
+
+ rm.commitRollback(rollback.getRollbackId(),
+ ParceledListSlice.<VersionedPackage>emptyList(),
+ "com.android.shell", receiver.getIntentSender());
+ } catch (RemoteException re) {
+ // Cannot happen.
+ }
+
+ final Intent result = receiver.getResult();
+ final int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
+ RollbackManager.STATUS_FAILURE);
+ if (status == RollbackManager.STATUS_SUCCESS) {
+ pw.println("Success");
+ return 0;
+ } else {
+ pw.println("Failure ["
+ + result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE) + "]");
+ return 1;
+ }
+ }
+
private void setParamsSize(InstallParams params, String inPath) {
if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
final ParcelFileDescriptor fd = openFileForSystem(inPath, "r");
diff --git a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
new file mode 100644
index 000000000000..8dd076028b43
--- /dev/null
+++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.rollback;
+
+import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.PackageRollbackInfo.RestoreInfo;
+import android.content.rollback.RollbackInfo;
+import android.os.storage.StorageManager;
+import android.util.IntArray;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.pm.Installer;
+import com.android.server.pm.Installer.InstallerException;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Encapsulates the logic for initiating userdata snapshots and rollbacks via installd.
+ */
+@VisibleForTesting
+// TODO(narayan): Reason about the failure scenarios that involve one or more IPCs to installd
+// failing. We need to decide what course of action to take if calls to snapshotAppData or
+// restoreAppDataSnapshot fail.
+public class AppDataRollbackHelper {
+ private static final String TAG = "RollbackManager";
+
+ private final Installer mInstaller;
+
+ public AppDataRollbackHelper(Installer installer) {
+ mInstaller = installer;
+ }
+
+ /**
+ * Creates an app data snapshot for a specified {@code packageName} for {@code installedUsers},
+ * a specified set of users for whom the package is installed.
+ *
+ * @return a list of users for which the snapshot is pending, usually because data for one or
+ * more users is still credential locked.
+ */
+ public IntArray snapshotAppData(String packageName, int[] installedUsers) {
+ final IntArray pendingBackups = new IntArray();
+ for (int user : installedUsers) {
+ final int storageFlags;
+ if (isUserCredentialLocked(user)) {
+ // We've encountered a user that hasn't unlocked on a FBE device, so we can't copy
+ // across app user data until the user unlocks their device.
+ Log.v(TAG, "User: " + user + " isn't unlocked, skipping CE userdata backup.");
+ storageFlags = Installer.FLAG_STORAGE_DE;
+ pendingBackups.add(user);
+ } else {
+ storageFlags = Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE;
+ }
+
+ try {
+ mInstaller.snapshotAppData(packageName, user, storageFlags);
+ } catch (InstallerException ie) {
+ Log.e(TAG, "Unable to create app data snapshot for: " + packageName
+ + ", userId: " + user, ie);
+ }
+ }
+
+ return pendingBackups;
+ }
+
+ /**
+ * Restores an app data snapshot for a specified package ({@code packageName},
+ * {@code rollbackData}) for a specified {@code userId}.
+ *
+ * @return {@code true} iff. a change to the {@code rollbackData} has been made. Changes to
+ * {@code rollbackData} are restricted to the removal or addition of {@code userId} to
+ * the list of pending backups or restores.
+ */
+ public boolean restoreAppData(String packageName, RollbackData rollbackData,
+ int userId, int appId, long ceDataInode, String seInfo) {
+ if (rollbackData == null) {
+ return false;
+ }
+
+ if (!rollbackData.inProgress) {
+ Log.e(TAG, "Request to restore userData for: " + packageName
+ + ", but no rollback in progress.");
+ return false;
+ }
+
+ PackageRollbackInfo packageInfo = RollbackManagerServiceImpl.getPackageRollbackInfo(
+ rollbackData, packageName);
+ int storageFlags = Installer.FLAG_STORAGE_DE;
+
+ final IntArray pendingBackups = packageInfo.getPendingBackups();
+ final List<RestoreInfo> pendingRestores = packageInfo.getPendingRestores();
+ boolean changedRollbackData = false;
+
+ // If we still have a userdata backup pending for this user, it implies that the user
+ // hasn't unlocked their device between the point of backup and the point of restore,
+ // so the data cannot have changed. We simply skip restoring CE data in this case.
+ if (pendingBackups != null && pendingBackups.indexOf(userId) != -1) {
+ pendingBackups.remove(pendingBackups.indexOf(userId));
+ changedRollbackData = true;
+ } else {
+ // There's no pending CE backup for this user, which means that we successfully
+ // managed to backup data for the user, which means we seek to restore it
+ if (isUserCredentialLocked(userId)) {
+ // We've encountered a user that hasn't unlocked on a FBE device, so we can't
+ // copy across app user data until the user unlocks their device.
+ pendingRestores.add(new RestoreInfo(userId, appId, seInfo));
+ changedRollbackData = true;
+ } else {
+ // This user has unlocked, we can proceed to restore both CE and DE data.
+ storageFlags = storageFlags | Installer.FLAG_STORAGE_CE;
+ }
+ }
+
+ try {
+ mInstaller.restoreAppDataSnapshot(packageName, appId, ceDataInode,
+ seInfo, userId, storageFlags);
+ } catch (InstallerException ie) {
+ Log.e(TAG, "Unable to restore app data snapshot: " + packageName, ie);
+ }
+
+ return changedRollbackData;
+ }
+
+ /**
+ * Computes the list of pending backups and restores for {@code userId} given lists of
+ * available and recent rollbacks. Packages pending backup for the given user are added
+ * to {@code pendingBackups} and packages pending restore are added to {@code pendingRestores}
+ * along with their corresponding {@code RestoreInfo}.
+ *
+ * @return the list of {@code RollbackData} that have been modified during this computation.
+ */
+ public List<RollbackData> computePendingBackupsAndRestores(int userId,
+ ArrayList<String> pendingBackupPackages, Map<String, RestoreInfo> pendingRestores,
+ List<RollbackData> availableRollbacks, List<RollbackInfo> recentRollbacks) {
+ List<RollbackData> rd = new ArrayList<>();
+ // First check with the list of available rollbacks to see whether there are any
+ // pending backup operations that we've not managed to execute.
+ for (RollbackData data : availableRollbacks) {
+ for (PackageRollbackInfo info : data.packages) {
+ final IntArray pendingBackupUsers = info.getPendingBackups();
+ if (pendingBackupUsers != null) {
+ final int idx = pendingBackupUsers.indexOf(userId);
+ if (idx != -1) {
+ pendingBackupPackages.add(info.getPackageName());
+ pendingBackupUsers.remove(idx);
+ if (rd.indexOf(data) == -1) {
+ rd.add(data);
+ }
+ }
+ }
+ }
+ }
+
+ // Then check with the list of recently executed rollbacks to see whether there are
+ // any rollback operations
+ for (RollbackInfo data : recentRollbacks) {
+ for (PackageRollbackInfo info : data.getPackages()) {
+ final RestoreInfo ri = info.getRestoreInfo(userId);
+ if (ri != null) {
+ if (pendingBackupPackages.contains(info.getPackageName())) {
+ // This implies that the user hasn't unlocked their device between
+ // the request to backup data for this user and the request to restore
+ // it, so we do nothing here.
+ pendingBackupPackages.remove(info.getPackageName());
+ } else {
+ pendingRestores.put(info.getPackageName(), ri);
+ }
+
+ info.removeRestoreInfo(ri);
+ }
+ }
+ }
+
+ return rd;
+ }
+
+ /**
+ * Commits the list of pending backups and restores for a given {@code userId}.
+ */
+ public void commitPendingBackupAndRestoreForUser(int userId,
+ ArrayList<String> pendingBackups, Map<String, RestoreInfo> pendingRestores) {
+ if (!pendingBackups.isEmpty()) {
+ for (String packageName : pendingBackups) {
+ try {
+ mInstaller.snapshotAppData(packageName, userId, Installer.FLAG_STORAGE_CE);
+ } catch (InstallerException ie) {
+ Log.e(TAG, "Unable to create app data snapshot for: " + packageName, ie);
+ }
+ }
+ }
+
+ // TODO(narayan): Should we perform the restore before the backup for packages that have
+ // both backups and restores pending ? We could get into this case if we have a pending
+ // restore from a rollback + a snapshot request from a new restore.
+ if (!pendingRestores.isEmpty()) {
+ for (String packageName : pendingRestores.keySet()) {
+ try {
+ final RestoreInfo ri = pendingRestores.get(packageName);
+
+ // TODO(narayan): Verify that the user of "0" for ceDataInode is accurate
+ // here. We know that the user has unlocked (and that their CE data is
+ // available) so we shouldn't need to resort to the fallback path.
+ mInstaller.restoreAppDataSnapshot(packageName, ri.appId,
+ 0 /* ceDataInode */, ri.seInfo, userId, Installer.FLAG_STORAGE_CE);
+ } catch (InstallerException ie) {
+ Log.e(TAG, "Unable to restore app data snapshot for: " + packageName, ie);
+ }
+ }
+ }
+ }
+
+ /**
+ * @return {@code true} iff. {@code userId} is locked on an FBE device.
+ */
+ @VisibleForTesting
+ public boolean isUserCredentialLocked(int userId) {
+ return StorageManager.isFileEncryptedNativeOrEmulated()
+ && !StorageManager.isUserKeyUnlocked(userId);
+ }
+}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerService.java b/services/core/java/com/android/server/rollback/RollbackManagerService.java
index 4b5e76497f62..ba6cdddb4cc8 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerService.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerService.java
@@ -39,4 +39,9 @@ public final class RollbackManagerService extends SystemService {
mService = new RollbackManagerServiceImpl(getContext());
publishBinderService(Context.ROLLBACK_SERVICE, mService);
}
+
+ @Override
+ public void onUnlockUser(int user) {
+ mService.onUnlockUser(user);
+ }
}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 289618eb133c..5eb137b4c50c 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -31,6 +31,7 @@ import android.content.pm.ParceledListSlice;
import android.content.pm.VersionedPackage;
import android.content.rollback.IRollbackManager;
import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.PackageRollbackInfo.RestoreInfo;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
import android.os.Binder;
@@ -39,14 +40,13 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
import android.os.Process;
-import android.os.storage.StorageManager;
+import android.util.IntArray;
import android.util.Log;
import android.util.SparseBooleanArray;
import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalServices;
import com.android.server.pm.Installer;
-import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.PackageManagerServiceUtils;
import java.io.File;
@@ -111,6 +111,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
private final HandlerThread mHandlerThread;
private final Installer mInstaller;
private final RollbackPackageHealthObserver mPackageHealthObserver;
+ private final AppDataRollbackHelper mUserdataHelper;
RollbackManagerServiceImpl(Context context) {
mContext = context;
@@ -124,6 +125,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
mRollbackStore = new RollbackStore(new File(Environment.getDataDirectory(), "rollback"));
mPackageHealthObserver = new RollbackPackageHealthObserver(mContext);
+ mUserdataHelper = new AppDataRollbackHelper(mInstaller);
// Kick off loading of the rollback data from strorage in a background
// thread.
@@ -424,6 +426,35 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
}
}
+ void onUnlockUser(int userId) {
+ getHandler().post(() -> {
+ final ArrayList<String> pendingBackupPackages = new ArrayList<>();
+ final Map<String, RestoreInfo> pendingRestorePackages = new HashMap<>();
+ final List<RollbackData> changed;
+ synchronized (mLock) {
+ ensureRollbackDataLoadedLocked();
+ changed = mUserdataHelper.computePendingBackupsAndRestores(userId,
+ pendingBackupPackages, pendingRestorePackages, mAvailableRollbacks,
+ mRecentlyExecutedRollbacks);
+ }
+
+ mUserdataHelper.commitPendingBackupAndRestoreForUser(userId,
+ pendingBackupPackages, pendingRestorePackages);
+
+ for (RollbackData rd : changed) {
+ try {
+ mRollbackStore.saveAvailableRollback(rd);
+ } catch (IOException ioe) {
+ Log.e(TAG, "Unable to save rollback info for : " + rd.rollbackId, ioe);
+ }
+ }
+
+ synchronized (mLock) {
+ mRollbackStore.saveRecentlyExecutedRollbacks(mRecentlyExecutedRollbacks);
+ }
+ });
+ }
+
/**
* Load rollback data from storage if it has not already been loaded.
* After calling this funciton, mAvailableRollbacks and
@@ -533,6 +564,20 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// that are necessary to keep track of.
synchronized (mLock) {
ensureRollbackDataLoadedLocked();
+
+ // This should never happen because we can't have any pending backups left after
+ // a rollback has been executed. See AppDataRollbackHelper#restoreAppData where we
+ // clear all pending backups at the point of restore because they're guaranteed to be
+ // no-ops.
+ //
+ // We may, however, have one or more pending restores left to handle.
+ for (PackageRollbackInfo target : rollback.getPackages()) {
+ if (target.getPendingBackups().size() > 0) {
+ Log.e(TAG, "No backups allowed to be pending for: " + target);
+ target.getPendingBackups().clear();
+ }
+ }
+
mRecentlyExecutedRollbacks.add(rollback);
mRollbackStore.saveRecentlyExecutedRollbacks(mRecentlyExecutedRollbacks);
}
@@ -701,27 +746,12 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
VersionedPackage installedVersion = new VersionedPackage(packageName,
installedPackage.getLongVersionCode());
- for (int user : installedUsers) {
- final int storageFlags;
- if (StorageManager.isFileEncryptedNativeOrEmulated()
- && !StorageManager.isUserKeyUnlocked(user)) {
- // We've encountered a user that hasn't unlocked on a FBE device, so we can't copy
- // across app user data until the user unlocks their device.
- Log.e(TAG, "User: " + user + " isn't unlocked, skipping CE userdata backup.");
- storageFlags = Installer.FLAG_STORAGE_DE;
- } else {
- storageFlags = Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE;
- }
-
- try {
- mInstaller.snapshotAppData(packageName, user, storageFlags);
- } catch (InstallerException ie) {
- Log.e(TAG, "Unable to create app data snapshot for: " + packageName, ie);
- }
- }
- PackageRollbackInfo info = new PackageRollbackInfo(newVersion, installedVersion);
+ final IntArray pendingBackups = mUserdataHelper.snapshotAppData(packageName,
+ installedUsers);
+ PackageRollbackInfo info = new PackageRollbackInfo(newVersion, installedVersion,
+ pendingBackups, new ArrayList<>());
RollbackData data;
try {
synchronized (mLock) {
@@ -760,40 +790,24 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
}
getHandler().post(() -> {
- PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
final RollbackData rollbackData = getRollbackForPackage(packageName);
- if (rollbackData == null) {
- pmi.finishPackageInstall(token, false);
- return;
- }
-
- if (!rollbackData.inProgress) {
- Log.e(TAG, "Request to restore userData for: " + packageName
- + ", but no rollback in progress.");
- pmi.finishPackageInstall(token, false);
- return;
- }
-
- final int storageFlags;
- if (StorageManager.isFileEncryptedNativeOrEmulated()
- && !StorageManager.isUserKeyUnlocked(userId)) {
- // We've encountered a user that hasn't unlocked on a FBE device, so we can't copy
- // across app user data until the user unlocks their device.
- Log.e(TAG, "User: " + userId + " isn't unlocked, skipping CE userdata restore.");
-
- storageFlags = Installer.FLAG_STORAGE_DE;
- } else {
- storageFlags = Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE;
- }
+ final boolean changedRollbackData = mUserdataHelper.restoreAppData(packageName,
+ rollbackData, userId, appId, ceDataInode, seInfo);
+ final PackageManagerInternal pmi = LocalServices.getService(
+ PackageManagerInternal.class);
+ pmi.finishPackageInstall(token, false);
- try {
- mInstaller.restoreAppDataSnapshot(packageName, appId, ceDataInode,
- seInfo, userId, storageFlags);
- } catch (InstallerException ie) {
- Log.e(TAG, "Unable to restore app data snapshot: " + packageName, ie);
+ // We've updated metadata about this rollback, so save it to flash.
+ if (changedRollbackData) {
+ try {
+ mRollbackStore.saveAvailableRollback(rollbackData);
+ } catch (IOException ioe) {
+ // TODO(narayan): What is the right thing to do here ? This isn't a fatal error,
+ // since it will only result in us trying to restore data again, which will be
+ // a no-op if there's no data available.
+ Log.e(TAG, "Unable to save available rollback: " + packageName, ioe);
+ }
}
-
- pmi.finishPackageInstall(token, false);
});
}
@@ -900,10 +914,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
ensureRollbackDataLoadedLocked();
for (int i = 0; i < mAvailableRollbacks.size(); ++i) {
RollbackData data = mAvailableRollbacks.get(i);
- for (PackageRollbackInfo info : data.packages) {
- if (info.getPackageName().equals(packageName)) {
- return data;
- }
+ if (getPackageRollbackInfo(data, packageName) != null) {
+ return data;
}
}
}
@@ -926,6 +938,22 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
}
}
}
+
+ return null;
+ }
+
+ /**
+ * Returns the {@code PackageRollbackInfo} associated with {@code packageName} from
+ * a specified {@code RollbackData}.
+ */
+ static PackageRollbackInfo getPackageRollbackInfo(RollbackData data,
+ String packageName) {
+ for (PackageRollbackInfo info : data.packages) {
+ if (info.getPackageName().equals(packageName)) {
+ return info;
+ }
+ }
+
return null;
}
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 28801038ebd1..f50e776ad22d 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -54,8 +54,8 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
}
@Override
- public int onHealthCheckFailed(String packageName) {
- RollbackInfo rollback = getAvailableRollback(packageName);
+ public int onHealthCheckFailed(String packageName, long versionCode) {
+ RollbackInfo rollback = getAvailableRollback(packageName, versionCode);
if (rollback == null) {
// Don't handle the notification, no rollbacks available for the package
return PackageHealthObserverImpact.USER_IMPACT_NONE;
@@ -65,8 +65,8 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
}
@Override
- public boolean execute(String packageName) {
- RollbackInfo rollback = getAvailableRollback(packageName);
+ public boolean execute(String packageName, long versionCode) {
+ RollbackInfo rollback = getAvailableRollback(packageName, versionCode);
if (rollback == null) {
// Expected a rollback to be available, what happened?
return false;
@@ -110,11 +110,12 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
PackageWatchdog.getInstance(mContext).startObservingHealth(this, packages, durationMs);
}
- private RollbackInfo getAvailableRollback(String packageName) {
+ private RollbackInfo getAvailableRollback(String packageName, long versionCode) {
for (RollbackInfo rollback : mRollbackManager.getAvailableRollbacks()) {
for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
- if (packageName.equals(packageRollback.getPackageName())) {
- // TODO(zezeozue): Only rollback if rollback version == failed package version
+ if (packageName.equals(packageRollback.getPackageName())
+ && packageRollback.getVersionRolledBackFrom().getVersionCode()
+ == versionCode) {
return rollback;
}
}
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 98ebb0943f43..c70f47dc5ed3 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -16,9 +16,12 @@
package com.android.server.rollback;
+import android.annotation.NonNull;
import android.content.pm.VersionedPackage;
import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.PackageRollbackInfo.RestoreInfo;
import android.content.rollback.RollbackInfo;
+import android.util.IntArray;
import android.util.Log;
import libcore.io.IoUtils;
@@ -99,6 +102,64 @@ class RollbackStore {
}
/**
+ * Converts an {@code JSONArray} of integers to an {@code IntArray}.
+ */
+ private static @NonNull IntArray convertToIntArray(@NonNull JSONArray jsonArray)
+ throws JSONException {
+ if (jsonArray.length() == 0) {
+ return new IntArray();
+ }
+
+ final int[] ret = new int[jsonArray.length()];
+ for (int i = 0; i < ret.length; ++i) {
+ ret[i] = jsonArray.getInt(i);
+ }
+
+ return IntArray.wrap(ret);
+ }
+
+ /**
+ * Converts an {@code IntArray} into an {@code JSONArray} of integers.
+ */
+ private static @NonNull JSONArray convertToJsonArray(@NonNull IntArray intArray) {
+ JSONArray jsonArray = new JSONArray();
+ for (int i = 0; i < intArray.size(); ++i) {
+ jsonArray.put(intArray.get(i));
+ }
+
+ return jsonArray;
+ }
+
+ private static @NonNull JSONArray convertToJsonArray(@NonNull List<RestoreInfo> list)
+ throws JSONException {
+ JSONArray jsonArray = new JSONArray();
+ for (RestoreInfo ri : list) {
+ JSONObject jo = new JSONObject();
+ jo.put("userId", ri.userId);
+ jo.put("appId", ri.appId);
+ jo.put("seInfo", ri.seInfo);
+ jsonArray.put(jo);
+ }
+
+ return jsonArray;
+ }
+
+ private static @NonNull ArrayList<RestoreInfo> convertToRestoreInfoArray(
+ @NonNull JSONArray array) throws JSONException {
+ ArrayList<RestoreInfo> restoreInfos = new ArrayList<>();
+
+ for (int i = 0; i < array.length(); ++i) {
+ JSONObject jo = array.getJSONObject(i);
+ restoreInfos.add(new RestoreInfo(
+ jo.getInt("userId"),
+ jo.getInt("appId"),
+ jo.getString("seInfo")));
+ }
+
+ return restoreInfos;
+ }
+
+ /**
* Reads the list of recently executed rollbacks from persistent storage.
*/
List<RollbackInfo> loadRecentlyExecutedRollbacks() {
@@ -239,6 +300,12 @@ class RollbackStore {
JSONObject json = new JSONObject();
json.put("versionRolledBackFrom", toJson(info.getVersionRolledBackFrom()));
json.put("versionRolledBackTo", toJson(info.getVersionRolledBackTo()));
+
+ IntArray pendingBackups = info.getPendingBackups();
+ List<RestoreInfo> pendingRestores = info.getPendingRestores();
+ json.put("pendingBackups", convertToJsonArray(pendingBackups));
+ json.put("pendingRestores", convertToJsonArray(pendingRestores));
+
return json;
}
@@ -247,7 +314,14 @@ class RollbackStore {
json.getJSONObject("versionRolledBackFrom"));
VersionedPackage versionRolledBackTo = versionedPackageFromJson(
json.getJSONObject("versionRolledBackTo"));
- return new PackageRollbackInfo(versionRolledBackFrom, versionRolledBackTo);
+
+ final IntArray pendingBackups = convertToIntArray(
+ json.getJSONArray("pendingBackups"));
+ final ArrayList<RestoreInfo> pendingRestores = convertToRestoreInfoArray(
+ json.getJSONArray("pendingRestores"));
+
+ return new PackageRollbackInfo(versionRolledBackFrom, versionRolledBackTo,
+ pendingBackups, pendingRestores);
}
private JSONArray versionedPackagesToJson(List<VersionedPackage> packages)
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 3426ba611c86..a8492fbb4160 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -29,6 +29,7 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_PRIVATE;
+import static android.view.Display.INVALID_DISPLAY;
import static android.view.InsetsState.TYPE_IME;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
@@ -43,6 +44,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
@@ -140,9 +142,11 @@ import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Region.Op;
import android.hardware.display.DisplayManagerInternal;
+import android.os.Binder;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
@@ -157,6 +161,7 @@ import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.InputChannel;
import android.view.InputDevice;
+import android.view.InputWindowHandle;
import android.view.InsetsState.InternalInsetType;
import android.view.MagnificationSpec;
import android.view.RemoteAnimationDefinition;
@@ -515,6 +520,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
private final InsetsStateController mInsetsStateController;
+ private SurfaceControl mParentSurfaceControl;
+ private InputWindowHandle mPortalWindowHandle;
+
// Last systemUiVisibility we received from status bar.
private int mLastStatusBarVisibility = 0;
// Last systemUiVisibility we dispatched to windows.
@@ -2410,10 +2418,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
win.getTouchableRegion(mTmpRegion);
mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
}
- for (int i = mTapExcludeProvidingWindows.size() - 1; i >= 0; i--) {
- final WindowState win = mTapExcludeProvidingWindows.valueAt(i);
- win.amendTapExcludeRegion(mTouchExcludeRegion);
- }
+ amendWindowTapExcludeRegion(mTouchExcludeRegion);
// TODO(multi-display): Support docked stacks on secondary displays.
if (mDisplayId == DEFAULT_DISPLAY && getSplitScreenPrimaryStack() != null) {
mDividerControllerLocked.getTouchRegion(mTmpRect);
@@ -2425,6 +2430,18 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
}
+ /**
+ * Union the region with all the tap exclude region provided by windows on this display.
+ *
+ * @param inOutRegion The region to be amended.
+ */
+ void amendWindowTapExcludeRegion(Region inOutRegion) {
+ for (int i = mTapExcludeProvidingWindows.size() - 1; i >= 0; i--) {
+ final WindowState win = mTapExcludeProvidingWindows.valueAt(i);
+ win.amendTapExcludeRegion(inOutRegion);
+ }
+ }
+
@Override
void switchUser() {
super.switchUser();
@@ -3586,6 +3603,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
private void updateBounds() {
calculateBounds(mDisplayInfo, mTmpBounds);
setBounds(mTmpBounds);
+ if (mPortalWindowHandle != null && mParentSurfaceControl != null) {
+ mPortalWindowHandle.touchableRegion.getBounds(mTmpRect);
+ if (!mTmpBounds.equals(mTmpRect)) {
+ mPortalWindowHandle.touchableRegion.set(mTmpBounds);
+ mPendingTransaction.setInputWindowInfo(mParentSurfaceControl, mPortalWindowHandle);
+ }
+ }
}
// Determines the current display bounds based on the current state
@@ -4830,15 +4854,43 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|| mWmService.mForceDesktopModeOnExternalDisplays;
}
- /**
+ /**
* Re-parent the DisplayContent's top surfaces, {@link #mWindowingLayer} and
* {@link #mOverlayLayer} to the specified surfaceControl.
*
- * @param surfaceControlHandle The new SurfaceControl, where the DisplayContent's
- * surfaces will be re-parented to.
+ * @param sc The new SurfaceControl, where the DisplayContent's surfaces will be re-parented to.
*/
void reparentDisplayContent(SurfaceControl sc) {
- mPendingTransaction.reparent(mWindowingLayer, sc)
- .reparent(mOverlayLayer, sc);
+ mParentSurfaceControl = sc;
+ if (mPortalWindowHandle == null) {
+ mPortalWindowHandle = createPortalWindowHandle(sc.toString());
+ }
+ mPendingTransaction.setInputWindowInfo(sc, mPortalWindowHandle)
+ .reparent(mWindowingLayer, sc).reparent(mOverlayLayer, sc);
+ }
+
+ /**
+ * Create a portal window handle for input. This window transports any touch to the display
+ * indicated by {@link InputWindowHandle#portalToDisplayId} if the touch hits this window.
+ *
+ * @param name The name of the portal window handle.
+ * @return the new portal window handle.
+ */
+ private InputWindowHandle createPortalWindowHandle(String name) {
+ // Let surface flinger to set the display ID of this input window handle because we don't
+ // know which display the parent surface control is on.
+ final InputWindowHandle portalWindowHandle = new InputWindowHandle(
+ null /* inputApplicationHandle */, null /* clientWindow */, INVALID_DISPLAY);
+ portalWindowHandle.name = name;
+ portalWindowHandle.token = new Binder();
+ portalWindowHandle.layoutParamsFlags =
+ FLAG_SPLIT_TOUCH | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL;
+ getBounds(mTmpBounds);
+ portalWindowHandle.touchableRegion.set(mTmpBounds);
+ portalWindowHandle.scaleFactor = 1f;
+ portalWindowHandle.ownerPid = Process.myPid();
+ portalWindowHandle.ownerUid = Process.myUid();
+ portalWindowHandle.portalToDisplayId = mDisplayId;
+ return portalWindowHandle;
}
}
diff --git a/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java b/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java
index cbc936f2f1d7..0a4ab67f033d 100644
--- a/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java
+++ b/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java
@@ -49,7 +49,9 @@ class TapExcludeRegionHolder {
void amendRegion(Region region, Rect boundingRegion) {
for (int i = mTapExcludeRects.size() - 1; i>= 0 ; --i) {
final Rect rect = mTapExcludeRects.valueAt(i);
- rect.intersect(boundingRegion);
+ if (boundingRegion != null) {
+ rect.intersect(boundingRegion);
+ }
region.union(rect);
}
}
diff --git a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
index 2e5df45f9080..dd94af657039 100644
--- a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
@@ -70,6 +70,18 @@ public class TaskTapPointerEventListener implements PointerEventListener {
// method target window will lose the focus.
return;
}
+ final Region windowTapExcludeRegion = Region.obtain();
+ mDisplayContent.amendWindowTapExcludeRegion(windowTapExcludeRegion);
+ if (windowTapExcludeRegion.contains(x, y)) {
+ windowTapExcludeRegion.recycle();
+ // The user is tapping on the window tap exclude region. We don't move this
+ // display to top. A window tap exclude region, for example, may be set by an
+ // ActivityView, and the region would match the bounds of both the ActivityView
+ // and the virtual display in it. In this case, we would take the tap that is on
+ // the embedded virtual display instead of this display.
+ return;
+ }
+ windowTapExcludeRegion.recycle();
WindowContainer parent = mDisplayContent.getParent();
if (parent != null && parent.getTopChild() != mDisplayContent) {
parent.positionChildAt(WindowContainer.POSITION_TOP, mDisplayContent,
@@ -81,9 +93,6 @@ public class TaskTapPointerEventListener implements PointerEventListener {
@Override
public void onPointerEvent(MotionEvent motionEvent) {
- if (motionEvent.getDisplayId() != getDisplayId()) {
- return;
- }
switch (motionEvent.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
final int x = (int) motionEvent.getX();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 752c24e7edb6..975e62a44b0a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -6532,8 +6532,13 @@ public class WindowManagerService extends IWindowManager.Stub
/**
* Update a tap exclude region with a rectangular area in the window identified by the provided
- * id. Touches on this region will not switch focus to this window. Passing an empty rect will
- * remove the area from the exclude region of this window.
+ * id. Touches down on this region will not:
+ * <ol>
+ * <li>Switch focus to this window.</li>
+ * <li>Move the display of this window to top.</li>
+ * <li>Send the touch events to this window.</li>
+ * </ol>
+ * Passing an empty rect will remove the area from the exclude region of this window.
*/
void updateTapExcludeRegion(IWindow client, int regionId, int left, int top, int width,
int height) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 4f120100693a..62e7200ef112 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -536,7 +536,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
private final Point mSurfacePosition = new Point();
/**
- * A region inside of this window to be excluded from touch-related focus switches.
+ * A region inside of this window to be excluded from touch.
*/
private TapExcludeRegionHolder mTapExcludeRegionHolder;
@@ -2168,6 +2168,24 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
region.set(mTmpRect);
cropRegionToStackBoundsIfNeeded(region);
+ subtractTouchExcludeRegionIfNeeded(region);
+ } else if (modal && mTapExcludeRegionHolder != null) {
+ final Region touchExcludeRegion = Region.obtain();
+ amendTapExcludeRegion(touchExcludeRegion);
+ if (!touchExcludeRegion.isEmpty()) {
+ // Remove touch modal because there are some areas that cannot be touched.
+ flags |= FLAG_NOT_TOUCH_MODAL;
+ // Give it a large touchable region at first because it was touch modal. The window
+ // might be moved on the display, so the touchable region should be large enough to
+ // ensure it covers the whole display, no matter where it is moved.
+ getDisplayContent().getBounds(mTmpRect);
+ final int dw = mTmpRect.width();
+ final int dh = mTmpRect.height();
+ region.set(-dw, -dh, dw + dw, dh + dh);
+ // Subtract the area that cannot be touched.
+ region.op(touchExcludeRegion, Region.Op.DIFFERENCE);
+ }
+ touchExcludeRegion.recycle();
} else {
// Not modal or full screen modal
getTouchableRegion(region);
@@ -2837,6 +2855,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
}
cropRegionToStackBoundsIfNeeded(outRegion);
+ subtractTouchExcludeRegionIfNeeded(outRegion);
}
private void cropRegionToStackBoundsIfNeeded(Region region) {
@@ -2855,6 +2874,22 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
/**
+ * If this window has areas that cannot be touched, we subtract those areas from its touchable
+ * region.
+ */
+ private void subtractTouchExcludeRegionIfNeeded(Region touchableRegion) {
+ if (mTapExcludeRegionHolder == null) {
+ return;
+ }
+ final Region touchExcludeRegion = Region.obtain();
+ amendTapExcludeRegion(touchExcludeRegion);
+ if (!touchExcludeRegion.isEmpty()) {
+ touchableRegion.op(touchExcludeRegion, Region.Op.DIFFERENCE);
+ }
+ touchExcludeRegion.recycle();
+ }
+
+ /**
* Report a focus change. Must be called with no locks held, and consistently
* from the same serialized thread (such as dispatched from a handler).
*/
@@ -4728,11 +4763,25 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mTapExcludeRegionHolder.updateRegion(regionId, left, top, width, height);
// Trigger touch exclude region update on current display.
currentDisplay.updateTouchExcludeRegion();
+ // Trigger touchable region update for this window.
+ currentDisplay.getInputMonitor().updateInputWindowsLw(true /* force */);
}
- /** Union the region with current tap exclude region that this window provides. */
+ /**
+ * Union the region with current tap exclude region that this window provides.
+ *
+ * @param region The region to be amended. It is on the screen coordinates.
+ */
void amendTapExcludeRegion(Region region) {
- mTapExcludeRegionHolder.amendRegion(region, getBounds());
+ final Region tempRegion = Region.obtain();
+ mTmpRect.set(mWindowFrames.mFrame);
+ mTmpRect.offsetTo(0, 0);
+ mTapExcludeRegionHolder.amendRegion(tempRegion, mTmpRect);
+ // The region held by the holder is on the window coordinates. We need to translate it to
+ // the screen coordinates.
+ tempRegion.translate(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top);
+ region.op(tempRegion, Region.Op.UNION);
+ tempRegion.recycle();
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
new file mode 100644
index 000000000000..33cbf7ae8ba6
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.rollback;
+
+import static org.junit.Assert.*;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.content.pm.VersionedPackage;
+import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.PackageRollbackInfo.RestoreInfo;
+import android.util.IntArray;
+
+import com.android.server.pm.Installer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+
+import java.io.File;
+import java.util.ArrayList;
+
+@RunWith(JUnit4.class)
+public class AppDataRollbackHelperTest {
+
+ @Test
+ public void testSnapshotAppData() throws Exception {
+ Installer installer = mock(Installer.class);
+ AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
+
+ // All users are unlocked so we should snapshot data for them.
+ doReturn(true).when(helper).isUserCredentialLocked(eq(10));
+ doReturn(true).when(helper).isUserCredentialLocked(eq(11));
+ IntArray pending = helper.snapshotAppData("com.foo.bar", new int[]{10, 11});
+ assertEquals(2, pending.size());
+ assertEquals(10, pending.get(0));
+ assertEquals(11, pending.get(1));
+
+ InOrder inOrder = Mockito.inOrder(installer);
+ inOrder.verify(installer).snapshotAppData(
+ eq("com.foo.bar"), eq(10), eq(Installer.FLAG_STORAGE_DE));
+ inOrder.verify(installer).snapshotAppData(
+ eq("com.foo.bar"), eq(11), eq(Installer.FLAG_STORAGE_DE));
+ inOrder.verifyNoMoreInteractions();
+
+ // One of the users is unlocked but the other isn't
+ doReturn(false).when(helper).isUserCredentialLocked(eq(10));
+ doReturn(true).when(helper).isUserCredentialLocked(eq(11));
+
+ pending = helper.snapshotAppData("com.foo.bar", new int[]{10, 11});
+ assertEquals(1, pending.size());
+ assertEquals(11, pending.get(0));
+
+ inOrder = Mockito.inOrder(installer);
+ inOrder.verify(installer).snapshotAppData(
+ eq("com.foo.bar"), eq(10),
+ eq(Installer.FLAG_STORAGE_CE | Installer.FLAG_STORAGE_DE));
+ inOrder.verify(installer).snapshotAppData(
+ eq("com.foo.bar"), eq(11), eq(Installer.FLAG_STORAGE_DE));
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ private static RollbackData createInProgressRollbackData(String packageName) {
+ RollbackData data = new RollbackData(1, new File("/does/not/exist"));
+ data.packages.add(new PackageRollbackInfo(
+ new VersionedPackage(packageName, 1), new VersionedPackage(packageName, 1),
+ new IntArray(), new ArrayList<>()));
+ data.inProgress = true;
+
+ return data;
+ }
+
+ @Test
+ public void testRestoreAppDataSnapshot_noRollbackData() throws Exception {
+ Installer installer = mock(Installer.class);
+ AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
+
+ assertFalse(helper.restoreAppData("com.foo", null, 0, 0, 0, "seinfo"));
+ verifyZeroInteractions(installer);
+ }
+
+ @Test
+ public void testRestoreAppDataSnapshot_noRollbackInProgress() throws Exception {
+ Installer installer = mock(Installer.class);
+ AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
+
+ RollbackData rd = createInProgressRollbackData("com.foo");
+ // Override the in progress flag.
+ rd.inProgress = false;
+ assertFalse(helper.restoreAppData("com.foo", rd, 0, 0, 0, "seinfo"));
+ verifyZeroInteractions(installer);
+ }
+
+ @Test
+ public void testRestoreAppDataSnapshot_pendingBackupForUser() throws Exception {
+ Installer installer = mock(Installer.class);
+ AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
+
+ RollbackData rd = createInProgressRollbackData("com.foo");
+ IntArray pendingBackups = rd.packages.get(0).getPendingBackups();
+ pendingBackups.add(10);
+ pendingBackups.add(11);
+
+ assertTrue(helper.restoreAppData("com.foo", rd, 10 /* userId */, 1, 2, "seinfo"));
+
+ // Should only require FLAG_STORAGE_DE here because we have a pending backup that we
+ // didn't manage to execute.
+ InOrder inOrder = Mockito.inOrder(installer);
+ inOrder.verify(installer).restoreAppDataSnapshot(
+ eq("com.foo"), eq(1), eq(2L), eq("seinfo"), eq(10), eq(Installer.FLAG_STORAGE_DE));
+ inOrder.verifyNoMoreInteractions();
+
+ assertEquals(1, pendingBackups.size());
+ assertEquals(11, pendingBackups.get(0));
+ }
+
+ @Test
+ public void testRestoreAppDataSnapshot_availableBackupForLockedUser() throws Exception {
+ Installer installer = mock(Installer.class);
+ AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
+ doReturn(true).when(helper).isUserCredentialLocked(eq(10));
+
+ RollbackData rd = createInProgressRollbackData("com.foo");
+
+ assertTrue(helper.restoreAppData("com.foo", rd, 10 /* userId */, 1, 2, "seinfo"));
+
+ InOrder inOrder = Mockito.inOrder(installer);
+ inOrder.verify(installer).restoreAppDataSnapshot(
+ eq("com.foo"), eq(1), eq(2L), eq("seinfo"), eq(10), eq(Installer.FLAG_STORAGE_DE));
+ inOrder.verifyNoMoreInteractions();
+
+ ArrayList<RestoreInfo> pendingRestores = rd.packages.get(0).getPendingRestores();
+ assertEquals(1, pendingRestores.size());
+ assertEquals(10, pendingRestores.get(0).userId);
+ assertEquals(1, pendingRestores.get(0).appId);
+ assertEquals("seinfo", pendingRestores.get(0).seInfo);
+ }
+
+ @Test
+ public void testRestoreAppDataSnapshot_availableBackupForUnockedUser() throws Exception {
+ Installer installer = mock(Installer.class);
+ AppDataRollbackHelper helper = spy(new AppDataRollbackHelper(installer));
+ doReturn(false).when(helper).isUserCredentialLocked(eq(10));
+
+ RollbackData rd = createInProgressRollbackData("com.foo");
+ assertFalse(helper.restoreAppData("com.foo", rd, 10 /* userId */, 1, 2, "seinfo"));
+
+ InOrder inOrder = Mockito.inOrder(installer);
+ inOrder.verify(installer).restoreAppDataSnapshot(
+ eq("com.foo"), eq(1), eq(2L), eq("seinfo"), eq(10),
+ eq(Installer.FLAG_STORAGE_DE | Installer.FLAG_STORAGE_CE));
+ inOrder.verifyNoMoreInteractions();
+
+ ArrayList<RestoreInfo> pendingRestores = rd.packages.get(0).getPendingRestores();
+ assertEquals(0, pendingRestores.size());
+ }
+}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 44756307a4b3..33178766f3a3 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -540,7 +540,7 @@ public class ServiceState implements Parcelable {
*
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
public int getDataRegState() {
return mDataRegState;
}
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 86af6422dad3..c1c598d52676 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import android.content.pm.VersionedPackage;
import android.os.test.TestLooper;
import android.support.test.InstrumentationRegistry;
@@ -47,6 +48,7 @@ public class PackageWatchdogTest {
private static final String APP_B = "com.package.b";
private static final String APP_C = "com.package.c";
private static final String APP_D = "com.package.d";
+ private static final long VERSION_CODE = 1L;
private static final String OBSERVER_NAME_1 = "observer1";
private static final String OBSERVER_NAME_2 = "observer2";
private static final String OBSERVER_NAME_3 = "observer3";
@@ -193,7 +195,7 @@ public class PackageWatchdogTest {
// Then fail APP_A below the threshold
for (int i = 0; i < TRIGGER_FAILURE_COUNT - 1; i++) {
- watchdog.onPackageFailure(new String[]{APP_A});
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
}
// Run handler so package failures are dispatched to observers
@@ -209,12 +211,10 @@ public class PackageWatchdogTest {
* the failed packages.
*/
@Test
- public void testPackageFailureNotifyNone() throws Exception {
+ public void testPackageFailureDifferentPackageNotifyNone() throws Exception {
PackageWatchdog watchdog = createWatchdog();
- TestObserver observer1 = new TestObserver(OBSERVER_NAME_1,
- PackageHealthObserverImpact.USER_IMPACT_HIGH);
- TestObserver observer2 = new TestObserver(OBSERVER_NAME_2,
- PackageHealthObserverImpact.USER_IMPACT_HIGH);
+ TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
+ TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION);
@@ -222,7 +222,7 @@ public class PackageWatchdogTest {
// Then fail APP_C (not observed) above the threshold
for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
- watchdog.onPackageFailure(new String[]{APP_C});
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE)));
}
// Run handler so package failures are dispatched to observers
@@ -234,6 +234,40 @@ public class PackageWatchdogTest {
}
/**
+ * Test package failure and does not notify any observer because the failed package version
+ * does not match the available rollback-from-version.
+ */
+ @Test
+ public void testPackageFailureDifferentVersionNotifyNone() throws Exception {
+ PackageWatchdog watchdog = createWatchdog();
+ long differentVersionCode = 2L;
+ TestObserver observer = new TestObserver(OBSERVER_NAME_1) {
+ public int onHealthCheckFailed(String packageName, long versionCode) {
+ if (versionCode == VERSION_CODE) {
+ // Only rollback for specific versionCode
+ return PackageHealthObserverImpact.USER_IMPACT_MEDIUM;
+ }
+ return PackageHealthObserverImpact.USER_IMPACT_NONE;
+ }
+ };
+
+ watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
+
+ // Then fail APP_A (different version) above the threshold
+ for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
+ watchdog.onPackageFailure(Arrays.asList(
+ new VersionedPackage(APP_A, differentVersionCode)));
+ }
+
+ // Run handler so package failures are dispatched to observers
+ mTestLooper.dispatchAll();
+
+ // Verify that observers are not notified
+ assertEquals(0, observer.mFailedPackages.size());
+ }
+
+
+ /**
* Test package failure and notifies only least impact observers.
*/
@Test
@@ -260,7 +294,10 @@ public class PackageWatchdogTest {
// Then fail all apps above the threshold
for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
- watchdog.onPackageFailure(new String[]{APP_A, APP_B, APP_C, APP_D});
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
+ new VersionedPackage(APP_B, VERSION_CODE),
+ new VersionedPackage(APP_C, VERSION_CODE),
+ new VersionedPackage(APP_D, VERSION_CODE)));
}
// Run handler so package failures are dispatched to observers
@@ -297,7 +334,7 @@ public class PackageWatchdogTest {
* <ul>
*/
@Test
- public void testPackageFailureNotifyLeastSuccessively() throws Exception {
+ public void testPackageFailureNotifyLeastImpactSuccessively() throws Exception {
PackageWatchdog watchdog = createWatchdog();
TestObserver observerFirst = new TestObserver(OBSERVER_NAME_1,
PackageHealthObserverImpact.USER_IMPACT_LOW);
@@ -310,7 +347,7 @@ public class PackageWatchdogTest {
// Then fail APP_A above the threshold
for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
- watchdog.onPackageFailure(new String[]{APP_A});
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
}
// Run handler so package failures are dispatched to observers
mTestLooper.dispatchAll();
@@ -327,7 +364,7 @@ public class PackageWatchdogTest {
// Then fail APP_A again above the threshold
for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
- watchdog.onPackageFailure(new String[]{APP_A});
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
}
// Run handler so package failures are dispatched to observers
mTestLooper.dispatchAll();
@@ -344,7 +381,7 @@ public class PackageWatchdogTest {
// Then fail APP_A again above the threshold
for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
- watchdog.onPackageFailure(new String[]{APP_A});
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
}
// Run handler so package failures are dispatched to observers
mTestLooper.dispatchAll();
@@ -361,7 +398,7 @@ public class PackageWatchdogTest {
// Then fail APP_A again above the threshold
for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
- watchdog.onPackageFailure(new String[]{APP_A});
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
}
// Run handler so package failures are dispatched to observers
mTestLooper.dispatchAll();
@@ -388,7 +425,7 @@ public class PackageWatchdogTest {
// Then fail APP_A above the threshold
for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) {
- watchdog.onPackageFailure(new String[]{APP_A});
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
}
// Run handler so package failures are dispatched to observers
@@ -420,11 +457,11 @@ public class PackageWatchdogTest {
mImpact = impact;
}
- public int onHealthCheckFailed(String packageName) {
+ public int onHealthCheckFailed(String packageName, long versionCode) {
return mImpact;
}
- public boolean execute(String packageName) {
+ public boolean execute(String packageName, long versionCode) {
mFailedPackages.add(packageName);
return true;
}