Merge "Ensure that the thumbnail path is valid even without a thumbnail." into oc-mr1-dev
diff --git a/api/current.txt b/api/current.txt
index 4961312..25e998c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -919,6 +919,7 @@
field public static final int multiprocess = 16842771; // 0x1010013
field public static final int name = 16842755; // 0x1010003
field public static final int navigationBarColor = 16843858; // 0x1010452
+ field public static final int navigationBarDividerColor = 16844141; // 0x101056d
field public static final int navigationContentDescription = 16843969; // 0x10104c1
field public static final int navigationIcon = 16843968; // 0x10104c0
field public static final int navigationMode = 16843471; // 0x10102cf
@@ -1524,6 +1525,7 @@
field public static final int windowHideAnimation = 16842935; // 0x10100b7
field public static final int windowIsFloating = 16842839; // 0x1010057
field public static final int windowIsTranslucent = 16842840; // 0x1010058
+ field public static final int windowLightNavigationBar = 16844140; // 0x101056c
field public static final int windowLightStatusBar = 16844000; // 0x10104e0
field public static final int windowMinWidthMajor = 16843606; // 0x1010356
field public static final int windowMinWidthMinor = 16843607; // 0x1010357
diff --git a/api/system-current.txt b/api/system-current.txt
index e867245..f5015f8 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1049,6 +1049,7 @@
field public static final int multiprocess = 16842771; // 0x1010013
field public static final int name = 16842755; // 0x1010003
field public static final int navigationBarColor = 16843858; // 0x1010452
+ field public static final int navigationBarDividerColor = 16844141; // 0x101056d
field public static final int navigationContentDescription = 16843969; // 0x10104c1
field public static final int navigationIcon = 16843968; // 0x10104c0
field public static final int navigationMode = 16843471; // 0x10102cf
@@ -1660,6 +1661,7 @@
field public static final int windowHideAnimation = 16842935; // 0x10100b7
field public static final int windowIsFloating = 16842839; // 0x1010057
field public static final int windowIsTranslucent = 16842840; // 0x1010058
+ field public static final int windowLightNavigationBar = 16844140; // 0x101056c
field public static final int windowLightStatusBar = 16844000; // 0x10104e0
field public static final int windowMinWidthMajor = 16843606; // 0x1010356
field public static final int windowMinWidthMinor = 16843607; // 0x1010357
diff --git a/api/test-current.txt b/api/test-current.txt
index 9487740..bbaf021 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -919,6 +919,7 @@
field public static final int multiprocess = 16842771; // 0x1010013
field public static final int name = 16842755; // 0x1010003
field public static final int navigationBarColor = 16843858; // 0x1010452
+ field public static final int navigationBarDividerColor = 16844141; // 0x101056d
field public static final int navigationContentDescription = 16843969; // 0x10104c1
field public static final int navigationIcon = 16843968; // 0x10104c0
field public static final int navigationMode = 16843471; // 0x10102cf
@@ -1524,6 +1525,7 @@
field public static final int windowHideAnimation = 16842935; // 0x10100b7
field public static final int windowIsFloating = 16842839; // 0x1010057
field public static final int windowIsTranslucent = 16842840; // 0x1010058
+ field public static final int windowLightNavigationBar = 16844140; // 0x101056c
field public static final int windowLightStatusBar = 16844000; // 0x10104e0
field public static final int windowMinWidthMajor = 16843606; // 0x1010356
field public static final int windowMinWidthMinor = 16843607; // 0x1010357
diff --git a/config/preloaded-classes b/config/preloaded-classes
index ff61d18..479cda4 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -2192,6 +2192,7 @@
android.util.Log
android.util.Log$1
android.util.Log$ImmediateLogWriter
+android.util.Log$PreloadHolder
android.util.Log$TerribleFailureHandler
android.util.LogPrinter
android.util.LongArray
diff --git a/config/preloaded-classes-extra b/config/preloaded-classes-extra
index 959fff5..09f393a 100644
--- a/config/preloaded-classes-extra
+++ b/config/preloaded-classes-extra
@@ -8,6 +8,7 @@
android.media.SoundPool
android.text.format.Formatter
android.text.Html$HtmlParser
+android.util.Log$PreloadHolder
com.android.org.conscrypt.TrustedCertificateStore
org.ccil.cowan.tagsoup.HTMLScanner
sun.security.jca.Providers
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 00d6657..1a2dc5c 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -843,7 +843,7 @@
// Assumes forward playing from here on.
for (int i = 0; i < mEvents.size(); i++) {
AnimationEvent event = mEvents.get(i);
- if (event.getTime() > currentPlayTime) {
+ if (event.getTime() > currentPlayTime || event.getTime() == DURATION_INFINITE) {
break;
}
@@ -1264,7 +1264,8 @@
} else {
for (int i = mLastEventId + 1; i < size; i++) {
AnimationEvent event = mEvents.get(i);
- if (event.getTime() <= currentPlayTime) {
+ // TODO: need a function that accounts for infinite duration to compare time
+ if (event.getTime() != DURATION_INFINITE && event.getTime() <= currentPlayTime) {
latestId = i;
}
}
diff --git a/core/java/android/app/SharedElementCallback.java b/core/java/android/app/SharedElementCallback.java
index af13e69..0d14a8d 100644
--- a/core/java/android/app/SharedElementCallback.java
+++ b/core/java/android/app/SharedElementCallback.java
@@ -176,7 +176,7 @@
Drawable d = imageView.getDrawable();
Drawable bg = imageView.getBackground();
if (d != null && (bg == null || bg.getAlpha() == 0)) {
- Bitmap bitmap = TransitionUtils.createDrawableBitmap(d);
+ Bitmap bitmap = TransitionUtils.createDrawableBitmap(d, imageView);
if (bitmap != null) {
Bundle bundle = new Bundle();
if (bitmap.getConfig() != Bitmap.Config.HARDWARE) {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 744ee8e..d7ecc81 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2078,16 +2078,30 @@
* {@code ro.tether.denied} system property, Settings.TETHER_SUPPORTED or
* due to device configuration.
*
+ * <p>If this app does not have permission to use this API, it will always
+ * return false rather than throw an exception.</p>
+ *
+ * <p>If the device has a hotspot provisioning app, the caller is required to hold the
+ * {@link android.Manifest.permission.TETHER_PRIVILEGED} permission.</p>
+ *
+ * <p>Otherwise, this method requires the caller to hold the ability to modify system
+ * settings as determined by {@link android.provider.Settings.System#canWrite}.</p>
+ *
* @return a boolean - {@code true} indicating Tethering is supported.
*
* {@hide}
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+ @RequiresPermission(anyOf = {android.Manifest.permission.TETHER_PRIVILEGED,
+ android.Manifest.permission.WRITE_SETTINGS})
public boolean isTetheringSupported() {
+ String pkgName = mContext.getOpPackageName();
try {
- String pkgName = mContext.getOpPackageName();
return mService.isTetheringSupported(pkgName);
+ } catch (SecurityException e) {
+ // This API is not available to this caller, but for backward-compatibility
+ // this will just return false instead of throwing.
+ return false;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/os/ParcelableException.java b/core/java/android/os/ParcelableException.java
index d84d629..7f71905 100644
--- a/core/java/android/os/ParcelableException.java
+++ b/core/java/android/os/ParcelableException.java
@@ -52,10 +52,12 @@
final String msg = in.readString();
try {
final Class<?> clazz = Class.forName(name, true, Parcelable.class.getClassLoader());
- return (Throwable) clazz.getConstructor(String.class).newInstance(msg);
+ if (Throwable.class.isAssignableFrom(clazz)) {
+ return (Throwable) clazz.getConstructor(String.class).newInstance(msg);
+ }
} catch (ReflectiveOperationException e) {
- throw new RuntimeException(name + ": " + msg);
}
+ return new RuntimeException(name + ": " + msg);
}
/** {@hide} */
diff --git a/core/java/android/transition/TransitionUtils.java b/core/java/android/transition/TransitionUtils.java
index 3af7e5d..3306a50 100644
--- a/core/java/android/transition/TransitionUtils.java
+++ b/core/java/android/transition/TransitionUtils.java
@@ -115,7 +115,7 @@
/**
* Get a copy of bitmap of given drawable, return null if intrinsic size is zero
*/
- public static Bitmap createDrawableBitmap(Drawable drawable) {
+ public static Bitmap createDrawableBitmap(Drawable drawable, View hostView) {
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
if (width <= 0 || height <= 0) {
@@ -128,7 +128,7 @@
}
int bitmapWidth = (int) (width * scale);
int bitmapHeight = (int) (height * scale);
- final RenderNode node = RenderNode.create("TransitionUtils", null);
+ final RenderNode node = RenderNode.create("TransitionUtils", hostView);
node.setLeftTopRightBottom(0, 0, width, height);
node.setClipToBounds(false);
final DisplayListCanvas canvas = node.start(width, height);
@@ -172,7 +172,7 @@
matrix.postTranslate(-bounds.left, -bounds.top);
matrix.postScale(scale, scale);
- final RenderNode node = RenderNode.create("TransitionUtils", null);
+ final RenderNode node = RenderNode.create("TransitionUtils", view);
node.setLeftTopRightBottom(0, 0, bitmapWidth, bitmapHeight);
node.setClipToBounds(false);
final DisplayListCanvas canvas = node.start(bitmapWidth, bitmapHeight);
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 8691136..0299865 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -392,7 +392,7 @@
// and the length of the tag.
// Note: we implicitly accept possible truncation for Modified-UTF8 differences. It
// is too expensive to compute that ahead of time.
- int bufferSize = NoPreloadHolder.LOGGER_ENTRY_MAX_PAYLOAD // Base.
+ int bufferSize = PreloadHolder.LOGGER_ENTRY_MAX_PAYLOAD // Base.
- 2 // Two terminators.
- (tag != null ? tag.length() : 0) // Tag length.
- 32; // Some slack.
@@ -429,10 +429,10 @@
}
/**
- * NoPreloadHelper class. Caches the LOGGER_ENTRY_MAX_PAYLOAD value to avoid
+ * PreloadHelper class. Caches the LOGGER_ENTRY_MAX_PAYLOAD value to avoid
* a JNI call during logging.
*/
- static class NoPreloadHolder {
+ static class PreloadHolder {
public final static int LOGGER_ENTRY_MAX_PAYLOAD =
logger_entry_max_payload_native();
}
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index fceefaf..6c13e0c 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -70,14 +70,15 @@
mEditor = Preconditions.checkNotNull(editor);
mTextView = mEditor.getTextView();
mTextClassificationHelper = new TextClassificationHelper(
- mTextView.getTextClassifier(), mTextView.getText(),
+ mTextView.getTextClassifier(),
+ getText(mTextView),
0, 1, mTextView.getTextLocales());
mSelectionTracker = new SelectionTracker(mTextView);
}
public void startActionModeAsync(boolean adjustSelection) {
mSelectionTracker.onOriginalSelection(
- mTextView.getText(),
+ getText(mTextView),
mTextView.getSelectionStart(),
mTextView.getSelectionEnd(),
mTextView.isTextEditable());
@@ -166,7 +167,7 @@
}
private void startActionMode(@Nullable SelectionResult result) {
- final CharSequence text = mTextView.getText();
+ final CharSequence text = getText(mTextView);
if (result != null && text instanceof Spannable) {
Selection.setSelection((Spannable) text, result.mStart, result.mEnd);
mTextClassification = result.mClassification;
@@ -198,7 +199,9 @@
}
private void resetTextClassificationHelper() {
- mTextClassificationHelper.reset(mTextView.getTextClassifier(), mTextView.getText(),
+ mTextClassificationHelper.reset(
+ mTextView.getTextClassifier(),
+ getText(mTextView),
mTextView.getSelectionStart(), mTextView.getSelectionEnd(),
mTextView.getTextLocales());
}
@@ -301,7 +304,7 @@
if (isSelectionStarted()
&& mAllowReset
&& textIndex >= mSelectionStart && textIndex <= mSelectionEnd
- && textView.getText() instanceof Spannable) {
+ && getText(textView) instanceof Spannable) {
mAllowReset = false;
boolean selected = editor.selectCurrentWord();
if (selected) {
@@ -557,7 +560,7 @@
mSelectionResultSupplier = Preconditions.checkNotNull(selectionResultSupplier);
mSelectionResultCallback = Preconditions.checkNotNull(selectionResultCallback);
// Make a copy of the original text.
- mOriginalText = mTextView.getText().toString();
+ mOriginalText = getText(mTextView).toString();
}
@Override
@@ -573,7 +576,7 @@
@Override
@UiThread
protected void onPostExecute(SelectionResult result) {
- result = TextUtils.equals(mOriginalText, mTextView.getText()) ? result : null;
+ result = TextUtils.equals(mOriginalText, getText(mTextView)) ? result : null;
mSelectionResultCallback.accept(result);
}
@@ -702,8 +705,6 @@
}
}
-
-
@SelectionEvent.ActionType
private static int getActionType(int menuItemId) {
switch (menuItemId) {
@@ -724,4 +725,14 @@
return SelectionEvent.ActionType.OTHER;
}
}
+
+ private static CharSequence getText(TextView textView) {
+ // Extracts the textView's text.
+ // TODO: Investigate why/when TextView.getText() is null.
+ final CharSequence text = textView.getText();
+ if (text != null) {
+ return text;
+ }
+ return "";
+ }
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 105ef44..9aca2de 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2056,11 +2056,11 @@
Corresponds to {@link android.view.Window#setNavigationBarColor(int)}. -->
<attr name="navigationBarColor" format="color" />
- <!-- @hide
- Shows 1dp line of the specified color between the navigation bar and the app content.
+ <!-- Shows a thin line of the specified color between the navigation bar and the app
+ content.
<p>For this to take effect, the window must be drawing the system bar backgrounds with
{@link android.R.attr#windowDrawsSystemBarBackgrounds} and the navigation bar must not
- have been requested to be translucent with
+ have been requested to be translucent with
{@link android.R.attr#windowTranslucentNavigation}. -->
<attr name="navigationBarDividerColor" format="color" />
@@ -2097,7 +2097,7 @@
-->
<attr name="windowSplashscreenContent" format="reference" />
- <!-- @hide If set, the navigation bar will be drawn such that it is
+ <!-- If set, the navigation bar will be drawn such that it is
compatible with a light navigation bar background.
<p>For this to take effect, the window must be drawing the system bar backgrounds with
{@link android.R.attr#windowDrawsSystemBarBackgrounds} and the navigation bar must not
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9eed12f..b2727f8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3023,7 +3023,7 @@
<bool name="config_handleVolumeKeysInWindowManager">false</bool>
<!-- Volume level of in-call notification tone playback [0..1] -->
- <item name="config_inCallNotificationVolume" format="float" type="dimen">.25</item>
+ <item name="config_inCallNotificationVolume" format="float" type="dimen">.10</item>
<!-- URI for in call notification sound -->
<string translatable="false" name="config_inCallNotificationSound">/system/media/audio/ui/InCallNotification.ogg</string>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 634d79a..cfcd23d 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2846,6 +2846,8 @@
<public name="showWhenLocked"/>
<public name="turnScreenOn"/>
<public name="classLoader" />
+ <public name="windowLightNavigationBar" />
+ <public name="navigationBarDividerColor" />
</public-group>
<public-group type="style" first-id="0x010302e0">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index ce6815f..5347719 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2679,6 +2679,8 @@
<string name="yes">OK</string>
<!-- Preference framework strings. -->
<string name="no">Cancel</string>
+ <!-- Preference framework strings. -->
+ <string name="close">CLOSE</string>
<!-- This is the generic "attention" string to be used in attention dialogs. Typically
combined with setIconAttribute(android.R.attr.alertDialogIcon)
(or setIcon(android.R.drawable.ic_dialog_alert) on legacy versions of the platform) -->
@@ -2811,6 +2813,11 @@
<!-- [CHAR LIMIT=200] Compat mode dialog: hint to re-enable compat mode dialog. -->
<string name="screen_compat_mode_hint">Re-enable this in System settings > Apps > Downloaded.</string>
+ <!-- Text of the alert that is displayed when a top application is killed by lmk. -->
+ <string name="top_app_killed_title">App isn\'t responding</string>
+ <!-- Top app killed by lmk dialog message. -->
+ <string name="top_app_killed_message"><xliff:g id="app_name">%1$s</xliff:g> may be using too much memory.</string>
+
<!-- [CHAR LIMIT=200] Unsupported display size dialog: message. Refers to "Display size" setting. -->
<string name="unsupported_display_size_message"><xliff:g id="app_name">%1$s</xliff:g> does not support the current Display size setting and may behave unexpectedly.</string>
<!-- [CHAR LIMIT=50] Unsupported display size dialog: check box label. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0548db6..b36630e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1890,6 +1890,9 @@
<java-symbol type="string" name="anr_application_process" />
<java-symbol type="string" name="anr_process" />
<java-symbol type="string" name="anr_title" />
+ <java-symbol type="string" name="top_app_killed_title" />
+ <java-symbol type="string" name="top_app_killed_message" />
+ <java-symbol type="string" name="close" />
<java-symbol type="string" name="car_mode_disable_notification_message" />
<java-symbol type="string" name="car_mode_disable_notification_title" />
<java-symbol type="string" name="chooser_wallpaper" />
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 0209cea..40288f5 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -159,8 +159,10 @@
if (mNativeInstance == 0) {
mNativeInstance = createNativeInstance(mLocalMatrix == null
? 0 : mLocalMatrix.native_instance);
- mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
- this, mNativeInstance);
+ if (mNativeInstance != 0) {
+ mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+ this, mNativeInstance);
+ }
}
return mNativeInstance;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 8d62f2a..81b8622 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -23,6 +23,7 @@
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
+import android.graphics.drawable.Drawable;
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.text.TextUtils;
@@ -34,10 +35,8 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.Utils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
-import com.android.settingslib.graph.BluetoothDeviceLayerDrawable;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.R.drawable;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
@@ -135,11 +134,7 @@
if (lastDevice != null) {
int batteryLevel = lastDevice.getBatteryLevel();
if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
- BluetoothDeviceLayerDrawable drawable = createLayerDrawable(mContext,
- R.drawable.ic_qs_bluetooth_connected, batteryLevel,
- mContext.getResources().getFraction(
- R.fraction.bt_battery_scale_fraction, 1, 1));
- state.icon = new DrawableIcon(drawable);
+ state.icon = new BluetoothBatteryDrawable(batteryLevel);
}
}
state.contentDescription = mContext.getString(
@@ -215,6 +210,22 @@
return new BluetoothDetailAdapter();
}
+ private class BluetoothBatteryDrawable extends Icon {
+ private int mLevel;
+
+ BluetoothBatteryDrawable(int level) {
+ mLevel = level;
+ }
+
+ @Override
+ public Drawable getDrawable(Context context) {
+ return createLayerDrawable(context,
+ R.drawable.ic_qs_bluetooth_connected, mLevel,
+ context.getResources().getFraction(
+ R.fraction.bt_battery_scale_fraction, 1, 1));
+ }
+ }
+
protected class BluetoothDetailAdapter implements DetailAdapter, QSDetailItems.Callback {
// We probably won't ever have space in the UI for more than 20 devices, so don't
// get info for them.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideStackActionButtonEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideStackActionButtonEvent.java
index e02fb14..e4a4f59 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideStackActionButtonEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideStackActionButtonEvent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,5 +22,15 @@
* This is sent when the stack action button should be hidden.
*/
public class HideStackActionButtonEvent extends EventBus.Event {
- // Simple event
+
+ // Whether or not to translate the stack action button when hiding it
+ public final boolean translate;
+
+ public HideStackActionButtonEvent() {
+ this(true);
+ }
+
+ public HideStackActionButtonEvent(boolean translate) {
+ this.translate = translate;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index c44cd72..4a11fd05 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -174,8 +174,6 @@
? R.layout.recents_low_ram_stack_action_button
: R.layout.recents_stack_action_button,
this, false);
- mStackActionButton.setOnClickListener(
- v -> EventBus.getDefault().send(new DismissAllTaskViewsEvent()));
mStackButtonShadowRadius = mStackActionButton.getShadowRadius();
mStackButtonShadowDistance = new PointF(mStackActionButton.getShadowDx(),
@@ -572,7 +570,7 @@
mTransitionHelper.launchTaskFromRecents(getStack(), event.task, mTaskStackView,
event.taskView, event.screenPinningRequested, event.targetTaskStack);
if (Recents.getConfiguration().isLowRamDevice) {
- hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, false /* translate */);
+ EventBus.getDefault().send(new HideStackActionButtonEvent(false /* translate */));
}
}
@@ -580,7 +578,7 @@
int taskViewExitToHomeDuration = TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION;
if (RecentsDebugFlags.Static.EnableStackActionButton) {
// Hide the stack action button
- hideStackActionButton(taskViewExitToHomeDuration, false /* translate */);
+ EventBus.getDefault().send(new HideStackActionButtonEvent());
}
animateBackgroundScrim(0f, taskViewExitToHomeDuration);
@@ -741,13 +739,10 @@
animateBackgroundScrim(getOpaqueScrimAlpha(),
TaskStackAnimationHelper.ENTER_FROM_HOME_TRANSLATION_DURATION);
}
- if (Recents.getConfiguration().isLowRamDevice && mEmptyView.getVisibility() != View.VISIBLE) {
- showStackActionButton(SHOW_STACK_ACTION_BUTTON_DURATION, false /* translate */);
- }
}
public final void onBusEvent(AllTaskViewsDismissedEvent event) {
- hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, true /* translate */);
+ EventBus.getDefault().send(new HideStackActionButtonEvent());
}
public final void onBusEvent(DismissAllTaskViewsEvent event) {
@@ -795,7 +790,8 @@
mStackActionButton.setVisibility(View.VISIBLE);
mStackActionButton.setAlpha(0f);
if (translate) {
- mStackActionButton.setTranslationY(-mStackActionButton.getMeasuredHeight() * 0.25f);
+ mStackActionButton.setTranslationY(mStackActionButton.getMeasuredHeight() *
+ (Recents.getConfiguration().isLowRamDevice ? 1 : -0.25f));
} else {
mStackActionButton.setTranslationY(0f);
}
@@ -841,8 +837,8 @@
if (mStackActionButton.getVisibility() == View.VISIBLE) {
if (translate) {
- mStackActionButton.animate()
- .translationY(-mStackActionButton.getMeasuredHeight() * 0.25f);
+ mStackActionButton.animate().translationY(mStackActionButton.getMeasuredHeight()
+ * (Recents.getConfiguration().isLowRamDevice ? 1 : -0.25f));
}
mStackActionButton.animate()
.alpha(0f)
@@ -954,7 +950,7 @@
/**
* @return the bounds of the stack action button.
*/
- private Rect getStackActionButtonBoundsFromStackLayout() {
+ Rect getStackActionButtonBoundsFromStackLayout() {
Rect actionButtonRect = new Rect(mTaskStackView.mLayoutAlgorithm.getStackActionButtonRect());
int left, top;
if (Recents.getConfiguration().isLowRamDevice) {
@@ -976,6 +972,16 @@
return actionButtonRect;
}
+ View getStackActionButton() {
+ return mStackActionButton;
+ }
+
+ @Override
+ public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+ super.requestDisallowInterceptTouchEvent(disallowIntercept);
+ mTouchHandler.cancelStackActionButtonClick();
+ }
+
public void dump(String prefix, PrintWriter writer) {
String innerPrefix = prefix + " ";
String id = Integer.toHexString(System.identityHashCode(this));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index 46619c2..b6b24bc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -23,6 +23,7 @@
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.PointerIcon;
+import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewDebug;
@@ -31,6 +32,8 @@
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
+import com.android.systemui.recents.events.activity.HideStackActionButtonEvent;
+import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
import com.android.systemui.recents.events.ui.HideIncompatibleAppOverlayEvent;
import com.android.systemui.recents.events.ui.ShowIncompatibleAppOverlayEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
@@ -99,8 +102,7 @@
/** Touch preprocessing for handling below */
public boolean onInterceptTouchEvent(MotionEvent ev) {
- handleTouchEvent(ev);
- return mDragRequested;
+ return handleTouchEvent(ev) || mDragRequested;
}
/** Handles touch events once we have intercepted them */
@@ -183,22 +185,47 @@
}
}
+ void cancelStackActionButtonClick() {
+ mRv.getStackActionButton().setPressed(false);
+ }
+
+ private boolean isWithinStackActionButton(float x, float y) {
+ Rect rect = mRv.getStackActionButtonBoundsFromStackLayout();
+ return mRv.getStackActionButton().getVisibility() == View.VISIBLE &&
+ mRv.getStackActionButton().pointInView(x - rect.left, y - rect.top, 0 /* slop */);
+ }
+
+ private void changeStackActionButtonDrawableHotspot(float x, float y) {
+ Rect rect = mRv.getStackActionButtonBoundsFromStackLayout();
+ mRv.getStackActionButton().drawableHotspotChanged(x - rect.left, y - rect.top);
+ }
+
/**
* Handles dragging touch events
*/
- private void handleTouchEvent(MotionEvent ev) {
+ private boolean handleTouchEvent(MotionEvent ev) {
int action = ev.getActionMasked();
+ boolean consumed = false;
+ float evX = ev.getX();
+ float evY = ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
- mDownPos.set((int) ev.getX(), (int) ev.getY());
+ mDownPos.set((int) evX, (int) evY);
mDeviceId = ev.getDeviceId();
+
+ if (isWithinStackActionButton(evX, evY)) {
+ changeStackActionButtonDrawableHotspot(evX, evY);
+ mRv.getStackActionButton().setPressed(true);
+ }
break;
case MotionEvent.ACTION_MOVE: {
- float evX = ev.getX();
- float evY = ev.getY();
float x = evX - mTaskViewOffset.x;
float y = evY - mTaskViewOffset.y;
+ if (mRv.getStackActionButton().isPressed() && isWithinStackActionButton(evX, evY)) {
+ changeStackActionButtonDrawableHotspot(evX, evY);
+ }
+
if (mDragRequested) {
if (!mIsDragging) {
mIsDragging = Math.hypot(evX - mDownPos.x, evY - mDownPos.y) > mDragSlop;
@@ -232,9 +259,7 @@
EventBus.getDefault().send(new DragDropTargetChangedEvent(mDragTask,
currentDropTarget));
}
-
}
-
mTaskView.setTranslationX(x);
mTaskView.setTranslationY(y);
}
@@ -242,6 +267,11 @@
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
+ if (mRv.getStackActionButton().isPressed() && isWithinStackActionButton(evX, evY)) {
+ EventBus.getDefault().send(new DismissAllTaskViewsEvent());
+ consumed = true;
+ }
+ cancelStackActionButtonClick();
if (mDragRequested) {
boolean cancelled = action == MotionEvent.ACTION_CANCEL;
if (cancelled) {
@@ -254,5 +284,6 @@
mDeviceId = -1;
}
}
+ return consumed;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 8899e30..d32b220 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -1768,8 +1768,17 @@
}
// In grid layout, the stack action button always remains visible.
- if (mEnterAnimationComplete && !useGridLayout() &&
- !Recents.getConfiguration().isLowRamDevice) {
+ if (mEnterAnimationComplete && !useGridLayout()) {
+ if (Recents.getConfiguration().isLowRamDevice) {
+ // Show stack button when user drags down to show older tasks on low ram devices
+ if (mStack.getTaskCount() > 0 && !mStackActionButtonVisible
+ && mTouchHandler.mIsScrolling && curScroll - prevScroll < 0) {
+ // Going up
+ EventBus.getDefault().send(
+ new ShowStackActionButtonEvent(true /* translate */));
+ }
+ return;
+ }
if (prevScroll > SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
curScroll <= SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
mStack.getTaskCount() > 0) {
@@ -1956,6 +1965,9 @@
// Remove the task from the stack
mStack.removeTask(event.task, event.animation, false /* fromDockGesture */);
EventBus.getDefault().send(new DeleteTaskDataEvent(event.task));
+ if (mStack.getTaskCount() > 0 && Recents.getConfiguration().isLowRamDevice) {
+ EventBus.getDefault().send(new ShowStackActionButtonEvent(false /* translate */));
+ }
MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_DISMISS,
event.task.key.getComponent().toString());
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 6bfef20..23a7dae 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -64,6 +64,7 @@
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
import com.android.systemui.recents.events.activity.UndockingTaskEvent;
@@ -1210,6 +1211,10 @@
}
}
+ public final void onBusEvent(DockedFirstAnimationFrameEvent event) {
+ saveSnapTargetBeforeMinimized(mSnapAlgorithm.getMiddleTarget());
+ }
+
public final void onBusEvent(DockedTopTaskEvent event) {
if (event.dragMode == NavigationBarGestureHelper.DRAG_MODE_NONE) {
mState.growAfterRecentsDrawn = false;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 2b4f0f3..9afa825 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -19,6 +19,7 @@
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.NETID_UNSET;
+import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_NONE;
import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.getNetworkTypeName;
@@ -90,6 +91,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -781,6 +783,13 @@
mNetworksDefined++; // used only in the log() statement below.
}
+ // Do the same for Ethernet, since it's often not specified in the configs, although many
+ // devices can use it via USB host adapters.
+ if (mNetConfigs[TYPE_ETHERNET] == null && hasService(Context.ETHERNET_SERVICE)) {
+ mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET);
+ mNetworksDefined++;
+ }
+
if (VDBG) log("mNetworksDefined=" + mNetworksDefined);
mProtectedNetworks = new ArrayList<Integer>();
@@ -5546,6 +5555,11 @@
return new WakeupMessage(c, h, s, cmd, 0, 0, obj);
}
+ @VisibleForTesting
+ public boolean hasService(String name) {
+ return ServiceManager.checkService(name) != null;
+ }
+
private void logDefaultNetworkEvent(NetworkAgentInfo newNai, NetworkAgentInfo prevNai) {
int newNetid = NETID_UNSET;
int prevNetid = NETID_UNSET;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cbfc747..bffccaf 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1690,6 +1690,7 @@
static final int SERVICE_FOREGROUND_CRASH_MSG = 69;
static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70;
static final int START_USER_SWITCH_FG_MSG = 712;
+ static final int TOP_APP_KILLED_BY_LMK_MSG = 73;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1921,6 +1922,17 @@
dispatchProcessDied(pid, uid);
break;
}
+ case TOP_APP_KILLED_BY_LMK_MSG: {
+ final String appName = (String) msg.obj;
+ final AlertDialog d = new BaseErrorDialog(mUiContext);
+ d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+ d.setTitle(mUiContext.getText(R.string.top_app_killed_title));
+ d.setMessage(mUiContext.getString(R.string.top_app_killed_message, appName));
+ d.setButton(DialogInterface.BUTTON_POSITIVE, mUiContext.getText(R.string.close),
+ obtainMessage(DISMISS_DIALOG_UI_MSG, d));
+ d.show();
+ break;
+ }
case DISPATCH_UIDS_CHANGED_UI_MSG: {
dispatchUidsChanged();
} break;
@@ -5430,6 +5442,7 @@
boolean doLowMem = app.instr == null;
boolean doOomAdj = doLowMem;
if (!app.killedByAm) {
+ maybeNotifyTopAppKilled(app);
Slog.i(TAG, "Process " + app.processName + " (pid " + pid + ") has died: "
+ ProcessList.makeOomAdjString(app.setAdj)
+ ProcessList.makeProcStateString(app.setProcState));
@@ -5463,6 +5476,23 @@
}
}
+ /** Show system error dialog when a top app is killed by LMK */
+ void maybeNotifyTopAppKilled(ProcessRecord app) {
+ if (!shouldNotifyTopAppKilled(app)) {
+ return;
+ }
+
+ Message msg = mHandler.obtainMessage(TOP_APP_KILLED_BY_LMK_MSG);
+ msg.obj = mContext.getPackageManager().getApplicationLabel(app.info);
+ mUiHandler.sendMessage(msg);
+ }
+
+ /** Only show notification when the top app is killed on low ram devices */
+ private boolean shouldNotifyTopAppKilled(ProcessRecord app) {
+ return app.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP &&
+ ActivityManager.isLowRamDeviceStatic();
+ }
+
/**
* If a stack trace dump file is configured, dump process stack traces.
* @param clearTraces causes the dump file to be erased prior to the new
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 11d0470..3c1f2d4 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -461,6 +461,8 @@
// Forced device usage for communications
private int mForcedUseForComm;
+ private int mForcedUseForCommExt; // External state returned by getters: always consistent
+ // with requests by setters
// List of binder death handlers for setMode() client processes.
// The last process to have called setMode() is at the top of the list.
@@ -2890,13 +2892,14 @@
mForcedUseForComm = AudioSystem.FORCE_NONE;
}
+ mForcedUseForCommExt = mForcedUseForComm;
sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0);
}
/** @see AudioManager#isSpeakerphoneOn() */
public boolean isSpeakerphoneOn() {
- return (mForcedUseForComm == AudioSystem.FORCE_SPEAKER);
+ return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER);
}
/** @see AudioManager#setBluetoothScoOn(boolean) */
@@ -2904,6 +2907,13 @@
if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
return;
}
+
+ // Only enable calls from system components
+ if (Binder.getCallingUid() >= FIRST_APPLICATION_UID) {
+ mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE;
+ return;
+ }
+
// for logging only
final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on)
.append(") from u/pid:").append(Binder.getCallingUid()).append("/")
@@ -2913,11 +2923,21 @@
public void setBluetoothScoOnInt(boolean on, String eventSource) {
if (on) {
+ // do not accept SCO ON if SCO audio is not connected
+ synchronized(mScoClients) {
+ if ((mBluetoothHeadset != null) &&
+ (mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice)
+ != BluetoothHeadset.STATE_AUDIO_CONNECTED)) {
+ mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO;
+ return;
+ }
+ }
mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
} else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
mForcedUseForComm = AudioSystem.FORCE_NONE;
}
-
+ mForcedUseForCommExt = mForcedUseForComm;
+ AudioSystem.setParameters("BT_SCO="+ (on ? "on" : "off"));
sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0);
sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
@@ -2926,7 +2946,7 @@
/** @see AudioManager#isBluetoothScoOn() */
public boolean isBluetoothScoOn() {
- return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO);
+ return (mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO);
}
/** @see AudioManager#setBluetoothA2dpOn(boolean) */
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 77769cd..4e92d10 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1278,13 +1278,11 @@
R.array.config_notificationFallbackVibePattern,
VIBRATE_PATTERN_MAXLEN,
DEFAULT_VIBRATE_PATTERN);
-
mInCallNotificationUri = Uri.parse("file://" +
resources.getString(R.string.config_inCallNotificationSound));
mInCallNotificationAudioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
- .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
.build();
mInCallNotificationVolume = resources.getFloat(R.dimen.config_inCallNotificationVolume);
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 4fafe34..e254196 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -425,7 +425,7 @@
}
if (useInfo.isUsedByOtherApps(path)) {
- pw.println("used be other apps: " + useInfo.getLoadingPackages(path));
+ pw.println("used by other apps: " + useInfo.getLoadingPackages(path));
}
Map<String, PackageDexUsage.DexUseInfo> dexUseInfoMap = useInfo.getDexUseInfoMap();
@@ -441,7 +441,7 @@
// TODO(calin): get the status of the oat file (needs installd call)
pw.println("class loader context: " + dexUseInfo.getClassLoaderContext());
if (dexUseInfo.isUsedByOtherApps()) {
- pw.println("used be other apps: " + dexUseInfo.getLoadingPackages());
+ pw.println("used by other apps: " + dexUseInfo.getLoadingPackages());
}
pw.decreaseIndent();
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ea1c029..224791b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3312,6 +3312,24 @@
removeCodePathLI(dstCodePath);
return null;
}
+
+ // If we have a profile for a compressed APK, copy it to the reference location.
+ // Since the package is the stub one, remove the stub suffix to get the normal package and
+ // APK name.
+ File profileFile = new File(getPrebuildProfilePath(pkg).replace(STUB_SUFFIX, ""));
+ if (profileFile.exists()) {
+ try {
+ // We could also do this lazily before calling dexopt in
+ // PackageDexOptimizer to prevent this happening on first boot. The issue
+ // is that we don't have a good way to say "do this only once".
+ if (!mInstaller.copySystemProfile(profileFile.getAbsolutePath(),
+ pkg.applicationInfo.uid, pkg.packageName)) {
+ Log.e(TAG, "decompressPackage failed to copy system profile!");
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath() + " ", e);
+ }
+ }
return dstCodePath;
}
@@ -9723,7 +9741,7 @@
* and {@code numberOfPackagesFailed}.
*/
private int[] performDexOptUpgrade(List<PackageParser.Package> pkgs, boolean showDialog,
- String compilerFilter, boolean bootComplete) {
+ final String compilerFilter, boolean bootComplete) {
int numberOfPackagesVisited = 0;
int numberOfPackagesOptimized = 0;
@@ -9734,6 +9752,8 @@
for (PackageParser.Package pkg : pkgs) {
numberOfPackagesVisited++;
+ boolean useProfileForDexopt = false;
+
if ((isFirstBoot() || isUpgrade()) && isSystemApp(pkg)) {
// Copy over initial preopt profiles since we won't get any JIT samples for methods
// that are already compiled.
@@ -9747,11 +9767,30 @@
if (!mInstaller.copySystemProfile(profileFile.getAbsolutePath(),
pkg.applicationInfo.uid, pkg.packageName)) {
Log.e(TAG, "Installer failed to copy system profile!");
+ } else {
+ // Disabled as this causes speed-profile compilation during first boot
+ // even if things are already compiled.
+ // useProfileForDexopt = true;
}
} catch (Exception e) {
Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath() + " ",
e);
}
+ } else {
+ PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(pkg.packageName);
+ // Handle compressed APKs in this path. Only do this for stubs with profiles to
+ // minimize the number off apps being speed-profile compiled during first boot.
+ // The other paths will not change the filter.
+ if (disabledPs != null && disabledPs.pkg.isStub) {
+ // The package is the stub one, remove the stub suffix to get the normal
+ // package and APK names.
+ String systemProfilePath =
+ getPrebuildProfilePath(disabledPs.pkg).replace(STUB_SUFFIX, "");
+ File systemProfile = new File(systemProfilePath);
+ // Use the profile for compilation if there exists one for the same package
+ // in the system partition.
+ useProfileForDexopt = systemProfile.exists();
+ }
}
}
@@ -9780,17 +9819,13 @@
}
}
- // If the OTA updates a system app which was previously preopted to a non-preopted state
- // the app might end up being verified at runtime. That's because by default the apps
- // are verify-profile but for preopted apps there's no profile.
- // Do a hacky check to ensure that if we have no profiles (a reasonable indication
- // that before the OTA the app was preopted) the app gets compiled with a non-profile
- // filter (by default 'quicken').
- // Note that at this stage unused apps are already filtered.
- if (isSystemApp(pkg) &&
- DexFile.isProfileGuidedCompilerFilter(compilerFilter) &&
- !Environment.getReferenceProfile(pkg.packageName).exists()) {
- compilerFilter = getNonProfileGuidedCompilerFilter(compilerFilter);
+ String pkgCompilerFilter = compilerFilter;
+ if (useProfileForDexopt) {
+ // Use background dexopt mode to try and use the profile. Note that this does not
+ // guarantee usage of the profile.
+ pkgCompilerFilter =
+ PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
+ PackageManagerService.REASON_BACKGROUND_DEXOPT);
}
// checkProfiles is false to avoid merging profiles during boot which
@@ -9801,7 +9836,7 @@
int dexoptFlags = bootComplete ? DexoptOptions.DEXOPT_BOOT_COMPLETE : 0;
int primaryDexOptStaus = performDexOptTraced(new DexoptOptions(
pkg.packageName,
- compilerFilter,
+ pkgCompilerFilter,
dexoptFlags));
switch (primaryDexOptStaus) {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 8816d43..6674f20 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -19,6 +19,8 @@
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
+import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
import static android.net.ConnectivityManager.TYPE_NONE;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.getNetworkTypeName;
@@ -781,6 +783,13 @@
return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj);
}
+ @Override
+ public boolean hasService(String name) {
+ // Currenty, the only relevant service that ConnectivityService checks for is
+ // ETHERNET_SERVICE.
+ return Context.ETHERNET_SERVICE.equals(name);
+ }
+
public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
return mLastCreatedNetworkMonitor;
}
@@ -928,6 +937,13 @@
// will fail. Failing here is much easier to debug.
assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
+ assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
+ assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
+
+ // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
+ // mocks, this assert exercises the ConnectivityService code path that ensures that
+ // TYPE_ETHERNET is supported if the ethernet service is running.
+ assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET));
}
@SmallTest