summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt4
-rw-r--r--api/system-current.txt4
-rw-r--r--api/test-current.txt4
-rw-r--r--config/preloaded-classes70
-rw-r--r--config/preloaded-classes-extra12
-rw-r--r--core/java/android/app/ActivityTransitionCoordinator.java7
-rw-r--r--core/java/android/app/usage/UsageStatsManager.java3
-rwxr-xr-xcore/java/android/provider/Settings.java6
-rw-r--r--core/java/android/util/TimingsTraceLog.java14
-rw-r--r--core/java/android/view/FocusFinder.java4
-rw-r--r--core/java/android/view/textclassifier/TextClassification.java2
-rw-r--r--core/java/android/view/textclassifier/TextSelection.java2
-rw-r--r--core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java6
-rw-r--r--core/java/android/widget/RemoteViews.java325
-rw-r--r--core/java/android/widget/SelectionActionModeHelper.java129
-rw-r--r--core/java/android/widget/TabHost.java5
-rw-r--r--core/java/android/widget/TextView.java6
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java4
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java8
-rw-r--r--core/java/com/android/internal/widget/PointerLocationView.java7
-rw-r--r--core/res/res/drawable/ic_close.xml2
-rw-r--r--core/res/res/drawable/ic_eject_24dp.xml5
-rw-r--r--core/res/res/drawable/ic_feedback.xml2
-rw-r--r--core/res/res/drawable/ic_refresh.xml2
-rw-r--r--core/res/res/values/config.xml2
-rw-r--r--core/res/res/values/strings.xml4
-rw-r--r--core/tests/coretests/src/android/util/TimingsTraceLogTest.java70
-rw-r--r--core/tests/coretests/src/android/widget/RemoteViewsTest.java34
-rw-r--r--core/tests/coretests/src/android/widget/SelectionActionModeHelperTest.java151
-rw-r--r--data/keyboards/Vendor_054c_Product_09cc.kl67
-rw-r--r--data/sounds/AudioPackageGo.mk6
-rw-r--r--keystore/java/android/security/KeyStore.java2
-rw-r--r--libs/hwui/renderthread/CanvasContext.h4
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp2
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.h4
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp14
-rw-r--r--packages/SystemUI/res/values-ldrtl/config.xml2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java54
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java5
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java13
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java2
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java4
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerServiceImpl.java9
-rw-r--r--services/core/java/com/android/server/pm/OtaDexoptService.java8
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java14
-rw-r--r--services/core/java/com/android/server/pm/dex/DexoptUtils.java17
-rw-r--r--services/core/java/com/android/server/webkit/WebViewUpdater.java1
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java10
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java9
-rw-r--r--services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp4
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java49
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java5
-rw-r--r--tools/aapt2/xml/XmlDom.cpp16
68 files changed, 938 insertions, 439 deletions
diff --git a/api/current.txt b/api/current.txt
index ecba8e0d8130..9c3929503a12 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -40289,6 +40289,7 @@ package android.telephony {
method public int getPhoneCount();
method public int getPhoneType();
method public android.telephony.ServiceState getServiceState();
+ method public android.telephony.SignalStrength getSignalStrength();
method public java.lang.String getSimCountryIso();
method public java.lang.String getSimOperator();
method public java.lang.String getSimOperatorName();
@@ -51074,10 +51075,11 @@ package android.widget {
public class RemoteViews implements android.view.LayoutInflater.Filter android.os.Parcelable {
ctor public RemoteViews(java.lang.String, int);
ctor public RemoteViews(android.widget.RemoteViews, android.widget.RemoteViews);
+ ctor public RemoteViews(android.widget.RemoteViews);
ctor public RemoteViews(android.os.Parcel);
method public void addView(int, android.widget.RemoteViews);
method public android.view.View apply(android.content.Context, android.view.ViewGroup);
- method public android.widget.RemoteViews clone();
+ method public deprecated android.widget.RemoteViews clone();
method public int describeContents();
method public int getLayoutId();
method public java.lang.String getPackage();
diff --git a/api/system-current.txt b/api/system-current.txt
index 406da4fc5861..4a76bfbda1d0 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -43809,6 +43809,7 @@ package android.telephony {
method public int getPhoneCount();
method public int getPhoneType();
method public android.telephony.ServiceState getServiceState();
+ method public android.telephony.SignalStrength getSignalStrength();
method public java.lang.String getSimCountryIso();
method public java.lang.String getSimOperator();
method public java.lang.String getSimOperatorName();
@@ -55052,10 +55053,11 @@ package android.widget {
public class RemoteViews implements android.view.LayoutInflater.Filter android.os.Parcelable {
ctor public RemoteViews(java.lang.String, int);
ctor public RemoteViews(android.widget.RemoteViews, android.widget.RemoteViews);
+ ctor public RemoteViews(android.widget.RemoteViews);
ctor public RemoteViews(android.os.Parcel);
method public void addView(int, android.widget.RemoteViews);
method public android.view.View apply(android.content.Context, android.view.ViewGroup);
- method public android.widget.RemoteViews clone();
+ method public deprecated android.widget.RemoteViews clone();
method public int describeContents();
method public int getLayoutId();
method public java.lang.String getPackage();
diff --git a/api/test-current.txt b/api/test-current.txt
index eae151b15ddf..9f5266626c50 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -40580,6 +40580,7 @@ package android.telephony {
method public int getPhoneCount();
method public int getPhoneType();
method public android.telephony.ServiceState getServiceState();
+ method public android.telephony.SignalStrength getSignalStrength();
method public java.lang.String getSimCountryIso();
method public java.lang.String getSimOperator();
method public java.lang.String getSimOperatorName();
@@ -51577,10 +51578,11 @@ package android.widget {
public class RemoteViews implements android.view.LayoutInflater.Filter android.os.Parcelable {
ctor public RemoteViews(java.lang.String, int);
ctor public RemoteViews(android.widget.RemoteViews, android.widget.RemoteViews);
+ ctor public RemoteViews(android.widget.RemoteViews);
ctor public RemoteViews(android.os.Parcel);
method public void addView(int, android.widget.RemoteViews);
method public android.view.View apply(android.content.Context, android.view.ViewGroup);
- method public android.widget.RemoteViews clone();
+ method public deprecated android.widget.RemoteViews clone();
method public int describeContents();
method public int getLayoutId();
method public java.lang.String getPackage();
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 5da78091448e..cd2965392c44 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -1159,6 +1159,7 @@ android.icu.impl.ICUService
android.icu.impl.ICUService$CacheEntry
android.icu.impl.ICUService$Factory
android.icu.impl.ICUService$Key
+android.icu.impl.IDNA2003
android.icu.impl.LocaleIDParser
android.icu.impl.LocaleIDs
android.icu.impl.Norm2AllModes
@@ -1254,6 +1255,7 @@ android.icu.impl.locale.BaseLocale$Key
android.icu.impl.locale.LocaleObjectCache
android.icu.impl.locale.LocaleObjectCache$CacheEntry
android.icu.impl.locale.LocaleSyntaxException
+android.icu.impl.number.Parse
android.icu.lang.UCharacter
android.icu.lang.UCharacterEnums$ECharacterCategory
android.icu.lang.UCharacterEnums$ECharacterDirection
@@ -1468,6 +1470,7 @@ android.media.IRingtonePlayer
android.media.IRingtonePlayer$Stub
android.media.IRingtonePlayer$Stub$Proxy
android.media.Image
+android.media.ImageReader
android.media.JetPlayer
android.media.MediaCodec$BufferInfo
android.media.MediaCodec$BufferMap
@@ -1478,9 +1481,11 @@ android.media.MediaCodecInfo$AudioCapabilities
android.media.MediaCodecInfo$CodecProfileLevel
android.media.MediaCodecInfo$Feature
android.media.MediaCodecInfo$VideoCapabilities
+android.media.MediaCodecList
android.media.MediaFormat
android.media.MediaMetadata$1
android.media.MediaMetadata$Builder
+android.media.MediaPlayer
android.media.MediaPlayer$1
android.media.MediaPlayer$2
android.media.MediaPlayer$EventHandler
@@ -1511,6 +1516,7 @@ android.media.PlayerBase$IPlayerWrapper
android.media.PlayerBase$PlayerIdCard$1
android.media.RemoteDisplay
android.media.Ringtone$MyOnCompletionListener
+android.media.SoundPool
android.media.SubtitleController$Listener
android.media.ToneGenerator
android.media.Utils
@@ -2050,6 +2056,7 @@ android.text.FontConfig$Font
android.text.GetChars
android.text.GraphicsOperations
android.text.Html
+android.text.Html$HtmlParser
android.text.HtmlToSpannedConverter$Href
android.text.Hyphenator
android.text.Hyphenator$HyphenationData
@@ -2099,6 +2106,7 @@ android.text.TextUtils$SimpleStringSplitter
android.text.TextUtils$StringSplitter
android.text.TextUtils$TruncateAt
android.text.TextWatcher
+android.text.format.Formatter
android.text.format.Time$TimeCalculator
android.text.method.AllCapsTransformationMethod
android.text.method.ArrowKeyMovementMethod
@@ -4426,81 +4434,21 @@ org.apache.harmony.xml.ExpatParser$ExpatLocator
org.apache.harmony.xml.ExpatReader
org.apache.harmony.xml.parsers.SAXParserFactoryImpl
org.apache.harmony.xml.parsers.SAXParserImpl
-org.apache.http.ConnectionReuseStrategy
-org.apache.http.HeaderElement
-org.apache.http.HttpEntity
-org.apache.http.HttpException
-org.apache.http.HttpHost
-org.apache.http.HttpMessage
-org.apache.http.HttpRequest
-org.apache.http.HttpRequestInterceptor
-org.apache.http.HttpResponse
-org.apache.http.HttpResponseFactory
-org.apache.http.NameValuePair
-org.apache.http.ProtocolException
-org.apache.http.ProtocolVersion
-org.apache.http.ReasonPhraseCatalog
-org.apache.http.StatusLine
-org.apache.http.client.HttpClient
-org.apache.http.client.ResponseHandler
-org.apache.http.client.methods.AbortableHttpRequest
-org.apache.http.client.methods.HttpRequestBase
-org.apache.http.client.methods.HttpUriRequest
-org.apache.http.client.params.HttpClientParams
-org.apache.http.conn.ClientConnectionManager
-org.apache.http.conn.ClientConnectionOperator
org.apache.http.conn.ConnectTimeoutException
-org.apache.http.conn.params.ConnManagerPNames
-org.apache.http.conn.params.ConnManagerParams$1
-org.apache.http.conn.params.ConnPerRoute
org.apache.http.conn.scheme.LayeredSocketFactory
-org.apache.http.conn.scheme.Scheme
-org.apache.http.conn.scheme.SchemeRegistry
org.apache.http.conn.scheme.SocketFactory
org.apache.http.conn.ssl.AllowAllHostnameVerifier
org.apache.http.conn.ssl.BrowserCompatHostnameVerifier
org.apache.http.conn.ssl.StrictHostnameVerifier
org.apache.http.conn.ssl.X509HostnameVerifier
-org.apache.http.entity.AbstractHttpEntity
-org.apache.http.entity.BasicHttpEntity
-org.apache.http.impl.DefaultConnectionReuseStrategy
-org.apache.http.impl.DefaultHttpResponseFactory
-org.apache.http.impl.client.AbstractHttpClient
-org.apache.http.impl.client.DefaultHttpClient
-org.apache.http.impl.conn.IdleConnectionHandler
-org.apache.http.impl.conn.tsccm.AbstractConnPool
-org.apache.http.impl.conn.tsccm.ConnPoolByRoute
-org.apache.http.impl.conn.tsccm.RefQueueHandler
-org.apache.http.impl.conn.tsccm.RefQueueWorker
-org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager
-org.apache.http.impl.cookie.DateParseException
-org.apache.http.impl.cookie.DateUtils$DateFormatHolder$1
-org.apache.http.message.AbstractHttpMessage
-org.apache.http.message.BasicHeader
-org.apache.http.message.BasicHeaderElement
-org.apache.http.message.BasicHttpResponse
-org.apache.http.message.BasicNameValuePair
-org.apache.http.message.BasicStatusLine
-org.apache.http.message.HeaderGroup
-org.apache.http.message.HeaderValueParser
-org.apache.http.message.ParserCursor
-org.apache.http.params.AbstractHttpParams
-org.apache.http.params.BasicHttpParams
org.apache.http.params.CoreConnectionPNames
-org.apache.http.params.CoreProtocolPNames
org.apache.http.params.HttpConnectionParams
org.apache.http.params.HttpParams
-org.apache.http.params.HttpProtocolParams
-org.apache.http.protocol.BasicHttpProcessor
-org.apache.http.protocol.HTTP
-org.apache.http.protocol.HttpContext
-org.apache.http.protocol.HttpRequestInterceptorList
-org.apache.http.protocol.HttpResponseInterceptorList
-org.apache.http.util.CharArrayBuffer
org.ccil.cowan.tagsoup.AttributesImpl
org.ccil.cowan.tagsoup.AutoDetector
org.ccil.cowan.tagsoup.Element
org.ccil.cowan.tagsoup.ElementType
+org.ccil.cowan.tagsoup.HTMLScanner
org.ccil.cowan.tagsoup.HTMLSchema
org.ccil.cowan.tagsoup.Parser$1
org.ccil.cowan.tagsoup.ScanHandler
diff --git a/config/preloaded-classes-extra b/config/preloaded-classes-extra
index 1934cbca27ad..959fff5c1e5c 100644
--- a/config/preloaded-classes-extra
+++ b/config/preloaded-classes-extra
@@ -1 +1,13 @@
android.icu.impl.coll.CollationRoot
+android.icu.impl.IDNA2003
+android.icu.impl.number.Parse
+android.icu.util.TimeZone
+android.media.ImageReader
+android.media.MediaCodecList
+android.media.MediaPlayer
+android.media.SoundPool
+android.text.format.Formatter
+android.text.Html$HtmlParser
+com.android.org.conscrypt.TrustedCertificateStore
+org.ccil.cowan.tagsoup.HTMLScanner
+sun.security.jca.Providers
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 7d4d70d49d53..9b2bfc5702cb 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -1006,9 +1006,12 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
final int numElements = mTransitioningViews == null ? 0 : mTransitioningViews.size();
for (int i = 0; i < numElements; i++) {
final View view = mTransitioningViews.get(i);
- view.setTransitionVisibility(visiblity);
if (invalidate) {
- view.invalidate();
+ // Allow the view to be invalidated by the visibility change
+ view.setVisibility(visiblity);
+ } else {
+ // Don't invalidate the view with the visibility change
+ view.setTransitionVisibility(visiblity);
}
}
}
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 1f939f996c68..051dccbd86c0 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -172,9 +172,6 @@ public final class UsageStatsManager {
/**
* Query for events in the given time range. Events are only kept by the system for a few
* days.
- * <p />
- * <b>NOTE:</b> The last few minutes of the event log will be truncated to prevent abuse
- * by applications.
*
* @param beginTime The inclusive beginning of the range of events to include in the results.
* @param endTime The exclusive end of the range of events to include in the results.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6f8ba489ee0c..2cb3864f9ea4 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7120,6 +7120,11 @@ public final class Settings {
public static final String QS_AUTO_ADDED_TILES = "qs_auto_tiles";
/**
+ * Whether the Lockdown button should be shown in the power menu.
+ * @hide
+ */
+ public static final String LOCKDOWN_IN_POWER_MENU = "lockdown_in_power_menu";
+ /**
* This are the settings to be backed up.
*
* NOTE: Settings are backed up and restored in the order they appear
@@ -7221,6 +7226,7 @@ public final class Settings {
SCREENSAVER_COMPONENTS,
SCREENSAVER_ACTIVATE_ON_DOCK,
SCREENSAVER_ACTIVATE_ON_SLEEP,
+ LOCKDOWN_IN_POWER_MENU,
};
/** @hide */
diff --git a/core/java/android/util/TimingsTraceLog.java b/core/java/android/util/TimingsTraceLog.java
index 36e9f77bb831..3e6f09bfa799 100644
--- a/core/java/android/util/TimingsTraceLog.java
+++ b/core/java/android/util/TimingsTraceLog.java
@@ -25,6 +25,7 @@ import java.util.Deque;
/**
* Helper class for reporting boot and shutdown timing metrics.
+ * <p>Note: This class is not thread-safe. Use a separate copy for other threads</p>
* @hide
*/
public class TimingsTraceLog {
@@ -34,10 +35,12 @@ public class TimingsTraceLog {
DEBUG_BOOT_TIME ? new ArrayDeque<>() : null;
private final String mTag;
private long mTraceTag;
+ private long mThreadId;
public TimingsTraceLog(String tag, long traceTag) {
mTag = tag;
mTraceTag = traceTag;
+ mThreadId = Thread.currentThread().getId();
}
/**
@@ -45,6 +48,7 @@ public class TimingsTraceLog {
* @param name name to appear in trace
*/
public void traceBegin(String name) {
+ assertSameThread();
Trace.traceBegin(mTraceTag, name);
if (DEBUG_BOOT_TIME) {
mStartTimes.push(Pair.create(name, SystemClock.elapsedRealtime()));
@@ -56,6 +60,7 @@ public class TimingsTraceLog {
* Also {@link #logDuration logs} the duration.
*/
public void traceEnd() {
+ assertSameThread();
Trace.traceEnd(mTraceTag);
if (!DEBUG_BOOT_TIME) {
return;
@@ -68,6 +73,15 @@ public class TimingsTraceLog {
logDuration(event.first, (SystemClock.elapsedRealtime() - event.second));
}
+ private void assertSameThread() {
+ final Thread currentThread = Thread.currentThread();
+ if (currentThread.getId() != mThreadId) {
+ throw new IllegalStateException("Instance of TimingsTraceLog can only be called from "
+ + "the thread it was created on (tid: " + mThreadId + "), but was from "
+ + currentThread.getName() + " (tid: " + currentThread.getId() + ")");
+ }
+ }
+
/**
* Log the duration so it can be parsed by external tools for performance reporting
*/
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index af26a88e877c..74555de5f291 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -574,10 +574,10 @@ public class FocusFinder {
switch (direction) {
case View.FOCUS_LEFT:
case View.FOCUS_RIGHT:
- return (rect2.bottom >= rect1.top) && (rect2.top <= rect1.bottom);
+ return (rect2.bottom > rect1.top) && (rect2.top < rect1.bottom);
case View.FOCUS_UP:
case View.FOCUS_DOWN:
- return (rect2.right >= rect1.left) && (rect2.left <= rect1.right);
+ return (rect2.right > rect1.left) && (rect2.left < rect1.right);
}
throw new IllegalArgumentException("direction must be one of "
+ "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index fa7b9a59c669..1849368f6ae9 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -261,7 +261,7 @@ public final class TextClassification {
* @hide
*/
Builder setVersionInfo(@NonNull String versionInfo) {
- mVersionInfo = Preconditions.checkNotNull(mVersionInfo);
+ mVersionInfo = Preconditions.checkNotNull(versionInfo);
return this;
}
diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java
index 085dd32966b0..11ebe8359b9c 100644
--- a/core/java/android/view/textclassifier/TextSelection.java
+++ b/core/java/android/view/textclassifier/TextSelection.java
@@ -169,7 +169,7 @@ public final class TextSelection {
* @hide
*/
Builder setVersionInfo(@NonNull String versionInfo) {
- mVersionInfo = Preconditions.checkNotNull(mVersionInfo);
+ mVersionInfo = Preconditions.checkNotNull(versionInfo);
return this;
}
diff --git a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
index 45baf912ebb2..77aea2345304 100644
--- a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
+++ b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
@@ -253,6 +253,7 @@ public final class SmartSelectionEventTracker {
private static void debugLog(LogMaker log) {
if (!DEBUG_LOG_ENABLED) return;
+ final String tag = Objects.toString(log.getTaggedData(TAG), "tag");
final int index = Integer.parseInt(Objects.toString(log.getTaggedData(INDEX), ZERO));
final String event;
@@ -291,7 +292,6 @@ public final class SmartSelectionEventTracker {
event = "RESET";
break;
case SelectionEvent.EventType.SELECTION_STARTED:
- final String tag = Objects.toString(log.getTaggedData(TAG), "tag");
String sessionId = Objects.toString(log.getTaggedData(SESSION_ID), "");
sessionId = sessionId.substring(sessionId.lastIndexOf("-") + 1);
Log.d(LOG_TAG, String.format("New selection session: %s(%s)", tag, sessionId));
@@ -326,8 +326,8 @@ public final class SmartSelectionEventTracker {
final String entity = Objects.toString(
log.getTaggedData(ENTITY_TYPE), TextClassifier.TYPE_UNKNOWN);
- Log.d(LOG_TAG, String.format("%2d: %s, context=%d,%d - old=%d,%d [%s]",
- index, event, eventStart, eventEnd, smartStart, smartEnd, entity));
+ Log.d(LOG_TAG, String.format("%2d: %s, context=%d,%d - old=%d,%d [%s] (%s)",
+ index, event, eventStart, eventEnd, smartStart, smartEnd, entity, tag));
}
/**
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 46742b8852ff..bc85fadb5ad9 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -144,11 +144,6 @@ public class RemoteViews implements Parcelable, Filter {
private ArrayList<Action> mActions;
/**
- * A class to keep track of memory usage by this RemoteViews
- */
- private MemoryUsageCounter mMemoryUsageCounter;
-
- /**
* Maps bitmaps to unique indicies to avoid Bitmap duplication.
*/
private BitmapCache mBitmapCache;
@@ -294,7 +289,6 @@ public class RemoteViews implements Parcelable, Filter {
public String asyncMethodName;
}
-
/**
* This annotation indicates that a subclass of View is allowed to be used
* with the {@link RemoteViews} mechanism.
@@ -386,14 +380,6 @@ public class RemoteViews implements Parcelable, Filter {
return 0;
}
- /**
- * Overridden by each class to report on it's own memory usage
- */
- public void updateMemoryUsageEstimate(MemoryUsageCounter counter) {
- // We currently only calculate Bitmap memory usage, so by default,
- // don't do anything here
- }
-
public void setBitmapCache(BitmapCache bitmapCache) {
// Do nothing
}
@@ -466,7 +452,7 @@ public class RemoteViews implements Parcelable, Filter {
// We first copy the new RemoteViews, as the process of merging modifies the way the actions
// reference the bitmap cache. We don't want to modify the object as it may need to
// be merged and applied multiple times.
- RemoteViews copy = newRv.clone();
+ RemoteViews copy = new RemoteViews(newRv);
HashMap<String, Action> map = new HashMap<String, Action>();
if (mActions == null) {
@@ -500,7 +486,6 @@ public class RemoteViews implements Parcelable, Filter {
// Because pruning can remove the need for bitmaps, we reconstruct the bitmap cache
mBitmapCache = new BitmapCache();
setBitmapCache(mBitmapCache);
- recalculateMemoryUsage();
}
private static class RemoteViewsContextWrapper extends ContextWrapper {
@@ -1162,15 +1147,17 @@ public class RemoteViews implements Parcelable, Filter {
}
private static class BitmapCache {
+
ArrayList<Bitmap> mBitmaps;
+ int mBitmapMemory = -1;
public BitmapCache() {
- mBitmaps = new ArrayList<Bitmap>();
+ mBitmaps = new ArrayList<>();
}
public BitmapCache(Parcel source) {
int count = source.readInt();
- mBitmaps = new ArrayList<Bitmap>();
+ mBitmaps = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
Bitmap b = Bitmap.CREATOR.createFromParcel(source);
mBitmaps.add(b);
@@ -1185,6 +1172,7 @@ public class RemoteViews implements Parcelable, Filter {
return mBitmaps.indexOf(b);
} else {
mBitmaps.add(b);
+ mBitmapMemory = -1;
return (mBitmaps.size() - 1);
}
}
@@ -1206,28 +1194,15 @@ public class RemoteViews implements Parcelable, Filter {
}
}
- public void assimilate(BitmapCache bitmapCache) {
- ArrayList<Bitmap> bitmapsToBeAdded = bitmapCache.mBitmaps;
- int count = bitmapsToBeAdded.size();
- for (int i = 0; i < count; i++) {
- Bitmap b = bitmapsToBeAdded.get(i);
- if (!mBitmaps.contains(b)) {
- mBitmaps.add(b);
+ public int getBitmapMemory() {
+ if (mBitmapMemory < 0) {
+ mBitmapMemory = 0;
+ int count = mBitmaps.size();
+ for (int i = 0; i < count; i++) {
+ mBitmapMemory += mBitmaps.get(i).getAllocationByteCount();
}
}
- }
-
- public void addBitmapMemory(MemoryUsageCounter memoryCounter) {
- for (int i = 0; i < mBitmaps.size(); i++) {
- memoryCounter.addBitmapMemory(mBitmaps.get(i));
- }
- }
-
- @Override
- protected BitmapCache clone() {
- BitmapCache bitmapCache = new BitmapCache();
- bitmapCache.mBitmaps.addAll(mBitmaps);
- return bitmapCache;
+ return mBitmapMemory;
}
}
@@ -1429,37 +1404,17 @@ public class RemoteViews implements Parcelable, Filter {
case CHAR_SEQUENCE:
TextUtils.writeToParcel((CharSequence)this.value, out, flags);
break;
- case URI:
- out.writeInt(this.value != null ? 1 : 0);
- if (this.value != null) {
- ((Uri)this.value).writeToParcel(out, flags);
- }
- break;
- case BITMAP:
- out.writeInt(this.value != null ? 1 : 0);
- if (this.value != null) {
- ((Bitmap)this.value).writeToParcel(out, flags);
- }
- break;
case BUNDLE:
out.writeBundle((Bundle) this.value);
break;
+ case URI:
+ case BITMAP:
case INTENT:
- out.writeInt(this.value != null ? 1 : 0);
- if (this.value != null) {
- ((Intent)this.value).writeToParcel(out, flags);
- }
- break;
case COLOR_STATE_LIST:
- out.writeInt(this.value != null ? 1 : 0);
- if (this.value != null) {
- ((ColorStateList)this.value).writeToParcel(out, flags);
- }
- break;
case ICON:
out.writeInt(this.value != null ? 1 : 0);
if (this.value != null) {
- ((Icon)this.value).writeToParcel(out, flags);
+ ((Parcelable) this.value).writeToParcel(out, flags);
}
break;
default:
@@ -1595,7 +1550,6 @@ public class RemoteViews implements Parcelable, Filter {
}
private void configureRemoteViewsAsChild(RemoteViews rv) {
- mBitmapCache.assimilate(rv.mBitmapCache);
rv.setBitmapCache(mBitmapCache);
rv.setNotRoot();
}
@@ -1693,11 +1647,6 @@ public class RemoteViews implements Parcelable, Filter {
}
@Override
- public void updateMemoryUsageEstimate(MemoryUsageCounter counter) {
- counter.increment(mNestedViews.estimateMemoryUsage());
- }
-
- @Override
public void setBitmapCache(BitmapCache bitmapCache) {
mNestedViews.setBitmapCache(bitmapCache);
}
@@ -2302,30 +2251,6 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
- * Simple class used to keep track of memory usage in a RemoteViews.
- *
- */
- private class MemoryUsageCounter {
- public void clear() {
- mMemoryUsage = 0;
- }
-
- public void increment(int numBytes) {
- mMemoryUsage += numBytes;
- }
-
- public int getMemoryUsage() {
- return mMemoryUsage;
- }
-
- public void addBitmapMemory(Bitmap b) {
- increment(b.getAllocationByteCount());
- }
-
- int mMemoryUsage;
- }
-
- /**
* Create a new RemoteViews object that will display the views contained
* in the specified layout file.
*
@@ -2363,9 +2288,6 @@ public class RemoteViews implements Parcelable, Filter {
mApplication = application;
mLayoutId = layoutId;
mBitmapCache = new BitmapCache();
- // setup the memory usage statistics
- mMemoryUsageCounter = new MemoryUsageCounter();
- recalculateMemoryUsage();
}
private boolean hasLandscapeAndPortraitLayouts() {
@@ -2393,14 +2315,49 @@ public class RemoteViews implements Parcelable, Filter {
mLandscape = landscape;
mPortrait = portrait;
- // setup the memory usage statistics
- mMemoryUsageCounter = new MemoryUsageCounter();
-
mBitmapCache = new BitmapCache();
configureRemoteViewsAsChild(landscape);
configureRemoteViewsAsChild(portrait);
+ }
+
+ /**
+ * Creates a copy of another RemoteViews.
+ */
+ public RemoteViews(RemoteViews src) {
+ mBitmapCache = src.mBitmapCache;
+ mApplication = src.mApplication;
+ mIsRoot = src.mIsRoot;
+ mLayoutId = src.mLayoutId;
+ mIsWidgetCollectionChild = src.mIsWidgetCollectionChild;
+ mReapplyDisallowed = src.mReapplyDisallowed;
+
+ if (src.hasLandscapeAndPortraitLayouts()) {
+ mLandscape = new RemoteViews(src.mLandscape);
+ mPortrait = new RemoteViews(src.mPortrait);
+
+ }
+
+ if (src.mActions != null) {
+ mActions = new ArrayList<>();
- recalculateMemoryUsage();
+ Parcel p = Parcel.obtain();
+ int count = src.mActions.size();
+ for (int i = 0; i < count; i++) {
+ p.setDataPosition(0);
+ Action a = src.mActions.get(i);
+ a.writeToParcel(
+ p, a.hasSameAppInfo(mApplication) ? PARCELABLE_ELIDE_DUPLICATES : 0);
+ p.setDataPosition(0);
+ // Since src is already in memory, we do not care about stack overflow as it has
+ // already been read once.
+ mActions.add(getActionFromParcel(p, 0));
+ }
+ p.recycle();
+ }
+
+ // Now that everything is initialized and duplicated, setting a new BitmapCache will
+ // re-initialize the cache.
+ setBitmapCache(new BitmapCache());
}
/**
@@ -2437,71 +2394,9 @@ public class RemoteViews implements Parcelable, Filter {
int count = parcel.readInt();
if (count > 0) {
- mActions = new ArrayList<Action>(count);
- for (int i=0; i<count; i++) {
- int tag = parcel.readInt();
- switch (tag) {
- case SET_ON_CLICK_PENDING_INTENT_TAG:
- mActions.add(new SetOnClickPendingIntent(parcel));
- break;
- case SET_DRAWABLE_PARAMETERS_TAG:
- mActions.add(new SetDrawableParameters(parcel));
- break;
- case REFLECTION_ACTION_TAG:
- mActions.add(new ReflectionAction(parcel));
- break;
- case VIEW_GROUP_ACTION_ADD_TAG:
- mActions.add(new ViewGroupActionAdd(parcel, mBitmapCache, mApplication,
- depth));
- break;
- case VIEW_GROUP_ACTION_REMOVE_TAG:
- mActions.add(new ViewGroupActionRemove(parcel));
- break;
- case SET_REFLECTION_ACTION_WITHOUT_PARAMS_TAG:
- mActions.add(new ReflectionActionWithoutParams(parcel));
- break;
- case SET_EMPTY_VIEW_ACTION_TAG:
- mActions.add(new SetEmptyView(parcel));
- break;
- case SET_PENDING_INTENT_TEMPLATE_TAG:
- mActions.add(new SetPendingIntentTemplate(parcel));
- break;
- case SET_ON_CLICK_FILL_IN_INTENT_TAG:
- mActions.add(new SetOnClickFillInIntent(parcel));
- break;
- case SET_REMOTE_VIEW_ADAPTER_INTENT_TAG:
- mActions.add(new SetRemoteViewsAdapterIntent(parcel));
- break;
- case TEXT_VIEW_DRAWABLE_ACTION_TAG:
- mActions.add(new TextViewDrawableAction(parcel));
- break;
- case TEXT_VIEW_SIZE_ACTION_TAG:
- mActions.add(new TextViewSizeAction(parcel));
- break;
- case VIEW_PADDING_ACTION_TAG:
- mActions.add(new ViewPaddingAction(parcel));
- break;
- case BITMAP_REFLECTION_ACTION_TAG:
- mActions.add(new BitmapReflectionAction(parcel));
- break;
- case SET_REMOTE_VIEW_ADAPTER_LIST_TAG:
- mActions.add(new SetRemoteViewsAdapterList(parcel));
- break;
- case TEXT_VIEW_DRAWABLE_COLOR_FILTER_ACTION_TAG:
- mActions.add(new TextViewDrawableColorFilterAction(parcel));
- break;
- case SET_REMOTE_INPUTS_ACTION_TAG:
- mActions.add(new SetRemoteInputsAction(parcel));
- break;
- case LAYOUT_PARAM_ACTION_TAG:
- mActions.add(new LayoutParamAction(parcel));
- break;
- case OVERRIDE_TEXT_COLORS_TAG:
- mActions.add(new OverrideTextColorsAction(parcel));
- break;
- default:
- throw new ActionException("Tag " + tag + " not found");
- }
+ mActions = new ArrayList<>(count);
+ for (int i = 0; i < count; i++) {
+ mActions.add(getActionFromParcel(parcel, depth));
}
}
} else {
@@ -2512,40 +2407,69 @@ public class RemoteViews implements Parcelable, Filter {
mLayoutId = mPortrait.getLayoutId();
}
mReapplyDisallowed = parcel.readInt() == 0;
-
- // setup the memory usage statistics
- mMemoryUsageCounter = new MemoryUsageCounter();
- recalculateMemoryUsage();
}
+ private Action getActionFromParcel(Parcel parcel, int depth) {
+ int tag = parcel.readInt();
+ switch (tag) {
+ case SET_ON_CLICK_PENDING_INTENT_TAG:
+ return new SetOnClickPendingIntent(parcel);
+ case SET_DRAWABLE_PARAMETERS_TAG:
+ return new SetDrawableParameters(parcel);
+ case REFLECTION_ACTION_TAG:
+ return new ReflectionAction(parcel);
+ case VIEW_GROUP_ACTION_ADD_TAG:
+ return new ViewGroupActionAdd(parcel, mBitmapCache, mApplication, depth);
+ case VIEW_GROUP_ACTION_REMOVE_TAG:
+ return new ViewGroupActionRemove(parcel);
+ case SET_REFLECTION_ACTION_WITHOUT_PARAMS_TAG:
+ return new ReflectionActionWithoutParams(parcel);
+ case SET_EMPTY_VIEW_ACTION_TAG:
+ return new SetEmptyView(parcel);
+ case SET_PENDING_INTENT_TEMPLATE_TAG:
+ return new SetPendingIntentTemplate(parcel);
+ case SET_ON_CLICK_FILL_IN_INTENT_TAG:
+ return new SetOnClickFillInIntent(parcel);
+ case SET_REMOTE_VIEW_ADAPTER_INTENT_TAG:
+ return new SetRemoteViewsAdapterIntent(parcel);
+ case TEXT_VIEW_DRAWABLE_ACTION_TAG:
+ return new TextViewDrawableAction(parcel);
+ case TEXT_VIEW_SIZE_ACTION_TAG:
+ return new TextViewSizeAction(parcel);
+ case VIEW_PADDING_ACTION_TAG:
+ return new ViewPaddingAction(parcel);
+ case BITMAP_REFLECTION_ACTION_TAG:
+ return new BitmapReflectionAction(parcel);
+ case SET_REMOTE_VIEW_ADAPTER_LIST_TAG:
+ return new SetRemoteViewsAdapterList(parcel);
+ case TEXT_VIEW_DRAWABLE_COLOR_FILTER_ACTION_TAG:
+ return new TextViewDrawableColorFilterAction(parcel);
+ case SET_REMOTE_INPUTS_ACTION_TAG:
+ return new SetRemoteInputsAction(parcel);
+ case LAYOUT_PARAM_ACTION_TAG:
+ return new LayoutParamAction(parcel);
+ case OVERRIDE_TEXT_COLORS_TAG:
+ return new OverrideTextColorsAction(parcel);
+ default:
+ throw new ActionException("Tag " + tag + " not found");
+ }
+ };
+
/**
* Returns a deep copy of the RemoteViews object. The RemoteView may not be
* attached to another RemoteView -- it must be the root of a hierarchy.
*
+ * @deprecated use {@link #RemoteViews(RemoteViews)} instead.
* @throws IllegalStateException if this is not the root of a RemoteView
* hierarchy
*/
@Override
+ @Deprecated
public RemoteViews clone() {
- synchronized (this) {
- Preconditions.checkState(mIsRoot, "RemoteView has been attached to another RemoteView. "
- + "May only clone the root of a RemoteView hierarchy.");
-
- Parcel p = Parcel.obtain();
+ Preconditions.checkState(mIsRoot, "RemoteView has been attached to another RemoteView. "
+ + "May only clone the root of a RemoteView hierarchy.");
- // Do not parcel the Bitmap cache - doing so creates an expensive copy of all bitmaps.
- // Instead pretend we're not owning the cache while parceling.
- mIsRoot = false;
- writeToParcel(p, PARCELABLE_ELIDE_DUPLICATES);
- p.setDataPosition(0);
- mIsRoot = true;
-
- RemoteViews rv = new RemoteViews(p, mBitmapCache.clone(), mApplication, 0);
- rv.mIsRoot = true;
-
- p.recycle();
- return rv;
- }
+ return new RemoteViews(this);
}
public String getPackage() {
@@ -2575,30 +2499,6 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
- * Updates the memory usage statistics.
- */
- private void recalculateMemoryUsage() {
- mMemoryUsageCounter.clear();
-
- if (!hasLandscapeAndPortraitLayouts()) {
- // Accumulate the memory usage for each action
- if (mActions != null) {
- final int count = mActions.size();
- for (int i= 0; i < count; ++i) {
- mActions.get(i).updateMemoryUsageEstimate(mMemoryUsageCounter);
- }
- }
- if (mIsRoot) {
- mBitmapCache.addBitmapMemory(mMemoryUsageCounter);
- }
- } else {
- mMemoryUsageCounter.increment(mLandscape.estimateMemoryUsage());
- mMemoryUsageCounter.increment(mPortrait.estimateMemoryUsage());
- mBitmapCache.addBitmapMemory(mMemoryUsageCounter);
- }
- }
-
- /**
* Recursively sets BitmapCache in the hierarchy and update the bitmap ids.
*/
private void setBitmapCache(BitmapCache bitmapCache) {
@@ -2621,7 +2521,7 @@ public class RemoteViews implements Parcelable, Filter {
*/
/** @hide */
public int estimateMemoryUsage() {
- return mMemoryUsageCounter.getMemoryUsage();
+ return mBitmapCache.getBitmapMemory();
}
/**
@@ -2636,12 +2536,9 @@ public class RemoteViews implements Parcelable, Filter {
" portrait layouts individually before constructing the combined layout.");
}
if (mActions == null) {
- mActions = new ArrayList<Action>();
+ mActions = new ArrayList<>();
}
mActions.add(a);
-
- // update the memory usage stats
- a.updateMemoryUsageEstimate(mMemoryUsageCounter);
}
/**
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 041b515f7e47..8fe3fd0eaa73 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UiThread;
import android.annotation.WorkerThread;
-import android.content.Context;
import android.graphics.Canvas;
import android.graphics.PointF;
import android.graphics.RectF;
@@ -48,6 +47,7 @@ import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Supplier;
+import java.util.regex.Pattern;
/**
* Helper class for starting selection action mode
@@ -56,7 +56,7 @@ import java.util.function.Supplier;
*/
@UiThread
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-final class SelectionActionModeHelper {
+public final class SelectionActionModeHelper {
/**
* Maximum time (in milliseconds) to wait for a result before timing out.
@@ -85,8 +85,7 @@ final class SelectionActionModeHelper {
mTextClassificationHelper = new TextClassificationHelper(
mTextView.getTextClassifier(), mTextView.getText(),
0, 1, mTextView.getTextLocales());
- mSelectionTracker =
- new SelectionTracker(mTextView.getContext(), mTextView.isTextEditable());
+ mSelectionTracker = new SelectionTracker(mTextView);
if (SMART_SELECT_ANIMATION_ENABLED) {
mSmartSelectSprite = new SmartSelectSprite(mTextView.getContext(),
@@ -235,17 +234,6 @@ final class SelectionActionModeHelper {
final List<RectF> selectionRectangles =
convertSelectionToRectangles(layout, result.mStart, result.mEnd);
- /*
- * Do not run the Smart Select animation when there are multiple lines involved, as this
- * behavior is currently broken.
- *
- * TODO fix Smart Select Animation when the selection spans multiple lines
- */
- if (selectionRectangles.size() != 1) {
- onAnimationEndCallback.run();
- return;
- }
-
final PointF touchPoint = new PointF(
mEditor.getLastUpPositionX(),
mEditor.getLastUpPositionY());
@@ -262,17 +250,66 @@ final class SelectionActionModeHelper {
private List<RectF> convertSelectionToRectangles(final Layout layout, final int start,
final int end) {
final List<RectF> result = new ArrayList<>();
- // TODO filter out invalid rectangles
- // getSelection might give us overlapping and zero-dimension rectangles which will interfere
- // with the Smart Select animation
layout.getSelection(start, end, (left, top, right, bottom, textSelectionLayout) ->
- result.add(new RectF(left, top, right, bottom)));
+ mergeRectangleIntoList(result, new RectF(left, top, right, bottom)));
result.sort(SmartSelectSprite.RECTANGLE_COMPARATOR);
-
return result;
}
+ /**
+ * Merges a {@link RectF} into an existing list of rectangles. While merging, this method
+ * makes sure that:
+ *
+ * <ol>
+ * <li>No rectangle is redundant (contained within a bigger rectangle)</li>
+ * <li>Rectangles of the same height and vertical position that intersect get merged</li>
+ * </ol>
+ *
+ * @param list the list of rectangles to merge the new rectangle in
+ * @param candidate the {@link RectF} to merge into the list
+ * @hide
+ */
+ @VisibleForTesting
+ public static void mergeRectangleIntoList(List<RectF> list, RectF candidate) {
+ if (candidate.isEmpty()) {
+ return;
+ }
+
+ final int elementCount = list.size();
+ for (int index = 0; index < elementCount; ++index) {
+ final RectF existingRectangle = list.get(index);
+ if (existingRectangle.contains(candidate)) {
+ return;
+ }
+ if (candidate.contains(existingRectangle)) {
+ existingRectangle.setEmpty();
+ continue;
+ }
+
+ final boolean rectanglesContinueEachOther = candidate.left == existingRectangle.right
+ || candidate.right == existingRectangle.left;
+ final boolean canMerge = candidate.top == existingRectangle.top
+ && candidate.bottom == existingRectangle.bottom
+ && (RectF.intersects(candidate, existingRectangle)
+ || rectanglesContinueEachOther);
+
+ if (canMerge) {
+ candidate.union(existingRectangle);
+ existingRectangle.setEmpty();
+ }
+ }
+
+ for (int index = elementCount - 1; index >= 0; --index) {
+ if (list.get(index).isEmpty()) {
+ list.remove(index);
+ }
+ }
+
+ list.add(candidate);
+ }
+
+
/** @hide */
@VisibleForTesting
public static PointF movePointInsideNearestRectangle(final PointF point,
@@ -281,7 +318,9 @@ final class SelectionActionModeHelper {
float bestY = -1;
double bestDistance = Double.MAX_VALUE;
- for (final RectF rectangle : rectangles) {
+ final int elementCount = rectangles.size();
+ for (int index = 0; index < elementCount; ++index) {
+ final RectF rectangle = rectangles.get(index);
final float candidateY = rectangle.centerY();
final float candidateX;
@@ -337,7 +376,7 @@ final class SelectionActionModeHelper {
*/
private static final class SelectionTracker {
- private final Context mContext;
+ private final TextView mTextView;
private SelectionMetricsLogger mLogger;
private int mOriginalStart;
@@ -347,9 +386,9 @@ final class SelectionActionModeHelper {
private boolean mSelectionStarted;
private boolean mAllowReset;
- SelectionTracker(Context context, boolean editable) {
- mContext = Preconditions.checkNotNull(context);
- mLogger = new SelectionMetricsLogger(context, editable);
+ SelectionTracker(TextView textView) {
+ mTextView = Preconditions.checkNotNull(textView);
+ mLogger = new SelectionMetricsLogger(textView);
}
/**
@@ -361,7 +400,7 @@ final class SelectionActionModeHelper {
mOriginalEnd = selectionEnd;
mSelectionStarted = true;
mAllowReset = false;
- maybeInvalidateLogger(editableText);
+ maybeInvalidateLogger();
mLogger.logSelectionStarted(text, selectionStart);
}
@@ -438,9 +477,9 @@ final class SelectionActionModeHelper {
return false;
}
- private void maybeInvalidateLogger(boolean editableText) {
- if (mLogger.isEditTextLogger() != editableText) {
- mLogger = new SelectionMetricsLogger(mContext, editableText);
+ private void maybeInvalidateLogger() {
+ if (mLogger.isEditTextLogger() != mTextView.isTextEditable()) {
+ mLogger = new SelectionMetricsLogger(mTextView);
}
}
}
@@ -462,20 +501,22 @@ final class SelectionActionModeHelper {
private static final class SelectionMetricsLogger {
private static final String LOG_TAG = "SelectionMetricsLogger";
+ private static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\s+");
private final SmartSelectionEventTracker mDelegate;
private final boolean mEditTextLogger;
- private final BreakIterator mWordIterator = BreakIterator.getWordInstance();
+ private final BreakIterator mWordIterator;
private int mStartIndex;
- private int mEndIndex;
private String mText;
- SelectionMetricsLogger(Context context, boolean editable) {
- final @SmartSelectionEventTracker.WidgetType int widgetType = editable
+ SelectionMetricsLogger(TextView textView) {
+ Preconditions.checkNotNull(textView);
+ final @SmartSelectionEventTracker.WidgetType int widgetType = textView.isTextEditable()
? SmartSelectionEventTracker.WidgetType.EDITTEXT
: SmartSelectionEventTracker.WidgetType.TEXTVIEW;
- mDelegate = new SmartSelectionEventTracker(context, widgetType);
- mEditTextLogger = editable;
+ mDelegate = new SmartSelectionEventTracker(textView.getContext(), widgetType);
+ mEditTextLogger = textView.isTextEditable();
+ mWordIterator = BreakIterator.getWordInstance(textView.getTextLocale());
}
public void logSelectionStarted(CharSequence text, int index) {
@@ -487,7 +528,6 @@ final class SelectionActionModeHelper {
}
mWordIterator.setText(mText);
mStartIndex = index;
- mEndIndex = mWordIterator.following(index);
mDelegate.logEvent(SelectionEvent.selectionStarted(0));
} catch (Exception e) {
// Avoid crashes due to logging.
@@ -550,12 +590,15 @@ final class SelectionActionModeHelper {
} else if (start < mStartIndex) {
wordIndices[0] = -countWordsForward(start);
} else { // start > mStartIndex
- if (mStartIndex < start && start < mEndIndex) {
- // If the new selection did not move past the original word,
- // assume it has not moved.
- wordIndices[0] = 0;
- } else {
- wordIndices[0] = countWordsBackward(start);
+ wordIndices[0] = countWordsBackward(start);
+
+ // For the selection start index, avoid counting a partial word backwards.
+ if (!mWordIterator.isBoundary(start)
+ && !isWhitespace(
+ mWordIterator.preceding(start),
+ mWordIterator.following(start))) {
+ // We counted a partial word. Remove it.
+ wordIndices[0]--;
}
}
@@ -599,7 +642,7 @@ final class SelectionActionModeHelper {
}
private boolean isWhitespace(int start, int end) {
- return mText.substring(start, end).trim().isEmpty();
+ return PATTERN_WHITESPACE.matcher(mText.substring(start, end)).matches();
}
}
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 8de17c072b59..8696d0d5df7f 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -146,12 +146,17 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
// and relays them to the tab content.
mTabKeyListener = new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
+ if (KeyEvent.isModifierKey(keyCode)) {
+ return false;
+ }
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
+ case KeyEvent.KEYCODE_TAB:
+ case KeyEvent.KEYCODE_SPACE:
case KeyEvent.KEYCODE_ENTER:
return false;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 140ecc161057..3b9f7918ce55 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -10942,6 +10942,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
public boolean performLongClick() {
boolean handled = false;
+ boolean performedHapticFeedback = false;
if (mEditor != null) {
mEditor.mIsBeingLongClicked = true;
@@ -10949,6 +10950,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (super.performLongClick()) {
handled = true;
+ performedHapticFeedback = true;
}
if (mEditor != null) {
@@ -10957,7 +10959,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
if (handled) {
- performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ if (!performedHapticFeedback) {
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ }
if (mEditor != null) mEditor.mDiscardNextActionUp = true;
} else {
MetricsLogger.action(
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 5f1932c9cfff..b13560c10326 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2456,6 +2456,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
decor.setSystemUiVisibility(
decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
+ if (a.getBoolean(R.styleable.Window_windowLightNavigationBar, false)) {
+ decor.setSystemUiVisibility(
+ decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+ }
if (mAlwaysReadCloseOnTouchAttr || getContext().getApplicationInfo().targetSdkVersion
>= android.os.Build.VERSION_CODES.HONEYCOMB) {
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index f85333eb9588..b8ef82b8c1d9 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1614,7 +1614,8 @@ public class LockPatternUtils {
STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
SOME_AUTH_REQUIRED_AFTER_USER_REQUEST,
STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
- STRONG_AUTH_REQUIRED_AFTER_TIMEOUT})
+ STRONG_AUTH_REQUIRED_AFTER_TIMEOUT,
+ STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN})
@Retention(RetentionPolicy.SOURCE)
public @interface StrongAuthFlags {}
@@ -1651,6 +1652,11 @@ public class LockPatternUtils {
public static final int STRONG_AUTH_REQUIRED_AFTER_TIMEOUT = 0x10;
/**
+ * Strong authentication is required because the user has triggered lockdown.
+ */
+ public static final int STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN = 0x20;
+
+ /**
* Strong auth flags that do not prevent fingerprint from being accepted as auth.
*
* If any other flags are set, fingerprint is disabled.
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 592576bb41d0..e53162cc97fd 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -25,6 +25,7 @@ import android.hardware.input.InputManager;
import android.hardware.input.InputManager.InputDeviceListener;
import android.os.SystemProperties;
import android.util.Log;
+import android.util.Slog;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -630,6 +631,12 @@ public class PointerLocationView extends View implements InputDeviceListener,
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT; // will be 0 for UP
final int id = event.getPointerId(index);
+ if (id >= NP) {
+ Slog.wtf(TAG, "Got pointer ID out of bounds: id=" + id + " arraysize="
+ + NP + " pointerindex=" + index
+ + " action=0x" + Integer.toHexString(action));
+ return;
+ }
final PointerState ps = mPointers.get(id);
ps.mCurDown = false;
diff --git a/core/res/res/drawable/ic_close.xml b/core/res/res/drawable/ic_close.xml
index 708695994ab6..70565f296a1f 100644
--- a/core/res/res/drawable/ic_close.xml
+++ b/core/res/res/drawable/ic_close.xml
@@ -19,6 +19,6 @@ Copyright (C) 2016 The Android Open Source Project
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:pathData="M19.000000,6.400000l-1.400000,-1.400000 -5.600000,5.600000 -5.600000,-5.600000 -1.400000,1.400000 5.600000,5.600000 -5.600000,5.600000 1.400000,1.400000 5.600000,-5.600000 5.600000,5.600000 1.400000,-1.400000 -5.600000,-5.600000z"
+ android:pathData="M18.3,5.71a0.996,0.996 0,0 0,-1.41 0L12,10.59 7.11,5.7A0.996,0.996 0,1 0,5.7 7.11L10.59,12 5.7,16.89a0.996,0.996 0,1 0,1.41 1.41L12,13.41l4.89,4.89a0.996,0.996 0,1 0,1.41 -1.41L13.41,12l4.89,-4.89c0.38,-0.38 0.38,-1.02 0,-1.4z"
android:fillColor="#FF000000"/>
</vector>
diff --git a/core/res/res/drawable/ic_eject_24dp.xml b/core/res/res/drawable/ic_eject_24dp.xml
index 1bb351a57601..321ee3b6289c 100644
--- a/core/res/res/drawable/ic_eject_24dp.xml
+++ b/core/res/res/drawable/ic_eject_24dp.xml
@@ -20,5 +20,8 @@ Copyright (C) 2015 The Android Open Source Project
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
- android:pathData="M5 17h14v2H5zm7,-12L5.33 15h13.34z"/>
+ android:pathData="M6,17h12c0.55,0 1,0.45 1,1v0c0,0.55 -0.45,1 -1,1H6c-0.55,0 -1,-0.45 -1,-1v0C5,17.45 5.45,17 6,17z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M11.1,5.48l-5.22,7.83C5.39,14.03 5.91,15 6.78,15h10.44c0.87,0 1.39,-0.97 0.9,-1.69L12.9,5.48C12.47,4.84 11.53,4.84 11.1,5.48z"/>
</vector>
diff --git a/core/res/res/drawable/ic_feedback.xml b/core/res/res/drawable/ic_feedback.xml
index 365863da31e2..c316e7df5d4b 100644
--- a/core/res/res/drawable/ic_feedback.xml
+++ b/core/res/res/drawable/ic_feedback.xml
@@ -20,5 +20,5 @@ Copyright (C) 2016 The Android Open Source Project
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
- android:pathData="M20.0,2.0L4.0,2.0c-1.1,0.0 -1.9,0.9 -1.99,2.0L2.0,22.0l4.0,-4.0l14.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L22.0,4.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0zm-7.0,12.0l-2.0,0.0l0.0,-2.0l2.0,0.0l0.0,2.0zm0.0,-4.0l-2.0,0.0L11.0,6.0l2.0,0.0l0.0,4.0z"/>
+ android:pathData="M20,2H4C2.9,2 2,2.9 2,4v17.39c0,0.54 0.65,0.81 1.04,0.43L6.86,18H20c1.1,0 2,-0.9 2,-2V4C22,2.9 21.1,2 20,2zM11,7c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v3c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V7zM12,15.2c-0.61,0 -1.1,-0.49 -1.1,-1.1c0,-0.61 0.49,-1.1 1.1,-1.1c0.61,0 1.1,0.49 1.1,1.1C13.1,14.71 12.61,15.2 12,15.2z"/>
</vector>
diff --git a/core/res/res/drawable/ic_refresh.xml b/core/res/res/drawable/ic_refresh.xml
index 1297407fbb8b..5894f9526ec2 100644
--- a/core/res/res/drawable/ic_refresh.xml
+++ b/core/res/res/drawable/ic_refresh.xml
@@ -20,5 +20,5 @@ Copyright (C) 2016 The Android Open Source Project
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
- android:pathData="M17.65,6.35C16.2,4.9 14.21,4.0 12.0,4.0c-4.42,0.0 -7.99,3.58 -7.99,8.0s3.57,8.0 7.99,8.0c3.73,0.0 6.84,-2.55 7.73,-6.0l-2.08,0.0c-0.82,2.33 -3.04,4.0 -5.65,4.0 -3.31,0.0 -6.0,-2.69 -6.0,-6.0s2.69,-6.0 6.0,-6.0c1.66,0.0 3.1,0.69 4.22,1.78L13.0,11.0l7.0,0.0L20.0,4.0l-2.35,2.35z"/>
+ android:pathData="M17.65,6.35c-1.63,-1.63 -3.94,-2.57 -6.48,-2.31c-3.67,0.37 -6.69,3.35 -7.1,7.02C3.52,15.91 7.27,20 12,20c3.19,0 5.93,-1.87 7.21,-4.57c0.31,-0.66 -0.16,-1.43 -0.89,-1.43h-0.01c-0.37,0 -0.72,0.2 -0.88,0.53c-1.13,2.43 -3.84,3.97 -6.81,3.32c-2.22,-0.49 -4.01,-2.3 -4.49,-4.52C5.31,9.44 8.26,6 12,6c1.66,0 3.14,0.69 4.22,1.78l-2.37,2.37C13.54,10.46 13.76,11 14.21,11H19c0.55,0 1,-0.45 1,-1V5.21c0,-0.45 -0.54,-0.67 -0.85,-0.35L17.65,6.35z"/>
</vector>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c6bb52ecdeed..83bb443e1b72 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2367,12 +2367,14 @@
"silent" = silent mode
"users" = list of users
"restart" = restart device
+ "lockdown" = Lock down device until the user authenticates
-->
<string-array translatable="false" name="config_globalActionsList">
<item>power</item>
<item>restart</item>
<item>bugreport</item>
<item>users</item>
+ <item>lockdown</item>
</string-array>
<!-- Number of milliseconds to hold a wake lock to ensure that drawing is fully
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 9bd779e8cfb2..bd5b7116c435 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -526,8 +526,8 @@
<!-- label for item that launches voice assist in phone options dialog [CHAR LIMIT=15]-->
<string name="global_action_voice_assist">Voice Assist</string>
- <!-- label for item that locks the phone and enforces that it can't be unlocked without entering a credential. [CHAR LIMIT=15] -->
- <string name="global_action_lockdown">Lock now</string>
+ <!-- label for item that locks the phone and enforces that it can't be unlocked without strong authentication. [CHAR LIMIT=15] -->
+ <string name="global_action_lockdown">Enter lockdown</string>
<!-- Text to use when the number in a notification info is too large
(greater than status_bar_notification_info_maxnum, defined in
diff --git a/core/tests/coretests/src/android/util/TimingsTraceLogTest.java b/core/tests/coretests/src/android/util/TimingsTraceLogTest.java
new file mode 100644
index 000000000000..7bb4ab835e4f
--- /dev/null
+++ b/core/tests/coretests/src/android/util/TimingsTraceLogTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import static org.junit.Assert.assertTrue;
+
+import android.os.Trace;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Tests for {@link TimingsTraceLog}.
+ * <p>Usage: bit FrameworksCoreTests:android.util.TimingsTraceLogTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TimingsTraceLogTest {
+
+ @Test
+ public void testDifferentThreads() throws Exception {
+ TimingsTraceLog log = new TimingsTraceLog("TEST", Trace.TRACE_TAG_APP);
+ // Should be able to log on the same thread
+ log.traceBegin("test");
+ log.traceEnd();
+ final List<String> errors = new ArrayList<>();
+ // Calling from a different thread should fail
+ Thread t = new Thread(() -> {
+ try {
+ log.traceBegin("test");
+ errors.add("traceBegin should fail on a different thread");
+ } catch (IllegalStateException expected) {
+ }
+ try {
+ log.traceEnd();
+ errors.add("traceEnd should fail on a different thread");
+ } catch (IllegalStateException expected) {
+ }
+ // Verify that creating a new log will work
+ TimingsTraceLog log2 = new TimingsTraceLog("TEST", Trace.TRACE_TAG_APP);
+ log2.traceBegin("test");
+ log2.traceEnd();
+
+ });
+ t.start();
+ t.join();
+ assertTrue(errors.toString(), errors.isEmpty());
+ }
+
+}
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index bf994a97bdd1..d26437eafa07 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -16,6 +16,10 @@
package android.widget;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
@@ -36,10 +40,6 @@ import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
@@ -336,7 +336,9 @@ public class RemoteViewsTest {
parent.addView(R.id.layout, views);
views = parent;
}
+ // Both clone and parcel/unparcel work,
views.clone();
+ parcelAndRecreate(views);
views = new RemoteViews(mPackage, R.layout.remote_views_test);
for (int i = 0; i < 11; i++) {
@@ -344,8 +346,10 @@ public class RemoteViewsTest {
parent.addView(R.id.layout, views);
views = parent;
}
- exception.expect(IllegalArgumentException.class);
+ // Clone works but parcel/unparcel fails
views.clone();
+ exception.expect(IllegalArgumentException.class);
+ parcelAndRecreate(views);
}
@Test
@@ -355,15 +359,27 @@ public class RemoteViewsTest {
views = new RemoteViews(views,
new RemoteViews(mPackage, R.layout.remote_views_test));
}
+ // Both clone and parcel/unparcel work,
views.clone();
+ parcelAndRecreate(views);
views = new RemoteViews(mPackage, R.layout.remote_views_test);
for (int i = 0; i < 11; i++) {
- RemoteViews parent = new RemoteViews(mPackage, R.layout.remote_views_test);
- parent.addView(R.id.layout, views);
- views = parent;
+ views = new RemoteViews(views,
+ new RemoteViews(mPackage, R.layout.remote_views_test));
}
- exception.expect(IllegalArgumentException.class);
+ // Clone works but parcel/unparcel fails
views.clone();
+ exception.expect(IllegalArgumentException.class);
+ parcelAndRecreate(views);
+ }
+
+ private void parcelAndRecreate(RemoteViews views) {
+ Parcel p = Parcel.obtain();
+ views.writeToParcel(p, 0);
+ p.setDataPosition(0);
+
+ RemoteViews.CREATOR.createFromParcel(p);
+ p.recycle();
}
}
diff --git a/core/tests/coretests/src/android/widget/SelectionActionModeHelperTest.java b/core/tests/coretests/src/android/widget/SelectionActionModeHelperTest.java
index d94a017c27fd..b881053a5872 100644
--- a/core/tests/coretests/src/android/widget/SelectionActionModeHelperTest.java
+++ b/core/tests/coretests/src/android/widget/SelectionActionModeHelperTest.java
@@ -25,6 +25,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -110,4 +111,154 @@ public final class SelectionActionModeHelperTest {
assertEquals(expectedPointY, adjustedPoint.y, 0.0f);
}
+ @Test
+ public void testMergeRectangleIntoList_addThreeDisjointRectangles() {
+ testExpandRectangleList(
+ new RectF[] {
+ new RectF(0, 0, 1, 1),
+ new RectF(10, 10, 11, 11),
+ new RectF(20, 20, 21, 21)
+ },
+ new RectF[] {
+ new RectF(0, 0, 1, 1),
+ new RectF(10, 10, 11, 11),
+ new RectF(20, 20, 21, 21)
+ }
+ );
+ }
+
+ @Test
+ public void testMergeRectangleIntoList_addAnEmptyRectangle() {
+ testExpandRectangleList(
+ new RectF[] {
+ new RectF(0, 0, 0, 0)
+ },
+ new RectF[] {
+ }
+ );
+ }
+
+ @Test
+ public void testMergeRectangleIntoList_addAContainedRectangle() {
+ testExpandRectangleList(
+ new RectF[] {
+ new RectF(0, 0, 10, 10),
+ new RectF(9, 0, 10, 10)
+ },
+ new RectF[] {
+ new RectF(0, 0, 10, 10)
+ }
+ );
+ }
+
+ @Test
+ public void testMergeRectangleIntoList_addARectangleThatContainsExistingRectangles() {
+ testExpandRectangleList(
+ new RectF[] {
+ new RectF(0, 0, 1, 1),
+ new RectF(1, 0, 2, 1),
+ new RectF(0, 0, 2, 1)
+ },
+ new RectF[] {
+ new RectF(0, 0, 2, 1)
+ }
+ );
+ }
+
+ @Test
+ public void testMergeRectangleIntoList_addRectangleThatIntersectsAndHasTheSameHeightOnRight() {
+ testExpandRectangleList(
+ new RectF[] {
+ new RectF(0, 0, 1, 1),
+ new RectF(0.5f, 0, 1.5f, 1)
+ },
+ new RectF[] {
+ new RectF(0, 0, 1.5f, 1)
+ }
+ );
+ }
+
+ @Test
+ public void testMergeRectangleIntoList_addRectangleThatIntersectsAndHasTheSameHeightOnLeft() {
+ testExpandRectangleList(
+ new RectF[] {
+ new RectF(0.5f, 0, 1.5f, 1),
+ new RectF(0, 0, 1, 1)
+ },
+ new RectF[] {
+ new RectF(0, 0, 1.5f, 1)
+ }
+ );
+ }
+
+ @Test
+ public void testMergeRectangleIntoList_addRectangleThatExpandsToTheRight() {
+ testExpandRectangleList(
+ new RectF[] {
+ new RectF(0, 0, 1, 1),
+ new RectF(1, 0, 1.5f, 1)
+ },
+ new RectF[] {
+ new RectF(0, 0, 1.5f, 1)
+ }
+ );
+ }
+
+ @Test
+ public void testMergeRectangleIntoList_addRectangleThatExpandsToTheLeft() {
+ testExpandRectangleList(
+ new RectF[] {
+ new RectF(1, 0, 1.5f, 1),
+ new RectF(0, 0, 1, 1)
+ },
+ new RectF[] {
+ new RectF(0, 0, 1.5f, 1)
+ }
+ );
+ }
+
+
+ @Test
+ public void testMergeRectangleIntoList_addRectangleMadeObsoleteByMultipleExistingRectangles() {
+ testExpandRectangleList(
+ new RectF[] {
+ new RectF(0, 0, 1, 1),
+ new RectF(0.5f, 0, 1.5f, 1),
+ new RectF(0.25f, 0, 1.25f, 1)
+ },
+ new RectF[] {
+ new RectF(0, 0, 1.5f, 1)
+ }
+ );
+ }
+
+ @Test
+ public void testMergeRectangleIntoList_threeRectanglesThatTouchEachOther() {
+ testExpandRectangleList(
+ new RectF[] {
+ new RectF(0, 0, 1, 1),
+ new RectF(1, 0, 2, 1),
+ new RectF(2, 0, 3, 1)
+ },
+ new RectF[] {
+ new RectF(0, 0, 3, 1)
+ }
+ );
+ }
+
+
+ private void testExpandRectangleList(final RectF[] inputRectangles,
+ final RectF[] outputRectangles) {
+ final List<RectF> expectedOutput = Arrays.asList(outputRectangles);
+
+ final List<RectF> result = new ArrayList<>();
+ final int size = inputRectangles.length;
+ for (int index = 0; index < size; ++index) {
+ SelectionActionModeHelper.mergeRectangleIntoList(result, inputRectangles[index]);
+ }
+
+ assertEquals(expectedOutput, result);
+ }
+
+
}
diff --git a/data/keyboards/Vendor_054c_Product_09cc.kl b/data/keyboards/Vendor_054c_Product_09cc.kl
new file mode 100644
index 000000000000..f46573376ade
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_09cc.kl
@@ -0,0 +1,67 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Sony Playstation(R) DualShock 4 Controller
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x130 BUTTON_X
+# Cross
+key 0x131 BUTTON_A
+# Circle
+key 0x132 BUTTON_B
+# Triangle
+key 0x133 BUTTON_Y
+
+key 0x134 BUTTON_L1
+key 0x135 BUTTON_R1
+key 0x136 BUTTON_L2
+key 0x137 BUTTON_R2
+
+# L2 axis
+axis 0x03 LTRIGGER
+# R2 axis
+axis 0x04 RTRIGGER
+
+
+# Left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+# Right Analog Stick
+axis 0x02 Z
+axis 0x05 RZ
+
+# Left stick click
+key 0x13a BUTTON_THUMBL
+# Right stick click
+key 0x13b BUTTON_THUMBR
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x138 BUTTON_SELECT
+# Options
+key 0x139 BUTTON_START
+
+# PS key
+key 0x13c HOME
+# Touchpad press
+key 0x13d BUTTON_MODE
diff --git a/data/sounds/AudioPackageGo.mk b/data/sounds/AudioPackageGo.mk
index 3756d3056da9..ae742df8f9bb 100644
--- a/data/sounds/AudioPackageGo.mk
+++ b/data/sounds/AudioPackageGo.mk
@@ -40,3 +40,9 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/Alarm_Beep_03.ogg:system/media/audio/alarms/Alarm_Beep_03.ogg \
$(LOCAL_PATH)/alarms/ogg/Helium.ogg:system/media/audio/alarms/Helium.ogg \
$(LOCAL_PATH)/alarms/ogg/Oxygen.ogg:system/media/audio/alarms/Oxygen.ogg \
+ $(LOCAL_PATH)/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index ccf9de0abdb4..7e959a87da5d 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -754,6 +754,8 @@ public class KeyStore {
// None of the key's SIDs can ever be authenticated
return new KeyPermanentlyInvalidatedException();
}
+ case UNINITIALIZED:
+ return new KeyPermanentlyInvalidatedException();
default:
return new InvalidKeyException("Keystore operation failed", e);
}
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index aa6d2f3513d7..4a5b2c72b02a 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -162,8 +162,8 @@ public:
void addRenderNode(RenderNode* node, bool placeFront);
void removeRenderNode(RenderNode* node);
- void setContentDrawBounds(int left, int top, int right, int bottom) {
- mContentDrawBounds.set(left, top, right, bottom);
+ void setContentDrawBounds(const Rect& bounds) {
+ mContentDrawBounds = bounds;
}
RenderState& getRenderState() {
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 7d641d3ac7c7..a097272df359 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -32,6 +32,7 @@ namespace renderthread {
DrawFrameTask::DrawFrameTask()
: mRenderThread(nullptr)
, mContext(nullptr)
+ , mContentDrawBounds(0, 0, 0, 0)
, mSyncResult(SyncResult::OK) {
}
@@ -123,6 +124,7 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
mLayers[i]->apply();
}
mLayers.clear();
+ mContext->setContentDrawBounds(mContentDrawBounds);
mContext->prepareTree(info, mFrameInfo, mSyncQueued, mTargetNode);
// This is after the prepareTree so that any pending operations
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index fb480626d421..83ecb98f548f 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -61,6 +61,9 @@ public:
virtual ~DrawFrameTask();
void setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode);
+ void setContentDrawBounds(int left, int top, int right, int bottom) {
+ mContentDrawBounds.set(left, top, right, bottom);
+ }
void pushLayerUpdate(DeferredLayerUpdater* layer);
void removeLayerUpdate(DeferredLayerUpdater* layer);
@@ -82,6 +85,7 @@ private:
RenderThread* mRenderThread;
CanvasContext* mContext;
RenderNode* mTargetNode = nullptr;
+ Rect mContentDrawBounds;
/*********************************************
* Single frame data
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 690474376bef..a6aa301021e2 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -551,20 +551,8 @@ void RenderProxy::drawRenderNode(RenderNode* node) {
staticPostAndWait(task);
}
-CREATE_BRIDGE5(setContentDrawBounds, CanvasContext* context, int left, int top,
- int right, int bottom) {
- args->context->setContentDrawBounds(args->left, args->top, args->right, args->bottom);
- return nullptr;
-}
-
void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) {
- SETUP_TASK(setContentDrawBounds);
- args->context = mContext;
- args->left = left;
- args->top = top;
- args->right = right;
- args->bottom = bottom;
- staticPostAndWait(task);
+ mDrawFrameTask.setContentDrawBounds(left, top, right, bottom);
}
CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) {
diff --git a/packages/SystemUI/res/values-ldrtl/config.xml b/packages/SystemUI/res/values-ldrtl/config.xml
index 40604c16be9b..884c95f57f51 100644
--- a/packages/SystemUI/res/values-ldrtl/config.xml
+++ b/packages/SystemUI/res/values-ldrtl/config.xml
@@ -17,5 +17,5 @@
<resources>
<!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
when the PIP menu is shown with settings. -->
- <string translatable="false" name="pip_settings_bounds">"778 54 1258 324"</string>
+ <string translatable="false" name="pip_settings_bounds">"778 756 1258 1026"</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index c596398cf804..d95402cdb5dc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -50,6 +50,7 @@ import android.media.AudioManager;
import android.os.BatteryManager;
import android.os.CancellationSignal;
import android.os.Handler;
+import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.Message;
import android.os.RemoteException;
@@ -58,6 +59,8 @@ import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -67,8 +70,6 @@ import android.util.Log;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
-import com.google.android.collect.Lists;
-
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.PhoneConstants;
@@ -77,6 +78,8 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
+import com.google.android.collect.Lists;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -217,6 +220,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private UserManager mUserManager;
private int mFingerprintRunningState = FINGERPRINT_STATE_STOPPED;
private LockPatternUtils mLockPatternUtils;
+ private final IDreamManager mDreamManager;
+ private boolean mIsDreaming;
/**
* Short delay before restarting fingerprint authentication after a successful try
@@ -458,6 +463,26 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
updateFingerprintListeningState();
}
+ /**
+ * @return a cached version of DreamManager.isDreaming()
+ */
+ public boolean isDreaming() {
+ return mIsDreaming;
+ }
+
+ /**
+ * If the device is dreaming, awakens the device
+ */
+ public void awakenFromDream() {
+ if (mIsDreaming && mDreamManager != null) {
+ try {
+ mDreamManager.awaken();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to awaken from dream");
+ }
+ }
+ }
+
private void onFingerprintAuthenticated(int userId) {
Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
mUserFingerprintAuthenticated.put(userId, true);
@@ -1037,11 +1062,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private void handleDreamingStateChanged(int dreamStart) {
final int count = mCallbacks.size();
- boolean showingDream = dreamStart == 1;
+ mIsDreaming = dreamStart == 1;
for (int i = 0; i < count; i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
- cb.onDreamingStateChanged(showingDream);
+ cb.onDreamingStateChanged(mIsDreaming);
}
}
}
@@ -1146,6 +1171,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
mLockPatternUtils = new LockPatternUtils(context);
mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
+ mDreamManager = IDreamManager.Stub.asInterface(
+ ServiceManager.getService(DreamService.DREAM_SERVICE));
+
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
}
@@ -1183,7 +1211,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private boolean shouldListenForFingerprint() {
return (mKeyguardIsVisible || !mDeviceInteractive ||
(mBouncer && !mKeyguardGoingAway) || mGoingToSleep ||
- shouldListenForFingerprintAssistant())
+ shouldListenForFingerprintAssistant() || (mKeyguardOccluded && mIsDreaming))
&& !mSwitchingUser && !isFingerprintDisabled(getCurrentUser())
&& !mKeyguardGoingAway;
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 97a596242fbd..a9a915b23a0c 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -42,6 +42,7 @@ import com.android.systemui.power.PowerNotificationWarnings;
import com.android.systemui.power.PowerUI;
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
+import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -296,12 +297,13 @@ public class Dependency extends SystemUI {
mProviders.put(UiOffloadThread.class, UiOffloadThread::new);
-
mProviders.put(PowerUI.WarningsUI.class, () -> new PowerNotificationWarnings(mContext));
mProviders.put(IconLogger.class, () -> new IconLoggerImpl(mContext,
getDependency(BG_LOOPER), getDependency(MetricsLogger.class)));
+ mProviders.put(LightBarController.class, () -> new LightBarController(mContext));
+
// Put all dependencies above here so the factory can override them if it wants.
SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 33d5617c0397..4cbbbd6c2e90 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -14,6 +14,8 @@
package com.android.systemui.globalactions;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+
import com.android.internal.R;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.internal.colorextraction.ColorExtractor.GradientColors;
@@ -310,7 +312,10 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
} else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
mItems.add(getSettingsAction());
} else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {
- mItems.add(getLockdownAction());
+ if (Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0) {
+ mItems.add(getLockdownAction());
+ }
} else if (GLOBAL_ACTION_KEY_VOICEASSIST.equals(actionKey)) {
mItems.add(getVoiceAssistAction());
} else if (GLOBAL_ACTION_KEY_ASSIST.equals(actionKey)) {
@@ -575,7 +580,9 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
@Override
public void onPress() {
- new LockPatternUtils(mContext).requireCredentialEntry(UserHandle.USER_ALL);
+ new LockPatternUtils(mContext)
+ .requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN,
+ UserHandle.USER_ALL);
try {
WindowManagerGlobal.getWindowManagerService().lockNow(null);
} catch (RemoteException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 6c95a8013108..5a3081cd6664 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -18,6 +18,7 @@ package com.android.systemui.qs.customize;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
+import android.app.AlertDialog;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
@@ -35,6 +36,8 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
import android.widget.LinearLayout;
import android.widget.Toolbar;
import android.widget.Toolbar.OnMenuItemClickListener;
@@ -48,7 +51,9 @@ import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSContainerImpl;
import com.android.systemui.qs.QSDetailClipper;
import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback;
@@ -67,6 +72,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
private static final String EXTRA_QS_CUSTOMIZING = "qs_customizing";
private final QSDetailClipper mClipper;
+ private final LightBarController mLightBarController;
private boolean isShown;
private QSTileHost mHost;
@@ -80,6 +86,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
private int mX;
private int mY;
private boolean mOpening;
+ private boolean mIsShowingNavBackdrop;
public QSCustomizer(Context context, AttributeSet attrs) {
super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
@@ -114,6 +121,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
DefaultItemAnimator animator = new DefaultItemAnimator();
animator.setMoveDuration(TileAdapter.MOVE_DURATION);
mRecyclerView.setItemAnimator(animator);
+ mLightBarController = Dependency.get(LightBarController.class);
updateNavBackDrop(getResources().getConfiguration());
}
@@ -125,11 +133,16 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
private void updateNavBackDrop(Configuration newConfig) {
View navBackdrop = findViewById(R.id.nav_bar_background);
+ mIsShowingNavBackdrop = newConfig.smallestScreenWidthDp >= 600
+ || newConfig.orientation != Configuration.ORIENTATION_LANDSCAPE;
if (navBackdrop != null) {
- boolean shouldShow = newConfig.smallestScreenWidthDp >= 600
- || newConfig.orientation != Configuration.ORIENTATION_LANDSCAPE;
- navBackdrop.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
+ navBackdrop.setVisibility(mIsShowingNavBackdrop ? View.VISIBLE : View.GONE);
}
+ updateNavColors();
+ }
+
+ private void updateNavColors() {
+ mLightBarController.setQsCustomizing(mIsShowingNavBackdrop && isShown);
}
public void setHost(QSTileHost host) {
@@ -161,6 +174,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
announceForAccessibility(mContext.getString(
R.string.accessibility_desc_quick_settings_edit));
Dependency.get(KeyguardMonitor.class).addCallback(mKeyguardCallback);
+ updateNavColors();
}
}
@@ -176,6 +190,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
mNotifQsContainer.setCustomizerAnimating(false);
mNotifQsContainer.setCustomizerShowing(true);
Dependency.get(KeyguardMonitor.class).addCallback(mKeyguardCallback);
+ updateNavColors();
}
}
@@ -201,6 +216,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
announceForAccessibility(mContext.getString(
R.string.accessibility_desc_quick_settings));
Dependency.get(KeyguardMonitor.class).removeCallback(mKeyguardCallback);
+ updateNavColors();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 0bb74791d856..2e389ba151bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -112,6 +112,9 @@ public class CellularTile extends QSTileImpl<SignalState> {
@Override
protected void handleClick() {
+ if (getState().state == Tile.STATE_UNAVAILABLE) {
+ return;
+ }
if (mDataController.isMobileDataEnabled()) {
if (mKeyguardMonitor.isSecure() && !mKeyguardMonitor.canSkipBouncer()) {
mActivityStarter.postQSRunnableDismissingKeyguard(this::showDisableDialog);
@@ -190,7 +193,7 @@ public class CellularTile extends QSTileImpl<SignalState> {
}
if (cb.airplaneModeEnabled | cb.noSim) {
- state.state = Tile.STATE_INACTIVE;
+ state.state = Tile.STATE_UNAVAILABLE;
} else {
state.state = Tile.STATE_ACTIVE;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 184b95d56260..5557dde7a5d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -380,6 +380,15 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
}
+ @Override
+ public void setFakeShadowIntensity(float shadowIntensity, float outlineAlpha, int shadowYEnd,
+ int outlineTranslation) {
+ if (!mHasItemsInStableShelf) {
+ shadowIntensity = 0.0f;
+ }
+ super.setFakeShadowIntensity(shadowIntensity, outlineAlpha, shadowYEnd, outlineTranslation);
+ }
+
/**
* @return the icon amount how much this notification is in the shelf;
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 316d229e4f1a..00cb5329d2e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -85,6 +85,11 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback {
public static final int MODE_DISMISS_BOUNCER = 6;
/**
+ * Mode in which fingerprint wakes and unlocks the device from a dream.
+ */
+ public static final int MODE_WAKE_AND_UNLOCK_FROM_DREAM = 7;
+
+ /**
* How much faster we collapse the lockscreen when authenticating with fingerprint.
*/
private static final float FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
@@ -230,16 +235,19 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback {
}
Trace.endSection();
break;
+ case MODE_WAKE_AND_UNLOCK_FROM_DREAM:
case MODE_WAKE_AND_UNLOCK_PULSING:
case MODE_WAKE_AND_UNLOCK:
if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
mStatusBar.updateMediaMetaData(false /* metaDataChanged */,
true /* allowEnterAnimation */);
- } else {
+ } else if (mMode == MODE_WAKE_AND_UNLOCK){
Trace.beginSection("MODE_WAKE_AND_UNLOCK");
-
mDozeScrimController.abortDoze();
+ } else {
+ Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM");
+ mUpdateMonitor.awakenFromDream();
}
mStatusBarWindowManager.setStatusBarFocusable(false);
mKeyguardViewMediator.onWakeAndUnlocking();
@@ -299,6 +307,7 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback {
private int calculateMode() {
boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithFingerprintAllowed();
+ boolean deviceDreaming = mUpdateMonitor.isDreaming();
if (!mUpdateMonitor.isDeviceInteractive()) {
if (!mStatusBarKeyguardViewManager.isShowing()) {
@@ -311,6 +320,9 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback {
return MODE_SHOW_BOUNCER;
}
}
+ if (unlockingAllowed && deviceDreaming) {
+ return MODE_WAKE_AND_UNLOCK_FROM_DREAM;
+ }
if (mStatusBarKeyguardViewManager.isShowing()) {
if (mStatusBarKeyguardViewManager.isBouncerShowing() && unlockingAllowed) {
return MODE_DISMISS_BOUNCER;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index fd95cc4adc1d..165ed78996b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -27,6 +27,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.WindowInsets;
import android.view.accessibility.AccessibilityEvent;
import com.android.internal.widget.LockPatternUtils;
@@ -247,12 +248,16 @@ public class KeyguardBouncer {
removeView();
mHandler.removeCallbacks(mRemoveViewRunnable);
mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
- mKeyguardView = (KeyguardHostView) mRoot.findViewById(R.id.keyguard_host_view);
+ mKeyguardView = mRoot.findViewById(R.id.keyguard_host_view);
mKeyguardView.setLockPatternUtils(mLockPatternUtils);
mKeyguardView.setViewMediatorCallback(mCallback);
mContainer.addView(mRoot, mContainer.getChildCount());
mRoot.setVisibility(View.INVISIBLE);
- mRoot.dispatchApplyWindowInsets(mRoot.getRootWindowInsets());
+
+ final WindowInsets rootInsets = mRoot.getRootWindowInsets();
+ if (rootInsets != null) {
+ mRoot.dispatchApplyWindowInsets(rootInsets);
+ }
}
protected void removeView() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 917a56fbc99d..533771a31d0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -72,6 +72,7 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
private final Rect mLastFullscreenBounds = new Rect();
private final Rect mLastDockedBounds = new Rect();
+ private boolean mQsCustomizing;
public LightBarController(Context ctx) {
mDarkModeColor = Color.valueOf(ctx.getColor(R.color.dark_mode_icon_color_single_tone));
@@ -129,7 +130,8 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
mHasLightNavigationBar = isLight(vis, navigationBarMode,
View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
mNavigationLight = mHasLightNavigationBar
- && (mScrimAlphaBelowThreshold || !mInvertLightNavBarWithScrim);
+ && (mScrimAlphaBelowThreshold || !mInvertLightNavBarWithScrim)
+ && !mQsCustomizing;
if (mNavigationLight != last) {
updateNavigation();
}
@@ -146,6 +148,12 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
mLastNavigationBarMode);
}
+ public void setQsCustomizing(boolean customizing) {
+ if (mQsCustomizing == customizing) return;
+ mQsCustomizing = customizing;
+ reevaluate();
+ }
+
public void setScrimAlpha(float alpha) {
mScrimAlpha = alpha;
boolean belowThresholdBefore = mScrimAlphaBelowThreshold;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 7a10985fc60c..00ba1f293b8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1125,7 +1125,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
});
- mLightBarController = new LightBarController(context);
+ mLightBarController = Dependency.get(LightBarController.class);
if (mNavigationBar != null) {
mNavigationBar.setLightBarController(mLightBarController);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index 1411a544c346..f9c2130e4e81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -159,6 +159,11 @@ public class UnlockMethodCache {
public void onScreenTurnedOff() {
update(false /* updateAlways */);
}
+
+ @Override
+ public void onKeyguardVisibilityChanged(boolean showing) {
+ update(false /* updateAlways */);
+ }
};
public boolean isTrustManaged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 34a03bf36c47..652f8bb646d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -182,6 +182,7 @@ public class MobileSignalController extends SignalController<
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G);
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G);
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_TD_SCDMA, TelephonyIcons.THREE_G);
if (!mConfig.showAtLeast3G) {
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 4e592dbed322..75532d9e09be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -23,14 +23,12 @@ import android.animation.PropertyValuesHolder;
import android.animation.TimeAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.annotation.ColorInt;
import android.annotation.FloatRange;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.PorterDuff;
@@ -1083,6 +1081,20 @@ public class NotificationStackScrollLayout extends ViewGroup
@Override
public ExpandableView getChildAtPosition(float touchX, float touchY) {
+ return getChildAtPosition(touchX, touchY, true /* requireMinHeight */);
+
+ }
+
+ /**
+ * Get the child at a certain screen location.
+ *
+ * @param touchX the x coordinate
+ * @param touchY the y coordinate
+ * @param requireMinHeight Whether a minimum height is required for a child to be returned.
+ * @return the child at the given location.
+ */
+ private ExpandableView getChildAtPosition(float touchX, float touchY,
+ boolean requireMinHeight) {
// find the view under the pointer, accounting for GONE views
final int count = getChildCount();
for (int childIdx = 0; childIdx < count; childIdx++) {
@@ -1101,7 +1113,7 @@ public class NotificationStackScrollLayout extends ViewGroup
int left = 0;
int right = getWidth();
- if (bottom - top >= mMinInteractionHeight
+ if ((bottom - top >= mMinInteractionHeight || !requireMinHeight)
&& touchY >= top && touchY <= bottom && touchX >= left && touchX <= right) {
if (slidingChild instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) slidingChild;
@@ -3220,7 +3232,7 @@ public class NotificationStackScrollLayout extends ViewGroup
case MotionEvent.ACTION_DOWN: {
final int y = (int) ev.getY();
mScrolledToTopOnFirstDown = isScrolledToTop();
- if (getChildAtPosition(ev.getX(), y) == null) {
+ if (getChildAtPosition(ev.getX(), y, false /* requireMinHeight */) == null) {
setIsBeingDragged(false);
recycleVelocityTracker();
break;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 66d00dd6c5c6..65d969932ef5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -54,6 +54,7 @@ public abstract class SysuiTestCase {
@Before
public void SysuiSetup() throws Exception {
System.setProperty("dexmaker.share_classloader", "true");
+ mContext.setTheme(R.style.Theme_SystemUI);
SystemUIFactory.createFromConfig(mContext);
mRealInstrumentation = InstrumentationRegistry.getInstrumentation();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
new file mode 100644
index 000000000000..40512205a8f8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static org.mockito.Mockito.mock;
+
+import android.content.Context;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.UiThreadTest;
+import android.view.ContextThemeWrapper;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.keyguard.DismissCallbackRegistry;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class KeyguardBouncerTest extends SysuiTestCase {
+
+ @UiThreadTest
+ @Test
+ public void inflateDetached() {
+ final ViewGroup container = new FrameLayout(getContext());
+ final KeyguardBouncer bouncer = new KeyguardBouncer(getContext(),
+ mock(ViewMediatorCallback.class), mock(LockPatternUtils.class), container, mock(
+ DismissCallbackRegistry.class));
+
+ // Detached bouncer should still be able to be inflated
+ bouncer.inflateView();
+ }
+
+}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f1ea85374db3..e70a294d4684 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4649,7 +4649,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Ignore updates for disconnected networks
return;
}
-
+ // newLp is already a defensive copy.
+ newLp.ensureDirectlyConnectedRoutes();
if (VDBG) {
log("Update of LinkProperties for " + nai.name() +
"; created=" + nai.created +
@@ -4659,8 +4660,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
synchronized (nai) {
nai.linkProperties = newLp;
}
- // msg.obj is already a defensive copy.
- nai.linkProperties.ensureDirectlyConnectedRoutes();
if (nai.everConnected) {
updateLinkProperties(nai, oldLp);
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 966e553a6396..340d672df21c 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1542,18 +1542,7 @@ public class LocationManagerService extends ILocationManager.Stub {
*/
@Override
public List<String> getAllProviders() {
- ArrayList<String> out;
- synchronized (mLock) {
- out = new ArrayList<>(mProviders.size());
- for (LocationProviderInterface provider : mProviders) {
- String name = provider.getName();
- if (LocationManager.FUSED_PROVIDER.equals(name)) {
- continue;
- }
- out.add(name);
- }
- }
-
+ List<String> out = getProviders(null /*criteria*/, false /*enabledOnly*/);
if (D) Log.d(TAG, "getAllProviders()=" + out);
return out;
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 5d40c59c8bbd..88357bbd0029 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1223,7 +1223,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Still waiting for something to pause; can't sleep yet.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still waiting to pause " + mPausingActivity);
shouldSleep = false;
- } else if (mLastPausedActivity == topActivity()) {
+ } else if (topActivity() != null && topActivity().state == ActivityState.PAUSED) {
// Our top activity is currently paused, we need to ensure we move it to the stopped
// state.
stopActivityLocked(mLastPausedActivity);
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
index 553fd8c453a0..76195c4ac7d4 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
@@ -109,6 +109,10 @@ public class OffloadHardwareInterface {
mLog.e("tethering offload control not supported: " + e);
return false;
}
+ if (mOffloadControl == null) {
+ mLog.e("tethering IOffloadControl.getService() returned null");
+ return false;
+ }
}
final String logmsg = String.format("initOffloadControl(%s)",
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index c3957f432f4c..db6e9749535b 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -169,9 +169,8 @@ final class OverlayManagerServiceImpl {
}
final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
- if (updateAllOverlaysForTarget(packageName, userId, targetPackage)) {
- mListener.onOverlaysChanged(packageName, userId);
- }
+ updateAllOverlaysForTarget(packageName, userId, targetPackage);
+ mListener.onOverlaysChanged(packageName, userId);
}
void onTargetPackageChanged(@NonNull final String packageName, final int userId) {
@@ -211,9 +210,7 @@ final class OverlayManagerServiceImpl {
Slog.d(TAG, "onTargetPackageRemoved packageName=" + packageName + " userId=" + userId);
}
- if (updateAllOverlaysForTarget(packageName, userId, null)) {
- mListener.onOverlaysChanged(packageName, userId);
- }
+ updateAllOverlaysForTarget(packageName, userId, null);
}
/**
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index da6e26e17122..6253857d1aa4 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -53,7 +53,8 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
private final static boolean DEBUG_DEXOPT = true;
// The synthetic library dependencies denoting "no checks."
- private final static String[] NO_LIBRARIES = new String[] { "&" };
+ private final static String[] NO_LIBRARIES =
+ new String[] { PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK };
// The amount of "available" (free - low threshold) space necessary at the start of an OTA to
// not bulk-delete unused apps' odex files.
@@ -322,11 +323,6 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
new DexoptOptions(pkg.packageName, compilationReason,
DexoptOptions.DEXOPT_BOOT_COMPLETE));
- mPackageManagerService.getDexManager().dexoptSecondaryDex(
- new DexoptOptions(pkg.packageName, compilationReason,
- DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX |
- DexoptOptions.DEXOPT_BOOT_COMPLETE));
-
return commands;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 950fdd7e71fe..65678fc92798 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2711,8 +2711,14 @@ public class PackageManagerService extends IPackageManager.Stub
// Actual deletion of code and data will be handled by later
// reconciliation step
} else {
- final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
- if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
+ // we still have a disabled system package, but, it still might have
+ // been removed. check the code path still exists and check there's
+ // still a package. the latter can happen if an OTA keeps the same
+ // code path, but, changes the package name.
+ final PackageSetting disabledPs =
+ mSettings.getDisabledSystemPkgLPr(ps.name);
+ if (disabledPs.codePath == null || !disabledPs.codePath.exists()
+ || disabledPs.pkg == null) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
}
}
@@ -11398,6 +11404,10 @@ public class PackageManagerService extends IPackageManager.Stub
+ " but expected at " + known.codePathString
+ "; ignoring.");
}
+ } else {
+ throw new PackageManagerException(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
+ "Application package " + pkg.packageName
+ + " not found; ignoring.");
}
}
}
diff --git a/services/core/java/com/android/server/pm/dex/DexoptUtils.java b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
index ef2ee4a41555..e1310a2f1ab3 100644
--- a/services/core/java/com/android/server/pm/dex/DexoptUtils.java
+++ b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
@@ -21,6 +21,7 @@ import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.os.ClassLoaderFactory;
+import com.android.server.pm.PackageDexOptimizer;
import java.io.File;
import java.util.ArrayList;
@@ -238,10 +239,15 @@ public final class DexoptUtils {
/**
* Encodes a single class loader dependency starting from {@param path} and
* {@param classLoaderName}.
+ * When classpath is {@link PackageDexOptimizer#SKIP_SHARED_LIBRARY_CHECK}, the method returns
+ * the same. This special property is used only during OTA.
* NOTE: Keep this in sync with the dexopt expectations! Right now that is either "PCL[path]"
* for a PathClassLoader or "DLC[path]" for a DelegateLastClassLoader.
*/
- private static String encodeClassLoader(String classpath, String classLoaderName) {
+ /*package*/ static String encodeClassLoader(String classpath, String classLoaderName) {
+ if (classpath.equals(PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK)) {
+ return classpath;
+ }
String classLoaderDexoptEncoding = classLoaderName;
if (ClassLoaderFactory.isPathClassLoaderName(classLoaderName)) {
classLoaderDexoptEncoding = "PCL";
@@ -255,10 +261,17 @@ public final class DexoptUtils {
/**
* Links to dependencies together in a format accepted by dexopt.
+ * For the special case when either of cl1 or cl2 equals
+ * {@link PackageDexOptimizer#SKIP_SHARED_LIBRARY_CHECK}, the method returns the same. This
+ * property is used only during OTA.
* NOTE: Keep this in sync with the dexopt expectations! Right now that is a list of split
* dependencies {@see encodeClassLoader} separated by ';'.
*/
- private static String encodeClassLoaderChain(String cl1, String cl2) {
+ /*package*/ static String encodeClassLoaderChain(String cl1, String cl2) {
+ if (cl1.equals(PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK) ||
+ cl2.equals(PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK)) {
+ return PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK;
+ }
if (cl1.isEmpty()) return cl2;
if (cl2.isEmpty()) return cl1;
return cl1 + ";" + cl2;
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdater.java b/services/core/java/com/android/server/webkit/WebViewUpdater.java
index 203bbf61dc51..7fc907f95c93 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdater.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdater.java
@@ -569,6 +569,7 @@ class WebViewUpdater {
PackageInfo systemUserPackageInfo =
userPackages.get(UserHandle.USER_SYSTEM).getPackageInfo();
if (systemUserPackageInfo == null) {
+ pw.println(String.format(" %s is NOT installed.", provider.packageName));
continue;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index d74e48253132..f0b9f1794019 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1915,9 +1915,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
super.removeImmediately();
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
mDimLayerController.close();
- if (mDisplayId == DEFAULT_DISPLAY && mService.canDispatchPointerEvents()) {
- mService.unregisterPointerEventListener(mTapDetector);
- mService.unregisterPointerEventListener(mService.mMousePositionTracker);
+ if (mService.canDispatchPointerEvents()) {
+ if (mTapDetector != null) {
+ mService.unregisterPointerEventListener(mTapDetector);
+ }
+ if (mDisplayId == DEFAULT_DISPLAY && mService.mMousePositionTracker != null) {
+ mService.unregisterPointerEventListener(mService.mMousePositionTracker);
+ }
}
} finally {
mRemovingDisplay = false;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 54dd19961999..8a749762f993 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -249,13 +249,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
// Tap Listeners are supported for:
// 1. All physical displays (multi-display).
- // 2. VirtualDisplays that support virtual touch input. (Only VR for now)
- // TODO(multi-display): Support VirtualDisplays with no virtual touch input.
- if ((display.getType() != Display.TYPE_VIRTUAL
- || (display.getType() == Display.TYPE_VIRTUAL
- // Only VR VirtualDisplays
- && displayId == mService.mVr2dDisplayId))
- && mService.canDispatchPointerEvents()) {
+ // 2. VirtualDisplays on VR, AA (and everything else).
+ if (mService.canDispatchPointerEvents()) {
if (DEBUG_DISPLAY) {
Slog.d(TAG,
"Registering PointerEventListener for DisplayId: " + displayId);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e8e40a78554c..1b055664093f 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1475,7 +1475,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// TODO: Another visibility method that was added late in the release to minimize risk.
@Override
public boolean canAffectSystemUiFlags() {
- final boolean shown = mWinAnimator.getShown() && mWinAnimator.mShownAlpha > 0f;
+ final boolean shown = mWinAnimator.getShown();
// We only consider the app to be exiting when the animation has started. After the app
// transition is executed the windows are marked exiting before the new windows have been
@@ -1489,7 +1489,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
final boolean exiting = exitingSelf || mDestroying || appExiting;
final boolean translucent = mAttrs.alpha == 0.0f;
- return shown && !exiting && !translucent;
+
+ // If we are entering with a dummy animation, avoid affecting SystemUI flags until the
+ // transition is starting.
+ final boolean enteringWithDummyAnimation =
+ mWinAnimator.isDummyAnimation() && mWinAnimator.mShownAlpha == 0f;
+ return shown && !exiting && !translucent && !enteringWithDummyAnimation;
}
/**
diff --git a/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp b/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
index f9cbd1601290..9a17635721b8 100644
--- a/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
+++ b/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
@@ -113,7 +113,7 @@ static jboolean android_server_connectivity_tethering_OffloadHardwareInterface_c
hidl_handle h1(handleFromFileDescriptor(std::move(fd1))),
h2(handleFromFileDescriptor(std::move(fd2)));
- bool rval;
+ bool rval(false);
hidl_string msg;
const auto status = configInterface->setHandles(h1, h2,
[&rval, &msg](bool success, const hidl_string& errMsg) {
@@ -123,6 +123,8 @@ static jboolean android_server_connectivity_tethering_OffloadHardwareInterface_c
if (!status.isOk() || !rval) {
ALOGE("IOffloadConfig::setHandles() error: '%s' / '%s'",
status.description().c_str(), msg.c_str());
+ // If status is somehow not ok, make sure rval captures this too.
+ rval = false;
}
return rval;
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
index c8c8eb1aa5c6..150f7f0c948c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
@@ -16,10 +16,14 @@
package com.android.server.pm.dex;
+import com.android.server.pm.PackageDexOptimizer;
+
+import static com.android.server.pm.PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.content.pm.ApplicationInfo;
import android.support.test.filters.SmallTest;
@@ -369,4 +373,49 @@ public class DexoptUtilsTest {
}
assertTrue(gotException);
}
+
+ @Test
+ public void testEncodeClassLoader() {
+ assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoader(
+ SKIP_SHARED_LIBRARY_CHECK, "dalvik.system.PathClassLoader"));
+ assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoader(
+ SKIP_SHARED_LIBRARY_CHECK, "dalvik.system.DexClassLoader"));
+ assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoader(
+ SKIP_SHARED_LIBRARY_CHECK, "dalvik.system.DelegateLastClassLoader"));
+ assertEquals("PCL[xyz]", DexoptUtils.encodeClassLoader("xyz",
+ "dalvik.system.PathClassLoader"));
+ assertEquals("PCL[xyz]", DexoptUtils.encodeClassLoader("xyz",
+ "dalvik.system.DexClassLoader"));
+ assertEquals("DLC[xyz]", DexoptUtils.encodeClassLoader("xyz",
+ "dalvik.system.DelegateLastClassLoader"));
+ assertEquals("PCL[xyz]", DexoptUtils.encodeClassLoader("xyz", null));
+ assertEquals("abc[xyz]", DexoptUtils.encodeClassLoader("xyz", "abc"));
+
+ try {
+ DexoptUtils.encodeClassLoader(null, "abc");
+ fail(); // Exception should be caught.
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void testEncodeClassLoaderChain() {
+ assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoaderChain(
+ SKIP_SHARED_LIBRARY_CHECK, "PCL[a]"));
+ assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoaderChain("PCL[a]",
+ SKIP_SHARED_LIBRARY_CHECK));
+ assertEquals("PCL[a];DLC[b]", DexoptUtils.encodeClassLoaderChain("PCL[a]",
+ "DLC[b]"));
+ assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoaderChain("PCL[a]",
+ SKIP_SHARED_LIBRARY_CHECK));
+
+ try {
+ DexoptUtils.encodeClassLoaderChain("a", null);
+ fail(); // exception is expected
+ } catch (NullPointerException expected) {}
+
+ try {
+ DexoptUtils.encodeClassLoaderChain(null, "b");
+ fail(); // exception is expected
+ } catch (NullPointerException expected) {}
+ }
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 8680b11522be..719de12a7633 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1678,6 +1678,10 @@ public class TelephonyManager {
}
}
+ /*
+ * When adding a network type to the list below, make sure to add the correct icon to
+ * MobileSignalController.mapIconSets().
+ */
/** Network type is unknown */
public static final int NETWORK_TYPE_UNKNOWN = 0;
/** Current network is GPRS */
@@ -6832,7 +6836,6 @@ public class TelephonyManager {
* Get the most recent SignalStrength information reported by the modem. Due
* to power saving this information may not always be current.
* @return the most recent cached signal strength info from the modem
- * @hide
*/
@Nullable
public SignalStrength getSignalStrength() {
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index 19de3afb9d62..32ec7bc60c78 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -236,16 +236,22 @@ static void CopyAttributes(Element* el, android::ResXMLParser* parser, StringPoo
attr.name = util::Utf16ToUtf8(StringPiece16(str16, len));
}
+ uint32_t res_id = parser->getAttributeNameResID(i);
+ if (res_id > 0) {
+ attr.compiled_attribute = AaptAttribute(::aapt::Attribute(), {res_id});
+ }
+
str16 = parser->getAttributeStringValue(i, &len);
if (str16) {
attr.value = util::Utf16ToUtf8(StringPiece16(str16, len));
+ } else {
+ android::Res_value res_value;
+ if (parser->getAttributeValue(i, &res_value) > 0) {
+ attr.compiled_value = ResourceUtils::ParseBinaryResValue(
+ ResourceType::kAnim, {}, parser->getStrings(), res_value, out_pool);
+ }
}
- android::Res_value res_value;
- if (parser->getAttributeValue(i, &res_value) > 0) {
- attr.compiled_value = ResourceUtils::ParseBinaryResValue(
- ResourceType::kAnim, {}, parser->getStrings(), res_value, out_pool);
- }
el->attributes.push_back(std::move(attr));
}