diff options
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)); } |