diff options
50 files changed, 508 insertions, 273 deletions
diff --git a/api/current.txt b/api/current.txt index 6efa792c4448..2f33c34fd5b4 100644 --- a/api/current.txt +++ b/api/current.txt @@ -30528,7 +30528,7 @@ package android.os { field public static final int M = 23; // 0x17 field public static final int N = 24; // 0x18 field public static final int N_MR1 = 25; // 0x19 - field public static final int O = 26; // 0x1a + field public static final int O = 10000; // 0x2710 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { diff --git a/api/system-current.txt b/api/system-current.txt index 4124ad3fe462..9a62752c79e1 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -33245,7 +33245,7 @@ package android.os { field public static final int M = 23; // 0x17 field public static final int N = 24; // 0x18 field public static final int N_MR1 = 25; // 0x19 - field public static final int O = 26; // 0x1a + field public static final int O = 10000; // 0x2710 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { diff --git a/api/test-current.txt b/api/test-current.txt index a4e1866f90f0..6ea9b11aa41d 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -30637,7 +30637,7 @@ package android.os { field public static final int M = 23; // 0x17 field public static final int N = 24; // 0x18 field public static final int N_MR1 = 25; // 0x19 - field public static final int O = 26; // 0x1a + field public static final int O = 10000; // 0x2710 } public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable { diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index c8b8c6c1b262..2e56bcf8a3de 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -4358,6 +4358,8 @@ public class Notification implements Parcelable mN.mLargeIcon = null; Bitmap largeIconLegacy = mN.largeIcon; mN.largeIcon = null; + ArrayList<Action> actions = mActions; + mActions = new ArrayList<>(); Bundle publicExtras = new Bundle(); publicExtras.putBoolean(EXTRA_SHOW_WHEN, savedBundle.getBoolean(EXTRA_SHOW_WHEN)); @@ -4373,6 +4375,7 @@ public class Notification implements Parcelable mN.extras = savedBundle; mN.mLargeIcon = largeIcon; mN.largeIcon = largeIconLegacy; + mActions = actions; mStyle = style; return view; } diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index 33535302bd5c..7261dfa09bb4 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -1559,14 +1559,14 @@ public class AssistStructure implements Parcelable { @Override public void setText(CharSequence text) { ViewNodeText t = getNodeText(); - t.mText = text; + t.mText = TextUtils.trimNoCopySpans(text); t.mTextSelectionStart = t.mTextSelectionEnd = -1; } @Override public void setText(CharSequence text, int selectionStart, int selectionEnd) { ViewNodeText t = getNodeText(); - t.mText = text; + t.mText = TextUtils.trimNoCopySpans(text); t.mTextSelectionStart = selectionStart; t.mTextSelectionEnd = selectionEnd; } @@ -1737,13 +1737,6 @@ public class AssistStructure implements Parcelable { } @Override - public void setUrl(String url) { - if (url == null) return; - - setWebDomain(url); - } - - @Override public void setWebDomain(@Nullable String domain) { if (domain == null) { mNode.mWebDomain = null; diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl index 73e52c89dcc4..d163a4441097 100644 --- a/core/java/android/net/INetworkScoreService.aidl +++ b/core/java/android/net/INetworkScoreService.aidl @@ -45,7 +45,7 @@ interface INetworkScoreService * Set the active scorer and clear existing scores. * @param packageName the package name of the new scorer to use. * @return true if the operation succeeded, or false if the new package is not a valid scorer. - * @throws SecurityException if the caller is not the system. + * @throws SecurityException if the caller is not the system or a network scorer. */ boolean setActiveScorer(in String packageName); diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java index eeb426a4bcf9..9f6e45ca6fb5 100644 --- a/core/java/android/net/NetworkScoreManager.java +++ b/core/java/android/net/NetworkScoreManager.java @@ -16,27 +16,20 @@ package android.net; -import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT; - +import android.Manifest.permission; import android.annotation.IntDef; -import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.content.Context; -import android.os.Bundle; -import android.os.Handler; -import android.os.RemoteCallback; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; -import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; -import java.util.concurrent.CompletableFuture; /** * Class that manages communication between network subsystems and a network scorer. @@ -49,9 +42,9 @@ import java.util.concurrent.CompletableFuture; * * <p>A network scorer is any application which: * <ul> - * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission. + * <li>Declares the {@link permission#SCORE_NETWORKS} permission. * <li>Include a Service for the {@link #ACTION_RECOMMEND_NETWORKS} action - * protected by the {@link android.Manifest.permission#BIND_NETWORK_RECOMMENDATION_SERVICE} + * protected by the {@link permission#BIND_NETWORK_RECOMMENDATION_SERVICE} * permission. * </ul> * @@ -319,7 +312,7 @@ public class NetworkScoreManager { * * @return true if the operation succeeded, or false if the new package is not a valid scorer. * @throws SecurityException if the caller is not a system process or does not hold the - * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission + * {@link permission#SCORE_NETWORKS} permission * @hide */ @SystemApi @@ -351,7 +344,7 @@ public class NetworkScoreManager { * * @return true if the broadcast was sent, or false if there is no active scorer. * @throws SecurityException if the caller does not hold the - * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission. + * {@link permission#REQUEST_NETWORK_SCORES} permission. * @hide */ public boolean requestScores(NetworkKey[] networks) throws SecurityException { @@ -368,7 +361,7 @@ public class NetworkScoreManager { * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. * @throws SecurityException if the caller does not hold the - * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission. + * {@link permission#REQUEST_NETWORK_SCORES} permission. * @throws IllegalArgumentException if a score cache is already registered for this type. * @deprecated equivalent to registering for cache updates with CACHE_FILTER_NONE. * @hide @@ -385,7 +378,7 @@ public class NetworkScoreManager { * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores * @param filterType the {@link CacheUpdateFilter} to apply * @throws SecurityException if the caller does not hold the - * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission. + * {@link permission#REQUEST_NETWORK_SCORES} permission. * @throws IllegalArgumentException if a score cache is already registered for this type. * @hide */ @@ -404,7 +397,7 @@ public class NetworkScoreManager { * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. * @throws SecurityException if the caller does not hold the - * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission. + * {@link permission#REQUEST_NETWORK_SCORES} permission. * @throws IllegalArgumentException if a score cache is already registered for this type. * @hide */ @@ -417,25 +410,6 @@ public class NetworkScoreManager { } /** - * Request a recommendation for which network to connect to. - * - * <p>It is not safe to call this method from the main thread. - * - * @param request a {@link RecommendationRequest} instance containing additional - * request details - * @return a {@link RecommendationResult} instance containing the recommended network - * to connect to - * @throws SecurityException if the caller does not hold the - * {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} permission. - * @hide - * @deprecated to be removed. - */ - public RecommendationResult requestRecommendation(RecommendationRequest request) - throws SecurityException { - return null; - } - - /** * Determine whether the application with the given UID is the enabled scorer. * * @param callingUid the UID to check diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 4bad7ab76be6..86fcfc8fb961 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -758,7 +758,7 @@ public class Build { /** * O. */ - public static final int O = 26; + public static final int O = CUR_DEVELOPMENT; // STOPSHIP Replace with the real version. } /** The type of build, like "user" or "eng". */ diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java index 1ef3916a743f..8302eceb772a 100644 --- a/core/java/android/os/VintfObject.java +++ b/core/java/android/os/VintfObject.java @@ -26,17 +26,12 @@ public class VintfObject { private static final String LOG_TAG = "VintfObject"; /** - * Slurps all device information (both manifests) - * and report it. + * Slurps all device information (both manifests and both matrices) + * and report them. * If any error in getting one of the manifests, it is not included in * the list. */ - public static String[] report() { - ArrayList<String> ret = new ArrayList<>(); - put(ret, getDeviceManifest(), "device manifest"); - put(ret, getFrameworkManifest(), "framework manifest"); - return ret.toArray(new String[0]); - } + public static native String[] report(); /** * Verify that the given metadata for an OTA package is compatible with @@ -50,15 +45,4 @@ public class VintfObject { */ public static native int verify(String[] packageInfo); - // return null if any error, otherwise XML string. - private static native String getDeviceManifest(); - private static native String getFrameworkManifest(); - - private static void put(ArrayList<String> list, String content, String message) { - if (content == null || content.length() == 0) { - Log.e(LOG_TAG, "Cannot get;" + message + "; check native logs for details."); - return; - } - list.add(content); - } } diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java index 081deebaed77..91f43d632dfd 100644 --- a/core/java/android/text/TextUtils.java +++ b/core/java/android/text/TextUtils.java @@ -1921,6 +1921,22 @@ public class TextUtils { return false; } + /** + * If the {@code charSequence} is instance of {@link Spanned}, creates a new copy and + * {@link NoCopySpan}'s are removed from the copy. Otherwise the given {@code charSequence} is + * returned as it is. + * + * @hide + */ + @Nullable + public static CharSequence trimNoCopySpans(@Nullable CharSequence charSequence) { + if (charSequence != null && charSequence instanceof Spanned) { + // SpannableStringBuilder copy constructor trims NoCopySpans. + return new SpannableStringBuilder(charSequence); + } + return charSequence; + } + private static Object sLock = new Object(); private static char[] sTemp = null; diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java index f71589c6c5ef..6bdc9ff5d0fa 100644 --- a/core/java/android/view/ViewStructure.java +++ b/core/java/android/view/ViewStructure.java @@ -374,13 +374,6 @@ public abstract class ViewStructure { public abstract Rect getTempRect(); /** - * @deprecated - use {@link #setWebDomain(String)} instead. - * @hide - */ - @Deprecated - public abstract void setUrl(String url); - - /** * Sets the Web domain represented by this node. * * <p>Typically used when the view is a container for an HTML document. diff --git a/core/java/android/view/autofill/AutofillValue.java b/core/java/android/view/autofill/AutofillValue.java index b57dab56318e..3beae11cf38c 100644 --- a/core/java/android/view/autofill/AutofillValue.java +++ b/core/java/android/view/autofill/AutofillValue.java @@ -26,6 +26,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; import android.view.View; import com.android.internal.util.Preconditions; @@ -257,7 +258,8 @@ public final class AutofillValue implements Parcelable { * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info. */ public static AutofillValue forText(@Nullable CharSequence value) { - return value == null ? null : new AutofillValue(AUTOFILL_TYPE_TEXT, value); + return value == null ? null : new AutofillValue(AUTOFILL_TYPE_TEXT, + TextUtils.trimNoCopySpans(value)); } /** diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java index ebf1c0189b15..209ff097f9e6 100644 --- a/core/java/android/view/textclassifier/TextClassifierImpl.java +++ b/core/java/android/view/textclassifier/TextClassifierImpl.java @@ -607,6 +607,7 @@ final class TextClassifierImpl implements TextClassifier { @Nullable public static Intent create(Context context, String type, String text) { type = type.trim().toLowerCase(Locale.ENGLISH); + text = text.trim(); switch (type) { case TextClassifier.TYPE_EMAIL: return new Intent(Intent.ACTION_SENDTO) @@ -618,6 +619,9 @@ final class TextClassifierImpl implements TextClassifier { return new Intent(Intent.ACTION_VIEW) .setData(Uri.parse(String.format("geo:0,0?q=%s", text))); case TextClassifier.TYPE_URL: + if (!text.startsWith("https://") && !text.startsWith("http://")) { + text = "http://" + text; + } return new Intent(Intent.ACTION_VIEW, Uri.parse(text)) .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()); default: diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 1457d026ea39..569fe017ac86 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -49,7 +49,6 @@ import android.view.accessibility.AccessibilityNodeProvider; import android.widget.RemoteViews.RemoteView; import com.android.internal.R; -import com.android.internal.util.Preconditions; import com.google.android.collect.Lists; @@ -336,11 +335,6 @@ public class ListView extends AbsListView { * @param isSelectable whether the item is selectable */ public void addHeaderView(View v, Object data, boolean isSelectable) { - Preconditions.checkState( - v.getParent() == null, - "The specified child already has a parent. " - + "You must call removeView() on the child's parent first."); - final FixedViewInfo info = new FixedViewInfo(); info.view = v; info.data = data; @@ -435,11 +429,6 @@ public class ListView extends AbsListView { * @param isSelectable true if the footer view can be selected */ public void addFooterView(View v, Object data, boolean isSelectable) { - Preconditions.checkState( - v.getParent() == null, - "The specified child already has a parent. " - + "You must call removeView() on the child's parent first."); - final FixedViewInfo info = new FixedViewInfo(); info.view = v; info.data = data; diff --git a/core/jni/android/graphics/Movie.h b/core/jni/android/graphics/Movie.h index c0fbe4fd635f..736890d5215e 100644 --- a/core/jni/android/graphics/Movie.h +++ b/core/jni/android/graphics/Movie.h @@ -10,8 +10,9 @@ #ifndef Movie_DEFINED #define Movie_DEFINED -#include "SkRefCnt.h" +#include "SkBitmap.h" #include "SkCanvas.h" +#include "SkRefCnt.h" class SkStreamRewindable; diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp index 9491a1ecdad3..033f2dfe5173 100644 --- a/core/jni/android_os_VintfObject.cpp +++ b/core/jni/android_os_VintfObject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Android Open Source Project + * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,10 @@ #define LOG_TAG "VintfObject" //#define LOG_NDEBUG 0 +#include <android-base/logging.h> + +#include <vector> +#include <string> #include <JNIHelp.h> #include <vintf/VintfObject.h> @@ -23,31 +27,48 @@ #include "core_jni_helpers.h" +static jclass gString; + namespace android { -using vintf::HalManifest; -using vintf::RuntimeInfo; using vintf::VintfObject; using vintf::gHalManifestConverter; +using vintf::gCompatibilityMatrixConverter; +using vintf::XmlConverter; -static jstring android_os_VintfObject_getDeviceManifest(JNIEnv* env, jclass clazz) -{ - const HalManifest *manifest = VintfObject::GetDeviceHalManifest(); - if (manifest == nullptr) { - return nullptr; +static inline jobjectArray toJavaStringArray(JNIEnv* env, const std::vector<std::string>& v) { + jobjectArray ret = env->NewObjectArray(v.size(), gString, NULL /* init element */); + for (size_t i = 0; i < v.size(); ++i) { + env->SetObjectArrayElement(ret, i, env->NewStringUTF(v[i].c_str())); } - std::string xml = gHalManifestConverter(*manifest); - return env->NewStringUTF(xml.c_str()); + return ret; } -static jstring android_os_VintfObject_getFrameworkManifest(JNIEnv* env, jclass clazz) -{ - const HalManifest *manifest = VintfObject::GetFrameworkHalManifest(); - if (manifest == nullptr) { - return nullptr; +template<typename T> +static void tryAddSchema(const T* object, const XmlConverter<T>& converter, + const std::string& description, + std::vector<std::string>* cStrings) { + if (object == nullptr) { + LOG(WARNING) << __FUNCTION__ << "Cannot get " << description; + } else { + cStrings->push_back(converter(*object)); } - std::string xml = gHalManifestConverter(*manifest); - return env->NewStringUTF(xml.c_str()); +} + +static jobjectArray android_os_VintfObject_report(JNIEnv* env, jclass clazz) +{ + std::vector<std::string> cStrings; + + tryAddSchema(VintfObject::GetDeviceHalManifest(), gHalManifestConverter, + "device manifest", &cStrings); + tryAddSchema(VintfObject::GetFrameworkHalManifest(), gHalManifestConverter, + "framework manifest", &cStrings); + tryAddSchema(VintfObject::GetDeviceCompatibilityMatrix(), gCompatibilityMatrixConverter, + "device compatibility matrix", &cStrings); + tryAddSchema(VintfObject::GetFrameworkCompatibilityMatrix(), gCompatibilityMatrixConverter, + "framework compatibility matrix", &cStrings); + + return toJavaStringArray(env, cStrings); } static jint android_os_VintfObject_verify(JNIEnv *env, jclass clazz, jobjectArray packageInfo) { @@ -66,15 +87,18 @@ static jint android_os_VintfObject_verify(JNIEnv *env, jclass clazz, jobjectArra // ---------------------------------------------------------------------------- static const JNINativeMethod gVintfObjectMethods[] = { - {"getDeviceManifest", "()Ljava/lang/String;", (void*)android_os_VintfObject_getDeviceManifest}, - {"getFrameworkManifest", "()Ljava/lang/String;", (void*)android_os_VintfObject_getFrameworkManifest}, - {"verify", "([Ljava/lang/String;)I", (void*)android_os_VintfObject_verify}, + {"report", "()[Ljava/lang/String;", (void*)android_os_VintfObject_report}, + {"verify", "([Ljava/lang/String;)I", (void*)android_os_VintfObject_verify}, }; + const char* const kVintfObjectPathName = "android/os/VintfObject"; int register_android_os_VintfObject(JNIEnv* env) { + + gString = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/String")); + return RegisterMethodsOrDie(env, kVintfObjectPathName, gVintfObjectMethods, NELEM(gVintfObjectMethods)); } diff --git a/core/tests/coretests/src/android/os/VintfObjectTest.java b/core/tests/coretests/src/android/os/VintfObjectTest.java index aaaf55ccf799..821ee806743d 100644 --- a/core/tests/coretests/src/android/os/VintfObjectTest.java +++ b/core/tests/coretests/src/android/os/VintfObjectTest.java @@ -26,5 +26,8 @@ public class VintfObjectTest extends TestCase { // From /system/manifest.xml assertTrue(String.join("", xmls).contains( "<manifest version=\"1.0\" type=\"framework\">")); + // From /system/compatibility-matrix.xml + assertTrue(String.join("", xmls).contains( + "<compatibility-matrix version=\"1.0\" type=\"framework\">")); } } diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java index f59e4fc188d4..742fd60e25f7 100644 --- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java +++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java @@ -118,7 +118,7 @@ public class TextClassificationManagerTest { if (isTextClassifierDisabled()) return; String text = "Visit http://www.android.com for more information"; - String classifiedText = "http://www.android.com"; + String classifiedText = "www.android.com"; int startIndex = text.indexOf(classifiedText); int endIndex = startIndex + classifiedText.length(); assertThat(mClassifier.classifyText(text, startIndex, endIndex, LOCALES), @@ -193,7 +193,19 @@ public class TextClassificationManagerTest { public boolean matches(Object o) { if (o instanceof TextClassification) { TextClassification result = (TextClassification) o; - return text.equals(result.getText()) + final boolean typeRequirementSatisfied; + switch (type) { + case TextClassifier.TYPE_URL: + String scheme = result.getIntent().getData().getScheme(); + typeRequirementSatisfied = "http".equalsIgnoreCase(scheme) + || "https".equalsIgnoreCase(scheme); + break; + default: + typeRequirementSatisfied = true; + } + + return typeRequirementSatisfied + && text.equals(result.getText()) && result.getEntityCount() > 0 && type.equals(result.getEntity(0)); // TODO: Include other properties. diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp index bd798e8dc688..fcdd814bb63e 100644 --- a/libs/hwui/tests/unit/FrameBuilderTests.cpp +++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp @@ -819,7 +819,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferColorOp_unbounded) { EXPECT_EQ(1, renderer.getIndex()) << "ColorOp should not be rejected"; } -OPENGL_PIPELINE_TEST(FrameBuilder, renderNode) { +RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderNode) { class RenderNodeTestRenderer : public TestRendererBase { public: void onRectOp(const RectOp& op, const BakedOpState& state) override { @@ -2321,7 +2321,7 @@ RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, clip_replace) { EXPECT_EQ(1, renderer.getIndex()); } -OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedInMiddle) { +RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedInMiddle) { /* R is backward projected on B A / \ @@ -2351,7 +2351,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedInMiddle) { EXPECT_EQ(3, renderer.getIndex()); } -OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectLast) { +RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectLast) { /* R is backward projected on E A / | \ @@ -2383,7 +2383,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectLast) { EXPECT_EQ(4, renderer.getIndex()); } -OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderNoReceivable) { +RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderNoReceivable) { /* R is backward projected without receiver A / \ @@ -2412,7 +2412,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderNoReceivable) { EXPECT_EQ(2, renderer.getIndex()); } -OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderParentReceivable) { +RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderParentReceivable) { /* R is backward projected on C A / \ @@ -2441,7 +2441,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderParentReceivable) { EXPECT_EQ(3, renderer.getIndex()); } -OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderSameNodeReceivable) { +RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderSameNodeReceivable) { auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, [](RenderProperties& props, RecordingCanvas& canvas) { drawOrderedNode(&canvas, 0, nullptr); //nodeB @@ -2464,7 +2464,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderSameNodeReceivable) { EXPECT_EQ(2, renderer.getIndex()); } -OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling) { +RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling) { //TODO: this test together with the next "projectionReorderProjectedSibling2" likely expose a //bug in HWUI. First test draws R, while the second test does not draw R for a nearly identical //tree setup. The correct behaviour is to not draw R, because the receiver cannot be a sibling @@ -2497,7 +2497,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling) { EXPECT_EQ(3, renderer.getIndex()); } -OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling2) { +RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling2) { /* R is set to project on B, but R is not drawn because projecting on a sibling is not allowed. A | @@ -2530,7 +2530,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling2) { EXPECT_EQ(3, renderer.getIndex()); } -OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderGrandparentReceivable) { +RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderGrandparentReceivable) { /* R is backward projected on B A | @@ -2562,7 +2562,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderGrandparentReceivable) { EXPECT_EQ(3, renderer.getIndex()); } -OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivables) { +RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivables) { /* B and G are receivables, R is backward projected A / \ @@ -2595,7 +2595,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivables) { EXPECT_EQ(4, renderer.getIndex()); } -OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesLikelyScenario) { +RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesLikelyScenario) { /* B and G are receivables, G is backward projected A / \ @@ -2628,7 +2628,7 @@ OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesLikelyScenario EXPECT_EQ(4, renderer.getIndex()); } -OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesDeeper) { +RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesDeeper) { /* B and G are receivables, R is backward projected A / \ diff --git a/obex/javax/obex/ServerSession.java b/obex/javax/obex/ServerSession.java index 3831cf7285da..dbfeefdfb037 100644 --- a/obex/javax/obex/ServerSession.java +++ b/obex/javax/obex/ServerSession.java @@ -104,7 +104,6 @@ public final class ServerSession extends ObexSession implements Runnable { case ObexHelper.OBEX_OPCODE_DISCONNECT: handleDisconnectRequest(); - done = true; break; case ObexHelper.OBEX_OPCODE_GET: diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java index 646b6ba84ebb..be15e657d1c3 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java @@ -124,7 +124,8 @@ public class WifiTracker { */ private final Object mLock = new Object(); - //visible to both worker and main thread. Guarded by #mInternalAccessPoints + //visible to both worker and main thread. + @GuardedBy("mLock") private final AccessPointListenerAdapter mAccessPointListenerAdapter = new AccessPointListenerAdapter(); @@ -1005,12 +1006,13 @@ public class WifiTracker { if (DBG) { Log.d(TAG, "Starting to copy AP items on the MainHandler"); } - if (notifyListeners) { - notificationMap = mAccessPointListenerAdapter.mPendingNotifications.clone(); - } - - mAccessPointListenerAdapter.mPendingNotifications.clear(); synchronized (mLock) { + if (notifyListeners) { + notificationMap = mAccessPointListenerAdapter.mPendingNotifications.clone(); + } + + mAccessPointListenerAdapter.mPendingNotifications.clear(); + for (AccessPoint internalAccessPoint : mInternalAccessPoints) { AccessPoint accessPoint = oldAccessPoints.get(internalAccessPoint.mId); if (accessPoint == null) { diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java index 7d78c089b089..9ef05c5d4125 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java @@ -16,6 +16,7 @@ package com.android.systemui.plugins.qs; import android.content.Context; import android.graphics.drawable.Drawable; +import android.metrics.LogMaker; import android.service.quicksettings.Tile; import com.android.systemui.plugins.annotations.DependsOn; @@ -66,6 +67,10 @@ public interface QSTile { State getState(); + default LogMaker populate(LogMaker logMaker) { + return logMaker; + } + @ProvidesInterface(version = Callback.VERSION) public interface Callback { public static final int VERSION = 1; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java index 7139d59c6eef..af02e5beca92 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java @@ -37,6 +37,7 @@ public class DozeLog { private static final int PULSE_REASONS = 5; + public static final int PULSE_REASON_NONE = -1; public static final int PULSE_REASON_INTENT = 0; public static final int PULSE_REASON_NOTIFICATION = 1; public static final int PULSE_REASON_SENSOR_SIGMOTION = 2; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java index 34d621f7b624..5526e6ba3f45 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java @@ -107,6 +107,7 @@ public class DozeMachine { private final ArrayList<State> mQueuedRequests = new ArrayList<>(); private State mState = State.UNINITIALIZED; + private int mPulseReason; private boolean mWakeLockHeldForCurrentState = false; public DozeMachine(Service service, AmbientDisplayConfiguration config, @@ -134,6 +135,20 @@ public class DozeMachine { */ @MainThread public void requestState(State requestedState) { + Preconditions.checkArgument(requestedState != State.DOZE_REQUEST_PULSE); + requestState(requestedState, DozeLog.PULSE_REASON_NONE); + } + + @MainThread + public void requestPulse(int pulseReason) { + // Must not be called during a transition. There's no inherent problem with that, + // but there's currently no need to execute from a transition and it simplifies the + // code to not have to worry about keeping the pulseReason in mQueuedRequests. + Preconditions.checkState(!isExecutingTransition()); + requestState(State.DOZE_REQUEST_PULSE, pulseReason); + } + + private void requestState(State requestedState, int pulseReason) { Assert.isMainThread(); if (DEBUG) { Log.i(TAG, "request: current=" + mState + " req=" + requestedState, @@ -147,7 +162,7 @@ public class DozeMachine { for (int i = 0; i < mQueuedRequests.size(); i++) { // Transitions in Parts can call back into requestState, which will // cause mQueuedRequests to grow. - transitionTo(mQueuedRequests.get(i)); + transitionTo(mQueuedRequests.get(i), pulseReason); } mQueuedRequests.clear(); mWakeLock.release(); @@ -166,6 +181,20 @@ public class DozeMachine { return mState; } + /** + * @return the current pulse reason. + * + * This is only valid if the machine is currently in one of the pulse states. + */ + @MainThread + public int getPulseReason() { + Assert.isMainThread(); + Preconditions.checkState(mState == State.DOZE_REQUEST_PULSE + || mState == State.DOZE_PULSING + || mState == State.DOZE_PULSE_DONE, "must be in pulsing state, but is " + mState); + return mPulseReason; + } + /** Requests the PowerManager to wake up now. */ public void wakeUp() { mDozeService.requestWakeUp(); @@ -175,7 +204,7 @@ public class DozeMachine { return !mQueuedRequests.isEmpty(); } - private void transitionTo(State requestedState) { + private void transitionTo(State requestedState, int pulseReason) { State newState = transitionPolicy(requestedState); if (DEBUG) { @@ -191,6 +220,7 @@ public class DozeMachine { State oldState = mState; mState = newState; + updatePulseReason(newState, oldState, pulseReason); performTransitionOnComponents(oldState, newState); updateScreenState(newState); updateWakeLockState(newState); @@ -198,6 +228,14 @@ public class DozeMachine { resolveIntermediateState(newState); } + private void updatePulseReason(State newState, State oldState, int pulseReason) { + if (newState == State.DOZE_REQUEST_PULSE) { + mPulseReason = pulseReason; + } else if (oldState == State.DOZE_PULSE_DONE) { + mPulseReason = DozeLog.PULSE_REASON_NONE; + } + } + private void performTransitionOnComponents(State oldState, State newState) { for (Part p : mParts) { p.transitionTo(oldState, newState); @@ -281,7 +319,8 @@ public class DozeMachine { case INITIALIZED: case DOZE_PULSE_DONE: transitionTo(mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT) - ? DozeMachine.State.DOZE_AOD : DozeMachine.State.DOZE); + ? DozeMachine.State.DOZE_AOD : DozeMachine.State.DOZE, + DozeLog.PULSE_REASON_NONE); break; default: break; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index a721bf80859f..693a690d7f59 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -238,7 +238,7 @@ public class DozeTriggers implements DozeMachine.Part { mDozeHost.isPulsingBlocked()); return; } - mMachine.requestState(DozeMachine.State.DOZE_REQUEST_PULSE); + mMachine.requestPulse(reason); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java index 4e72bdf3a0f8..22869d876508 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java @@ -83,7 +83,7 @@ public class DozeUi implements DozeMachine.Part { unscheduleTimeTick(); break; case DOZE_REQUEST_PULSE: - pulseWhileDozing(DozeLog.PULSE_REASON_NOTIFICATION /* TODO */); + pulseWhileDozing(mMachine.getPulseReason()); break; case DOZE_PULSE_DONE: mHost.abortPulsing(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index f5e096ebbbef..c4d88aec7b8c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -22,6 +22,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; +import android.metrics.LogMaker; import android.os.Handler; import android.os.Message; import android.service.quicksettings.Tile; @@ -30,6 +31,7 @@ import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; + import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settingslib.Utils; @@ -179,7 +181,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback { public void openDetails(String subPanel) { QSTile tile = getTile(subPanel); - showDetailAdapter(true, tile.getDetailAdapter(), new int[] {getWidth() / 2, 0}); + showDetailAdapter(true, tile.getDetailAdapter(), new int[]{getWidth() / 2, 0}); } private QSTile getTile(String subPanel) { @@ -485,8 +487,9 @@ public class QSPanel extends LinearLayout implements Tunable, Callback { private void logTiles() { for (int i = 0; i < mRecords.size(); i++) { - TileRecord tileRecord = mRecords.get(i); - mMetricsLogger.visible(tileRecord.tile.getMetricsCategory()); + QSTile tile = mRecords.get(i).tile; + mMetricsLogger.write(tile.populate(new LogMaker(tile.getMetricsCategory()) + .setType(MetricsEvent.TYPE_OPEN))); } } @@ -544,12 +547,13 @@ public class QSPanel extends LinearLayout implements Tunable, Callback { private static final int SHOW_DETAIL = 1; private static final int SET_TILE_VISIBILITY = 2; private static final int ANNOUNCE_FOR_ACCESSIBILITY = 3; + @Override public void handleMessage(Message msg) { if (msg.what == SHOW_DETAIL) { - handleShowDetail((Record)msg.obj, msg.arg1 != 0); + handleShowDetail((Record) msg.obj, msg.arg1 != 0); } else if (msg.what == ANNOUNCE_FOR_ACCESSIBILITY) { - announceForAccessibility((CharSequence)msg.obj); + announceForAccessibility((CharSequence) msg.obj); } } } @@ -569,8 +573,11 @@ public class QSPanel extends LinearLayout implements Tunable, Callback { public interface QSTileLayout { void addTile(TileRecord tile); + void removeTile(TileRecord tile); + int getOffsetTop(TileRecord tile); + boolean updateResources(); void setListening(boolean listening); diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java index dc9176f66bb2..017365f6c64d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java @@ -157,7 +157,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener } @Override - protected LogMaker populate(LogMaker logMaker) { + public LogMaker populate(LogMaker logMaker) { return super.populate(logMaker).setComponentName(mComponent); } @@ -275,7 +275,6 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener } catch (RemoteException e) { // Called through wrapper, won't happen here. } - MetricsLogger.action(mContext, getMetricsCategory(), mComponent.getPackageName()); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index 976efb2c289b..32af2305062e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -175,7 +175,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile { mHandler.sendEmptyMessage(H.LONG_CLICK); } - protected LogMaker populate(LogMaker logMaker) { + public LogMaker populate(LogMaker logMaker) { if (mState instanceof BooleanState) { logMaker.addTaggedData(FIELD_QS_VALUE, ((BooleanState) mState).value ? 1 : 0); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java index 24d8b924ee85..fa6ba96ef502 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java @@ -106,7 +106,7 @@ public class DozeMachineTest { public void testPulseDone_goesToDoze() { when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(false); mMachine.requestState(INITIALIZED); - mMachine.requestState(DOZE_REQUEST_PULSE); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); mMachine.requestState(DOZE_PULSE_DONE); @@ -119,7 +119,7 @@ public class DozeMachineTest { public void testPulseDone_goesToAoD() { when(mConfigMock.alwaysOnEnabled(anyInt())).thenReturn(true); mMachine.requestState(INITIALIZED); - mMachine.requestState(DOZE_REQUEST_PULSE); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); mMachine.requestState(DOZE_PULSE_DONE); @@ -163,7 +163,7 @@ public class DozeMachineTest { public void testWakeLock_heldInPulseStates() { mMachine.requestState(INITIALIZED); - mMachine.requestState(DOZE_REQUEST_PULSE); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); assertTrue(mWakeLockFake.isHeld()); mMachine.requestState(DOZE_PULSING); @@ -186,7 +186,7 @@ public class DozeMachineTest { mMachine.requestState(INITIALIZED); mMachine.requestState(DOZE); - mMachine.requestState(DOZE_REQUEST_PULSE); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); mMachine.requestState(DOZE_PULSE_DONE); @@ -198,9 +198,9 @@ public class DozeMachineTest { mMachine.requestState(INITIALIZED); mMachine.requestState(DOZE); - mMachine.requestState(DOZE_REQUEST_PULSE); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); - mMachine.requestState(DOZE_REQUEST_PULSE); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSE_DONE); } @@ -209,7 +209,7 @@ public class DozeMachineTest { mMachine.requestState(INITIALIZED); mMachine.requestState(DOZE); - mMachine.requestState(DOZE_REQUEST_PULSE); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSE_DONE); } @@ -235,7 +235,7 @@ public class DozeMachineTest { public void testScreen_onInPulse() { mMachine.requestState(INITIALIZED); - mMachine.requestState(DOZE_REQUEST_PULSE); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); mMachine.requestState(DOZE_PULSING); assertEquals(Display.STATE_ON, mServiceFake.screenState); @@ -246,7 +246,7 @@ public class DozeMachineTest { mMachine.requestState(INITIALIZED); mMachine.requestState(DOZE); - mMachine.requestState(DOZE_REQUEST_PULSE); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); assertEquals(Display.STATE_OFF, mServiceFake.screenState); } @@ -256,7 +256,7 @@ public class DozeMachineTest { mMachine.requestState(INITIALIZED); mMachine.requestState(DOZE_AOD); - mMachine.requestState(DOZE_REQUEST_PULSE); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState); } @@ -270,12 +270,43 @@ public class DozeMachineTest { return null; }).when(mPartMock).transitionTo(any(), eq(DOZE_REQUEST_PULSE)); - mMachine.requestState(DOZE_REQUEST_PULSE); + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); assertEquals(DOZE_PULSING, mMachine.getState()); } @Test + public void testPulseReason_getMatchesRequest() { + mMachine.requestState(INITIALIZED); + mMachine.requestState(DOZE); + mMachine.requestPulse(DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP); + + assertEquals(DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP, mMachine.getPulseReason()); + } + + @Test + public void testPulseReason_getFromTransition() { + mMachine.requestState(INITIALIZED); + mMachine.requestState(DOZE); + doAnswer(inv -> { + DozeMachine.State newState = inv.getArgument(1); + if (newState == DOZE_REQUEST_PULSE + || newState == DOZE_PULSING + || newState == DOZE_PULSE_DONE) { + assertEquals(DozeLog.PULSE_REASON_NOTIFICATION, mMachine.getPulseReason()); + } else { + assertTrue("unexpected state " + newState, + newState == DOZE || newState == DOZE_AOD); + } + return null; + }).when(mPartMock).transitionTo(any(), any()); + + mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION); + mMachine.requestState(DOZE_PULSING); + mMachine.requestState(DOZE_PULSE_DONE); + } + + @Test public void testWakeUp_wakesUp() { mMachine.wakeUp(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java index 12e75a14ba2b..d57f81399efd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java @@ -22,7 +22,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.mockito.Mockito.withSettings; import android.app.Instrumentation; import android.content.Context; @@ -39,8 +38,6 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; -import org.mockito.Answers; -import org.mockito.MockSettings; public class DozeTriggersTest { private Context mContext; @@ -104,7 +101,7 @@ public class DozeTriggersTest { mSensors.PROXIMITY.sendProximityResult(true); /* Far */ }); - verify(mMachine).requestState(DozeMachine.State.DOZE_REQUEST_PULSE); + verify(mMachine).requestPulse(anyInt()); } }
\ No newline at end of file diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 018fb6886cd9..9d03fded6511 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -221,7 +221,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState final int numContexts = mContexts.size(); for (int i = 0; i < numContexts; i++) { - fillStructureWithAllowedValues(mContexts.get(i).getStructure()); + fillStructureWithAllowedValues(mContexts.get(i).getStructure(), flags); } request = new FillRequest(requestId, mContexts, mClientState, flags); @@ -235,10 +235,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * Updates values of the nodes in the structure so that: * - proper node is focused * - autofillValue is sent back to service when it was previously autofilled + * - autofillValue is sent in the view used to force a request * * @param structure The structure to be filled + * @param flags The flags that started the session */ - private void fillStructureWithAllowedValues(@NonNull AssistStructure structure) { + private void fillStructureWithAllowedValues(@NonNull AssistStructure structure, int flags) { final int numViewStates = mViewStates.size(); for (int i = 0; i < numViewStates; i++) { final ViewState viewState = mViewStates.valueAt(i); @@ -257,8 +259,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } if (mCurrentViewId != null) { overlay.focused = mCurrentViewId.equals(viewState.id); + if (overlay.focused && (flags & FLAG_MANUAL_REQUEST) != 0) { + overlay.value = node.getAutofillValue(); + } } - node.setAutofillOverlay(overlay); } } diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 45ecbdb327e6..dd0b33dcebcd 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -2393,7 +2393,7 @@ public class BackupManagerService implements BackupManagerServiceInterface { long token = mAncestralToken; synchronized (mQueueLock) { - if (mEverStoredApps.contains(packageName)) { + if (mCurrentToken != 0 && mEverStoredApps.contains(packageName)) { if (MORE_DEBUG) { Slog.i(TAG, "App in ever-stored, so using current token"); } @@ -10456,8 +10456,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF final long oldId = Binder.clearCallingIdentity(); try { String prevTransport = mTransportManager.selectTransport(transport); - Settings.Secure.putString(mContext.getContentResolver(), - Settings.Secure.BACKUP_TRANSPORT, transport); + updateStateForTransport(transport); Slog.v(TAG, "selectBackupTransport() set " + mTransportManager.getCurrentTransportName() + " returning " + prevTransport); return prevTransport; @@ -10481,9 +10480,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF @Override public void onSuccess(String transportName) { mTransportManager.selectTransport(transportName); - Settings.Secure.putString(mContext.getContentResolver(), - Settings.Secure.BACKUP_TRANSPORT, - mTransportManager.getCurrentTransportName()); + updateStateForTransport(mTransportManager.getCurrentTransportName()); Slog.v(TAG, "Transport successfully selected: " + transport.flattenToShortString()); try { listener.onSuccess(transportName); @@ -10506,6 +10503,28 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF Binder.restoreCallingIdentity(oldId); } + private void updateStateForTransport(String newTransportName) { + // Publish the name change + Settings.Secure.putString(mContext.getContentResolver(), + Settings.Secure.BACKUP_TRANSPORT, newTransportName); + + // And update our current-dataset bookkeeping + IBackupTransport transport = mTransportManager.getTransportBinder(newTransportName); + if (transport != null) { + try { + mCurrentToken = transport.getCurrentRestoreSet(); + } catch (Exception e) { + // Oops. We can't know the current dataset token, so reset and figure it out + // when we do the next k/v backup operation on this transport. + mCurrentToken = 0; + } + } else { + // The named transport isn't bound at this particular moment, so we can't + // know yet what its current dataset token is. Reset as above. + mCurrentToken = 0; + } + } + // Supply the configuration Intent for the given transport. If the name is not one // of the available transports, or if the transport does not supply any configuration // UI, the method returns null. diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java index 90caae8e73f8..fb2982eb0baa 100644 --- a/services/backup/java/com/android/server/backup/TransportManager.java +++ b/services/backup/java/com/android/server/backup/TransportManager.java @@ -182,13 +182,13 @@ public class TransportManager { String[] getBoundTransportNames() { synchronized (mTransportLock) { - return mBoundTransports.keySet().toArray(new String[0]); + return mBoundTransports.keySet().toArray(new String[mBoundTransports.size()]); } } ComponentName[] getAllTransportCompenents() { synchronized (mTransportLock) { - return mValidTransports.keySet().toArray(new ComponentName[0]); + return mValidTransports.keySet().toArray(new ComponentName[mValidTransports.size()]); } } diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java index 114d7619a024..fdc0bba09a52 100644 --- a/services/core/java/com/android/server/NetworkScoreService.java +++ b/services/core/java/com/android/server/NetworkScoreService.java @@ -631,6 +631,11 @@ public class NetworkScoreService extends INetworkScoreService.Stub { PackageManager.PERMISSION_GRANTED; } + private boolean callerCanScoreNetworks() { + return mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS) == + PackageManager.PERMISSION_GRANTED; + } + @Override public boolean clearScores() { // Only the active scorer or the system should be allowed to flush all scores. @@ -651,9 +656,9 @@ public class NetworkScoreService extends INetworkScoreService.Stub { @Override public boolean setActiveScorer(String packageName) { // Only the system can set the active scorer - if (!isCallerSystemProcess(getCallingUid()) && !callerCanRequestScores()) { + if (!isCallerSystemProcess(getCallingUid()) && !callerCanScoreNetworks()) { throw new SecurityException( - "Caller is neither the system process nor a score requester."); + "Caller is neither the system process or a network scorer."); } return mNetworkScorerAppManager.setActiveScorer(packageName); diff --git a/services/core/java/com/android/server/NetworkScorerAppManager.java b/services/core/java/com/android/server/NetworkScorerAppManager.java index 8404025e6726..42777bf33bd3 100644 --- a/services/core/java/com/android/server/NetworkScorerAppManager.java +++ b/services/core/java/com/android/server/NetworkScorerAppManager.java @@ -208,11 +208,11 @@ public class NetworkScorerAppManager { * * <p>The caller must have permission to write to {@link Settings.Global}. * - * @param packageName the packageName of the new scorer to use. If null, the scoring app will - * revert back to the configured default. Otherwise, the scorer will only - * be set if it is a valid scorer application. - * @return true if the scorer was changed, or false if the package is not a valid scorer or - * a valid network recommendation provider exists. + * @param packageName the packageName of the new scorer to use. If null, scoring will be forced + * off, otherwise the scorer will only be set if it is a valid scorer + * application. + * @return true if the package was a valid scorer (including <code>null</code>) and now + * represents the active scorer, false otherwise. */ @VisibleForTesting public boolean setActiveScorer(String packageName) { @@ -223,16 +223,19 @@ public class NetworkScorerAppManager { return true; } - if (packageName == null) { - // revert to the default setting. - packageName = getDefaultPackageSetting(); + if (TextUtils.isEmpty(packageName)) { + Log.i(TAG, "Network scorer forced off, was: " + oldPackageName); + setNetworkRecommendationsPackage(null); + setNetworkRecommendationsEnabledSetting( + NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF); + return true; } - Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName); - // We only make the change if the new package is valid. if (getScorer(packageName) != null) { + Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName); setNetworkRecommendationsPackage(packageName); + setNetworkRecommendationsEnabledSetting(NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON); return true; } else { Log.w(TAG, "Requested network scorer is not valid: " + packageName); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index e0fc531eb326..43135334ba74 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -1258,6 +1258,10 @@ public final class ActiveServices { mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState, s.appInfo.uid, s.name, s.processName); + // Once the apps have become associated, if one of them is caller is ephemeral + // the target app should now be able to see the calling app + mAm.grantEphemeralAccessLocked(callerApp.userId, service, + s.appInfo.uid, UserHandle.getAppId(callerApp.uid)); AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp); ConnectionRecord c = new ConnectionRecord(b, activity, diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index ace2b557c4a6..01707c59d56d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -572,11 +572,10 @@ public class ActivityManagerService extends IActivityManager.Stub // Determines whether to take full screen screenshots static final boolean TAKE_FULLSCREEN_SCREENSHOTS = true; - // STOPSHIP: Update default to a smaller value. /** * Default value for {@link Settings.Global#NETWORK_ACCESS_TIMEOUT_MS}. */ - private static final long NETWORK_ACCESS_TIMEOUT_DEFAULT_MS = 2000; // 2 sec + private static final long NETWORK_ACCESS_TIMEOUT_DEFAULT_MS = 200; // 0.2 sec /** * State indicating that there is no need for any blocking for network. @@ -4312,6 +4311,7 @@ public class ActivityManagerService extends IActivityManager.Stub validateUid.idle = false; } validateUid.curProcState = validateUid.setProcState = item.processState; + validateUid.lastDispatchedProcStateSeq = item.procStateSeq; } } } @@ -23775,11 +23775,8 @@ public class ActivityManagerService extends IActivityManager.Stub if (totalTime >= mWaitForNetworkTimeoutMs) { Slog.wtf(TAG_NETWORK, "Total time waited for network rules to get updated: " + totalTime + ". Uid: " + callingUid + " procStateSeq: " - + procStateSeq); - } else if (DEBUG_NETWORK || totalTime >= mWaitForNetworkTimeoutMs / 2) { - Slog.d(TAG_NETWORK, "Total time waited for network rules to get updated: " - + totalTime + ". Uid: " + callingUid + " procStateSeq: " - + procStateSeq); + + procStateSeq + " UidRec: " + record + + " validateUidRec: " + mValidateUids.get(callingUid)); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 089217c53789..2273452c8d9a 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -1059,7 +1059,7 @@ class ActivityStarter { // We didn't do anything... but it was needed (a.k.a., client don't use that // intent!) And for paranoia, make sure we have correctly resumed the top activity. resumeTargetStackIfNeeded(); - if (outActivity.length > 0) { + if (outActivity != null && outActivity.length > 0) { outActivity[0] = reusedActivity; } return START_TASK_TO_FRONT; diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index 9620544a9a9b..4b632fe218f9 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -384,6 +384,8 @@ public class GnssLocationProvider implements LocationProviderInterface { // Wakelocks private final static String WAKELOCK_KEY = "GnssLocationProvider"; private final PowerManager.WakeLock mWakeLock; + private static final String DOWNLOAD_EXTRA_WAKELOCK_KEY = "GnssLocationProviderXtraDownload"; + private final PowerManager.WakeLock mDownloadXtraWakeLock; // Alarms private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP"; @@ -691,6 +693,11 @@ public class GnssLocationProvider implements LocationProviderInterface { mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); mWakeLock.setReferenceCounted(true); + // Create a separate wake lock for xtra downloader as it may be released due to timeout. + mDownloadXtraWakeLock = mPowerManager.newWakeLock( + PowerManager.PARTIAL_WAKE_LOCK, DOWNLOAD_EXTRA_WAKELOCK_KEY); + mDownloadXtraWakeLock.setReferenceCounted(true); + mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0); mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0); @@ -995,7 +1002,7 @@ public class GnssLocationProvider implements LocationProviderInterface { mDownloadXtraDataPending = STATE_DOWNLOADING; // hold wake lock while task runs - mWakeLock.acquire(DOWNLOAD_XTRA_DATA_TIMEOUT_MS); + mDownloadXtraWakeLock.acquire(DOWNLOAD_XTRA_DATA_TIMEOUT_MS); Log.i(TAG, "WakeLock acquired by handleDownloadXtraData()"); AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() { @Override @@ -1017,13 +1024,17 @@ public class GnssLocationProvider implements LocationProviderInterface { mXtraBackOff.nextBackoffMillis()); } - // release wake lock held by task - if (mWakeLock.isHeld()) { - mWakeLock.release(); - } else { - Log.e(TAG, "WakeLock expired before release in handleDownloadXtraData()"); + // Release wake lock held by task, synchronize on mLock in case multiple + // download tasks overrun. + synchronized (mLock) { + if (mDownloadXtraWakeLock.isHeld()) { + mDownloadXtraWakeLock.release(); + if (DEBUG) Log.d(TAG, "WakeLock released by handleDownloadXtraData()"); + } else { + Log.e(TAG, "WakeLock expired before release in " + + "handleDownloadXtraData()"); + } } - Log.i(TAG, "WakeLock released by handleDownloadXtraData()"); } }); } diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 4c0d9da52f37..f94a56f15fe0 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -24,6 +24,7 @@ import android.content.pm.PackageParser; import android.os.Environment; import android.os.FileUtils; import android.os.PowerManager; +import android.os.SystemClock; import android.os.UserHandle; import android.os.WorkSource; import android.util.Log; @@ -54,6 +55,7 @@ import static com.android.server.pm.Installer.DEXOPT_STORAGE_DE; import static com.android.server.pm.InstructionSets.getAppDexInstructionSets; import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets; +import static com.android.server.pm.PackageManagerService.WATCHDOG_TIMEOUT; import static com.android.server.pm.PackageManagerServiceCompilerMapping.getNonProfileGuidedCompilerFilter; import static dalvik.system.DexFile.isProfileGuidedCompilerFilter; @@ -67,13 +69,17 @@ public class PackageDexOptimizer { public static final int DEX_OPT_SKIPPED = 0; public static final int DEX_OPT_PERFORMED = 1; public static final int DEX_OPT_FAILED = -1; + // One minute over PM WATCHDOG_TIMEOUT + private static final long WAKELOCK_TIMEOUT_MS = WATCHDOG_TIMEOUT + 1000 * 60; /** Special library name that skips shared libraries check during compilation. */ public static final String SKIP_SHARED_LIBRARY_CHECK = "&"; + @GuardedBy("mInstallLock") private final Installer mInstaller; private final Object mInstallLock; + @GuardedBy("mInstallLock") private final PowerManager.WakeLock mDexoptWakeLock; private volatile boolean mSystemReady; @@ -111,21 +117,12 @@ public class PackageDexOptimizer { return DEX_OPT_SKIPPED; } synchronized (mInstallLock) { - // During boot the system doesn't need to instantiate and obtain a wake lock. - // PowerManager might not be ready, but that doesn't mean that we can't proceed with - // dexopt. - final boolean useLock = mSystemReady; - if (useLock) { - mDexoptWakeLock.setWorkSource(new WorkSource(pkg.applicationInfo.uid)); - mDexoptWakeLock.acquire(); - } + final long acquireTime = acquireWakeLockLI(pkg.applicationInfo.uid); try { return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles, targetCompilationFilter, packageStats, isUsedByOtherApps); } finally { - if (useLock) { - mDexoptWakeLock.release(); - } + releaseWakeLockLI(acquireTime); } } } @@ -250,22 +247,46 @@ public class PackageDexOptimizer { public int dexOptSecondaryDexPath(ApplicationInfo info, String path, Set<String> isas, String compilerFilter, boolean isUsedByOtherApps) { synchronized (mInstallLock) { - // During boot the system doesn't need to instantiate and obtain a wake lock. - // PowerManager might not be ready, but that doesn't mean that we can't proceed with - // dexopt. - final boolean useLock = mSystemReady; - if (useLock) { - mDexoptWakeLock.setWorkSource(new WorkSource(info.uid)); - mDexoptWakeLock.acquire(); - } + final long acquireTime = acquireWakeLockLI(info.uid); try { return dexOptSecondaryDexPathLI(info, path, isas, compilerFilter, isUsedByOtherApps); } finally { - if (useLock) { - mDexoptWakeLock.release(); - } + releaseWakeLockLI(acquireTime); + } + } + } + + @GuardedBy("mInstallLock") + private long acquireWakeLockLI(final int uid) { + // During boot the system doesn't need to instantiate and obtain a wake lock. + // PowerManager might not be ready, but that doesn't mean that we can't proceed with + // dexopt. + if (!mSystemReady) { + return -1; + } + mDexoptWakeLock.setWorkSource(new WorkSource(uid)); + mDexoptWakeLock.acquire(WAKELOCK_TIMEOUT_MS); + return SystemClock.elapsedRealtime(); + } + + @GuardedBy("mInstallLock") + private void releaseWakeLockLI(final long acquireTime) { + if (acquireTime < 0) { + return; + } + try { + if (mDexoptWakeLock.isHeld()) { + mDexoptWakeLock.release(); + } + final long duration = SystemClock.elapsedRealtime() - acquireTime; + if (duration >= WAKELOCK_TIMEOUT_MS) { + Slog.wtf(TAG, "WakeLock " + mDexoptWakeLock.getTag() + + " time out. Operation took " + duration + " ms. Thread: " + + Thread.currentThread().getName()); } + } catch (Exception e) { + Slog.wtf(TAG, "Error while releasing " + mDexoptWakeLock.getTag() + " lock", e); } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 1449aee58645..c4f3b26f466b 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -445,7 +445,7 @@ public class PackageManagerService extends IPackageManager.Stub * minute but we sometimes do very lengthy I/O operations on this thread, * such as installing multi-gigabyte applications, so ours needs to be longer. */ - private static final long WATCHDOG_TIMEOUT = 1000*60*10; // ten minutes + static final long WATCHDOG_TIMEOUT = 1000*60*10; // ten minutes /** * Wall-clock timeout (in milliseconds) after which we *require* that an fstrim diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index 4a8232da2b35..be50eeeefc24 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -62,6 +62,7 @@ public class DexManager { // Maps package name to code locations. // It caches the code locations for the installed packages. This allows for // faster lookups (no locks) when finding what package owns the dex file. + @GuardedBy("mPackageCodeLocationsCache") private final Map<String, PackageCodeLocations> mPackageCodeLocationsCache; // PackageDexUsage handles the actual I/O operations. It is responsible to @@ -206,7 +207,7 @@ public class DexManager { // In case there was an update, write the package use info to disk async. // Note that we do the writing here and not in PackageDexUsage in order to be // consistent with other methods in DexManager (e.g. reconcileSecondaryDexFiles performs - // multiple updates in PackaeDexUsage before writing it). + // multiple updates in PackageDexUsage before writing it). if (mPackageDexUsage.clearUsedByOtherApps(packageName)) { mPackageDexUsage.maybeWriteAsync(); } @@ -226,7 +227,7 @@ public class DexManager { // In case there was an update, write the package use info to disk async. // Note that we do the writing here and not in PackageDexUsage in order to be // consistent with other methods in DexManager (e.g. reconcileSecondaryDexFiles performs - // multiple updates in PackaeDexUsage before writing it). + // multiple updates in PackageDexUsage before writing it). if (updated) { mPackageDexUsage.maybeWriteAsync(); } @@ -245,17 +246,22 @@ public class DexManager { private void cachePackageCodeLocation(String packageName, String baseCodePath, String[] splitCodePaths, String[] dataDirs, int userId) { - PackageCodeLocations pcl = putIfAbsent(mPackageCodeLocationsCache, packageName, - new PackageCodeLocations(packageName, baseCodePath, splitCodePaths)); - pcl.updateCodeLocation(baseCodePath, splitCodePaths); - if (dataDirs != null) { - for (String dataDir : dataDirs) { - // The set of data dirs includes deviceProtectedDataDir and - // credentialProtectedDataDir which might be null for shared - // libraries. Currently we don't track these but be lenient - // and check in case we ever decide to store their usage data. - if (dataDir != null) { - pcl.mergeAppDataDirs(dataDir, userId); + synchronized (mPackageCodeLocationsCache) { + PackageCodeLocations pcl = putIfAbsent(mPackageCodeLocationsCache, packageName, + new PackageCodeLocations(packageName, baseCodePath, splitCodePaths)); + // TODO(calin): We are forced to extend the scope of this synchronization because + // the values of the cache (PackageCodeLocations) are updated in place. + // Make PackageCodeLocations immutable to simplify the synchronization reasoning. + pcl.updateCodeLocation(baseCodePath, splitCodePaths); + if (dataDirs != null) { + for (String dataDir : dataDirs) { + // The set of data dirs includes deviceProtectedDataDir and + // credentialProtectedDataDir which might be null for shared + // libraries. Currently we don't track these but be lenient + // and check in case we ever decide to store their usage data. + if (dataDir != null) { + pcl.mergeAppDataDirs(dataDir, userId); + } } } } @@ -527,10 +533,12 @@ public class DexManager { // The loadingPackage does not own the dex file. // Perform a reverse look-up in the cache to detect if any package has ownership. // Note that we can have false negatives if the cache falls out of date. - for (PackageCodeLocations pcl : mPackageCodeLocationsCache.values()) { - outcome = pcl.searchDex(dexPath, userId); - if (outcome != DEX_SEARCH_NOT_FOUND) { - return new DexSearchResult(pcl.mPackageName, outcome); + synchronized (mPackageCodeLocationsCache) { + for (PackageCodeLocations pcl : mPackageCodeLocationsCache.values()) { + outcome = pcl.searchDex(dexPath, userId); + if (outcome != DEX_SEARCH_NOT_FOUND) { + return new DexSearchResult(pcl.mPackageName, outcome); + } } } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 42eebe14905a..cd8e2ebf81a7 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -780,6 +780,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { private boolean mBugreportTvKey2Pressed; private boolean mBugreportTvScheduled; + private boolean mAccessibilityTvKey1Pressed; + private boolean mAccessibilityTvKey2Pressed; + private boolean mAccessibilityTvScheduled; + /* The number of steps between min and max brightness */ private static final int BRIGHTNESS_STEPS = 10; @@ -824,6 +828,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final int MSG_BACK_DELAYED_PRESS = 20; private static final int MSG_ACCESSIBILITY_SHORTCUT = 21; private static final int MSG_BUGREPORT_TV = 22; + private static final int MSG_ACCESSIBILITY_TV = 23; private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0; private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1; @@ -905,6 +910,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { case MSG_BUGREPORT_TV: takeBugreport(); break; + case MSG_ACCESSIBILITY_TV: + if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(false)) { + accessibilityShortcutActivated(); + } + break; } } } @@ -3319,6 +3329,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (!down) { cancelPreloadRecentApps(); + if (mHasFeatureLeanback) { + // Clear flags + mAccessibilityTvKey2Pressed = down; + } + mHomePressed = false; if (mHomeConsumed) { mHomeConsumed = false; @@ -3373,6 +3388,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { preloadRecentApps(); } } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { + if (mHasFeatureLeanback) { + mAccessibilityTvKey2Pressed = down; + if (interceptAccessibilityGestureTv()) { + return -1; + } + } + if (!keyguardOn) { handleLongPressOnHome(event.getDeviceId()); } @@ -3532,6 +3554,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { return 0; } else if (mHasFeatureLeanback && interceptBugreportGestureTv(keyCode, down)) { return -1; + } else if (mHasFeatureLeanback && keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { + mAccessibilityTvKey1Pressed = down; + if (interceptAccessibilityGestureTv()) { + return -1; + } } // Toggle Caps Lock on META-ALT. @@ -3750,6 +3777,25 @@ public class PhoneWindowManager implements WindowManagerPolicy { return mBugreportTvScheduled; } + /** + * TV only: recognizes a remote control gesture as Accessibility shortcut. + * Shortcut: Long press (HOME + DPAD_CENTER) + */ + private boolean interceptAccessibilityGestureTv() { + if (mAccessibilityTvKey1Pressed && mAccessibilityTvKey2Pressed) { + if (!mAccessibilityTvScheduled) { + mAccessibilityTvScheduled = true; + Message msg = Message.obtain(mHandler, MSG_ACCESSIBILITY_TV); + msg.setAsynchronous(true); + mHandler.sendMessage(msg); + } + } else if (mAccessibilityTvScheduled) { + mHandler.removeMessages(MSG_ACCESSIBILITY_TV); + mAccessibilityTvScheduled = false; + } + return mAccessibilityTvScheduled; + } + private void takeBugreport() { if ("1".equals(SystemProperties.get("ro.debuggable")) || Settings.Global.getInt(mContext.getContentResolver(), @@ -8235,6 +8281,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation); pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock); pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); + if (mHasFeatureLeanback) { + pw.print(prefix); + pw.print("mAccessibilityTvKey1Pressed="); pw.println(mAccessibilityTvKey1Pressed); + pw.print(prefix); + pw.print("mAccessibilityTvKey2Pressed="); pw.println(mAccessibilityTvKey2Pressed); + pw.print(prefix); + pw.print("mAccessibilityTvScheduled="); pw.println(mAccessibilityTvScheduled); + } mGlobalKeyManager.dump(prefix, pw); mStatusBarController.dump(pw, prefix); diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index cc4c23d8727b..e1dcb0e33f4d 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -67,6 +67,7 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -575,20 +576,22 @@ public class TrustManagerService extends SystemService { } private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) { - if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(), - Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) { - return; - } - PackageManager pm = mContext.getPackageManager(); - List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId); ComponentName defaultAgent = getDefaultFactoryTrustAgent(mContext); boolean shouldUseDefaultAgent = defaultAgent != null; - ArraySet<ComponentName> discoveredAgents = new ArraySet<>(); if (shouldUseDefaultAgent) { - discoveredAgents.add(defaultAgent); Log.i(TAG, "Enabling " + defaultAgent + " because it is a default agent."); + utils.setEnabledTrustAgents(Collections.singleton(defaultAgent), userId); } else { // A default agent is not set; perform regular trust agent discovery + if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) { + return; + } + PackageManager pm = mContext.getPackageManager(); + List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId); + + ArraySet<ComponentName> discoveredAgents = new ArraySet<>(); + for (ResolveInfo resolveInfo : resolveInfos) { ComponentName componentName = getComponentName(resolveInfo); int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags; @@ -599,13 +602,13 @@ public class TrustManagerService extends SystemService { } discoveredAgents.add(componentName); } - } - List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId); - if (previouslyEnabledAgents != null) { - discoveredAgents.addAll(previouslyEnabledAgents); + List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId); + if (previouslyEnabledAgents != null) { + discoveredAgents.addAll(previouslyEnabledAgents); + } + utils.setEnabledTrustAgents(discoveredAgents, userId); } - utils.setEnabledTrustAgents(discoveredAgents, userId); Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId); } diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java index f2a92df2b820..e5c7a72c78bc 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java @@ -24,6 +24,7 @@ import android.annotation.TestApi; import android.app.ActivityManager.TaskSnapshot; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; +import android.graphics.Bitmap.Config; import android.os.Process; import android.os.SystemClock; import android.util.ArraySet; @@ -266,12 +267,13 @@ class TaskSnapshotPersister { final File file = getBitmapFile(mTaskId, mUserId); final File reducedFile = getReducedResolutionBitmapFile(mTaskId, mUserId); final Bitmap bitmap = Bitmap.createHardwareBitmap(mSnapshot.getSnapshot()); - final Bitmap reduced = Bitmap.createScaledBitmap(bitmap, + final Bitmap swBitmap = bitmap.copy(Config.ARGB_8888, false /* isMutable */); + final Bitmap reduced = Bitmap.createScaledBitmap(swBitmap, (int) (bitmap.getWidth() * REDUCED_SCALE), (int) (bitmap.getHeight() * REDUCED_SCALE), true /* filter */); try { FileOutputStream fos = new FileOutputStream(file); - bitmap.compress(JPEG, QUALITY, fos); + swBitmap.compress(JPEG, QUALITY, fos); fos.close(); FileOutputStream reducedFos = new FileOutputStream(reducedFile); reduced.compress(JPEG, QUALITY, reducedFos); diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java index c78488f9d8d9..bb7e20bcb9c3 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java @@ -368,8 +368,8 @@ public class NetworkScoreServiceTest { } @Test - public void testSetActiveScorer_noRequestNetworkScoresPermission() { - when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) + public void testSetActiveScorer_noScoreNetworksPermission() { + when(mContext.checkCallingOrSelfPermission(permission.SCORE_NETWORKS)) .thenReturn(PackageManager.PERMISSION_DENIED); try { diff --git a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java index 0694eaefd288..ceb92dece764 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java @@ -228,30 +228,23 @@ public class NetworkScorerAppManagerTest { } @Test - public void testSetActiveScorer_nullPackage_validDefault() throws Exception { - String packageName = "package"; - String defaultPackage = "defaultPackage"; - setNetworkRecoPackageSetting(packageName); - setDefaultNetworkRecommendationPackage(defaultPackage); - final ComponentName recoComponent = new ComponentName(defaultPackage, "class1"); - mockScoreNetworksGranted(recoComponent.getPackageName()); - mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null); + public void testSetActiveScorer_nullPackage_currentIsSet() throws Exception { + setNetworkRecoPackageSetting("package"); assertTrue(mNetworkScorerAppManager.setActiveScorer(null)); verify(mSettingsFacade).putString(mMockContext, - Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage); + Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, null); + verify(mSettingsFacade).putInt(mMockContext, + Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, + NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF); } @Test - public void testSetActiveScorer_nullPackage_invalidDefault() throws Exception { - String packageName = "package"; - String defaultPackage = "defaultPackage"; - setNetworkRecoPackageSetting(packageName); - setDefaultNetworkRecommendationPackage(defaultPackage); + public void testSetActiveScorer_nullPackage_currentIsNull() throws Exception { + setNetworkRecoPackageSetting(null); - assertFalse(mNetworkScorerAppManager.setActiveScorer(null)); - verify(mSettingsFacade, never()).putString(any(), - eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), any()); + assertTrue(mNetworkScorerAppManager.setActiveScorer(null)); + verify(mSettingsFacade, never()).putString(any(), any(), any()); } @Test @@ -266,6 +259,9 @@ public class NetworkScorerAppManagerTest { assertTrue(mNetworkScorerAppManager.setActiveScorer(newPackage)); verify(mSettingsFacade).putString(mMockContext, Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, newPackage); + verify(mSettingsFacade).putInt(mMockContext, + Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, + NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON); } @Test @@ -341,6 +337,32 @@ public class NetworkScorerAppManagerTest { } @Test + public void testUpdateState_currentPackageNull_defaultNull() throws Exception { + setDefaultNetworkRecommendationPackage(null); + setNetworkRecoPackageSetting(null); + + mNetworkScorerAppManager.updateState(); + + verify(mSettingsFacade, never()).putString(any(), + eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), anyString()); + verify(mSettingsFacade, never()).putInt(any(), + eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt()); + } + + @Test + public void testUpdateState_currentPackageEmpty_defaultEmpty() throws Exception { + setDefaultNetworkRecommendationPackage(""); + setNetworkRecoPackageSetting(""); + + mNetworkScorerAppManager.updateState(); + + verify(mSettingsFacade, never()).putString(any(), + eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), anyString()); + verify(mSettingsFacade, never()).putInt(any(), + eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt()); + } + + @Test public void testUpdateState_currentPackageNotValid_sameAsDefault() throws Exception { String defaultPackage = "defaultPackage"; setDefaultNetworkRecommendationPackage(defaultPackage); diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java index ff632a5cdc7c..b133a44d0117 100644 --- a/wifi/java/android/net/wifi/RttManager.java +++ b/wifi/java/android/net/wifi/RttManager.java @@ -660,10 +660,10 @@ public class RttManager { @Deprecated public int tx_rate; - /** average transmit rate. Unit (100kbps). */ + /** average transmit rate. Unit (kbps). */ public int txRate; - /** average receiving rate Unit (100kbps). */ + /** average receiving rate Unit (kbps). */ public int rxRate; /** @@ -673,7 +673,7 @@ public class RttManager { @Deprecated public long rtt_ns; - /** average round trip time in 0.1 nano second. */ + /** average round trip time in picoseconds. */ public long rtt; /** @@ -683,7 +683,7 @@ public class RttManager { @Deprecated public long rtt_sd_ns; - /** standard deviation of RTT in 0.1 ns. */ + /** standard deviation of RTT in picoseconds. */ public long rttStandardDeviation; /** @@ -693,7 +693,7 @@ public class RttManager { @Deprecated public long rtt_spread_ns; - /** spread (i.e. max - min) RTT in 0.1 ns. */ + /** spread (i.e. max - min) RTT in picoseconds. */ public long rttSpread; /** diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index e31a74b42b14..f7333e281982 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -839,6 +839,10 @@ public class WifiConfiguration implements Parcelable { */ public static final int NETWORK_SELECTION_ENABLE = 0; /** + * The starting index for network selection disabled reasons + */ + public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1; + /** * @deprecated it is not used any more. * This network is disabled because higher layer (>2) network is bad */ |