diff options
25 files changed, 160 insertions, 94 deletions
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 7cec957adf41..a140f280e7c3 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -970,6 +970,9 @@ public final class ThreadedRenderer { observer.mNative = null; } + /** Not actually public - internal use only. This doc to make lint happy */ + public static native void disableVsync(); + static native void setupShadersDiskCache(String cacheFile); private static native void nRotateProcessStatsBuffer(); diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java index 1e8207a2e7b3..f712d5fa65ca 100644 --- a/core/java/android/widget/DayPickerView.java +++ b/core/java/android/widget/DayPickerView.java @@ -293,9 +293,19 @@ class DayPickerView extends ViewGroup { * @param setSelected whether to set the specified day as selected */ private void setDate(long timeInMillis, boolean animate, boolean setSelected) { + boolean dateClamped = false; + // Clamp the target day in milliseconds to the min or max if outside the range. + if (timeInMillis < mMinDate.getTimeInMillis()) { + timeInMillis = mMinDate.getTimeInMillis(); + dateClamped = true; + } else if (timeInMillis > mMaxDate.getTimeInMillis()) { + timeInMillis = mMaxDate.getTimeInMillis(); + dateClamped = true; + } + getTempCalendarForTime(timeInMillis); - if (setSelected) { + if (setSelected || dateClamped) { mSelectedDay.setTimeInMillis(timeInMillis); } @@ -353,13 +363,6 @@ class DayPickerView extends ViewGroup { public void onRangeChanged() { mAdapter.setRange(mMinDate, mMaxDate); - // Clamp the selected day to the new min/max. - if (mSelectedDay.before(mMinDate)) { - mSelectedDay.setTimeInMillis(mMinDate.getTimeInMillis()); - } else if (mSelectedDay.after(mMaxDate)) { - mSelectedDay.setTimeInMillis(mMaxDate.getTimeInMillis()); - } - // Changing the min/max date changes the selection position since we // don't really have stable IDs. Jumps immediately to the new position. setDate(mSelectedDay.getTimeInMillis(), false, false); diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 7117137ce2f8..aa6ffceea9f3 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -2342,24 +2342,26 @@ public class RemoteViews implements Parcelable, Filter { } - public synchronized RemoteViews clone() { - Preconditions.checkState(mIsRoot, "RemoteView has been attached to another RemoteView. " - + "May only clone the root of a RemoteView hierarchy."); + 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(); + Parcel p = Parcel.obtain(); - // 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; + // 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; + RemoteViews rv = new RemoteViews(p, mBitmapCache.clone(), mApplication, 0); + rv.mIsRoot = true; - p.recycle(); - return rv; + p.recycle(); + return rv; + } } public String getPackage() { diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index 438b1233a286..c9251bcac835 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -932,6 +932,10 @@ static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode( return createBitmap(env, bitmap.release(), android::bitmap::kBitmapCreateFlag_Mutable); } +static void android_view_ThreadedRenderer_disableVsync(JNIEnv*, jclass) { + RenderProxy::disableVsync(); +} + // ---------------------------------------------------------------------------- // FrameMetricsObserver // ---------------------------------------------------------------------------- @@ -1030,6 +1034,7 @@ static const JNINativeMethod gMethods[] = { (void*)android_view_ThreadedRenderer_copySurfaceInto }, { "nCreateHardwareBitmap", "(JII)Landroid/graphics/Bitmap;", (void*)android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode }, + { "disableVsync", "()V", (void*)android_view_ThreadedRenderer_disableVsync }, }; int register_android_view_ThreadedRenderer(JNIEnv* env) { diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index aad81df0b7e5..b5872485b136 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -69,6 +69,7 @@ bool Properties::waitForGpuCompletion = false; bool Properties::forceDrawFrame = false; bool Properties::filterOutTestOverhead = false; +bool Properties::disableVsync = false; static int property_get_int(const char* key, int defaultValue) { char buf[PROPERTY_VALUE_MAX] = {'\0',}; diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 9db64493928a..91b4a2d440e2 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -318,6 +318,12 @@ public: // any overhead they add static bool filterOutTestOverhead; + // Workaround a device lockup in edge cases by switching to async mode + // instead of the default vsync (b/38372997). Only system_server should hit this. + // Any existing RenderProxy & Surface combination will be unaffected, only things + // created after changing this. + static bool disableVsync; + // Used for testing only to change the render pipeline. #ifdef HWUI_GLES_WRAP_ENABLED static void overrideRenderPipelineType(RenderPipelineType); diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp index 44af5fd8d0dd..ed3070887b8b 100644 --- a/libs/hwui/renderthread/EglManager.cpp +++ b/libs/hwui/renderthread/EglManager.cpp @@ -279,6 +279,9 @@ bool EglManager::makeCurrent(EGLSurface surface, EGLint* errOut) { } } mCurrentSurface = surface; + if (Properties::disableVsync) { + eglSwapInterval(mEglDisplay, 0); + } return true; } diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index eed523810403..d842be9e7d6e 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -18,6 +18,7 @@ #include "DeferredLayerUpdater.h" #include "DisplayList.h" +#include "Properties.h" #include "Readback.h" #include "Rect.h" #include "renderthread/CanvasContext.h" @@ -708,6 +709,10 @@ void RenderProxy::onBitmapDestroyed(uint32_t pixelRefId) { thread.queue(task); } +void RenderProxy::disableVsync() { + Properties::disableVsync = true; +} + void RenderProxy::post(RenderTask* task) { mRenderThread.queue(task); } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index b21772cd88de..6f4e8cef4502 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -137,6 +137,8 @@ public: static int copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap); static void onBitmapDestroyed(uint32_t pixelRefId); + + ANDROID_API static void disableVsync(); private: RenderThread& mRenderThread; CanvasContext* mContext; diff --git a/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java b/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java index a36f5837ecb1..17d820a983f9 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java +++ b/packages/PrintSpooler/src/com/android/printspooler/util/PageRangeUtils.java @@ -426,7 +426,7 @@ public final class PageRangeUtils { // be based off the start of the written ones instead of zero. // The written pages are always non-null and not empty. final int offset = -pagesWrittenToFile[0].getStart(); - PageRangeUtils.offset(pagesInDocRequested, offset); + PageRangeUtils.offset(pagesInDocRequested.clone(), offset); return pagesInDocRequested; } else if (Arrays.equals(pagesInDocRequested, ALL_PAGES_RANGE) && isAllPages(pagesWrittenToFile, pageCount)) { diff --git a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java index 474de9074062..1cbb7450f7e1 100644 --- a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java +++ b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java @@ -88,21 +88,16 @@ public class ZoneGetter { private static final String XMLTAG_TIMEZONE = "timezone"; public static CharSequence getTimeZoneOffsetAndName(Context context, TimeZone tz, Date now) { - final Locale locale = Locale.getDefault(); - final CharSequence gmtText = getGmtOffsetText(context, locale, tz, now); - final TimeZoneNames timeZoneNames = TimeZoneNames.getInstance(locale); - final ZoneGetterData data = new ZoneGetterData(context); - - final boolean useExemplarLocationForLocalNames = - shouldUseExemplarLocationForLocalNames(data, timeZoneNames); - final CharSequence zoneName = getTimeZoneDisplayName(data, timeZoneNames, - useExemplarLocationForLocalNames, tz, tz.getID()); - if (zoneName == null) { + Locale locale = Locale.getDefault(); + CharSequence gmtText = getGmtOffsetText(context, locale, tz, now); + TimeZoneNames timeZoneNames = TimeZoneNames.getInstance(locale); + String zoneNameString = getZoneLongName(timeZoneNames, tz, now); + if (zoneNameString == null) { return gmtText; } // We don't use punctuation here to avoid having to worry about localizing that too! - return TextUtils.concat(gmtText, " ", zoneName); + return TextUtils.concat(gmtText, " ", zoneNameString); } public static List<Map<String, Object>> getZonesList(Context context) { diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java index 703e9d29e6ac..a3345ee58b7d 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java @@ -47,9 +47,9 @@ public class ZoneGetterTest { } @Test - public void getTimeZoneOffsetAndName_setLondon_returnLondon() { - // Check it will ends with 'London', not 'British Summer Time' or sth else - testTimeZoneOffsetAndNameInner(TIME_ZONE_LONDON_ID, "London"); + public void getTimeZoneOffsetAndName_setLondon_returnBritishSummerTime() { + // Check it will ends with 'British Summer Time', not 'London' or sth else + testTimeZoneOffsetAndNameInner(TIME_ZONE_LONDON_ID, "British Summer Time"); } @Test diff --git a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java index eaf715ffc4c9..5b3ec08ce752 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java @@ -35,9 +35,7 @@ public class CellTileView extends SignalTileView { public CellTileView(Context context) { super(context); mSignalDrawable = new SignalDrawable(mContext); - float dark = Utils.getColorAttr(context, android.R.attr.colorForeground) == 0xff000000 - ? 1 : 0; - mSignalDrawable.setDarkIntensity(dark); + mSignalDrawable.setDarkIntensity(isDark(mContext)); mSignalDrawable.setIntrinsicSize(context.getResources().getDimensionPixelSize( R.dimen.qs_tile_icon_size)); } @@ -50,6 +48,10 @@ public class CellTileView extends SignalTileView { } } + private static int isDark(Context context) { + return Utils.getColorAttr(context, android.R.attr.colorForeground) == 0xff000000 ? 1 : 0; + } + public static class SignalIcon extends Icon { private final int mState; @@ -64,7 +66,11 @@ public class CellTileView extends SignalTileView { @Override public Drawable getDrawable(Context context) { - return null; + //TODO: Not the optimal solution to create this drawable + SignalDrawable d = new SignalDrawable(context); + d.setDarkIntensity(isDark(context)); + d.setLevel(getState()); + return d; } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java index f124e8686749..697db5fabcd8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java @@ -73,6 +73,7 @@ public class QSDetail extends LinearLayout { private int mOpenY; private boolean mAnimatingOpen; private boolean mSwitchState; + private View mFooter; public QSDetail(Context context, @Nullable AttributeSet attrs) { super(context, attrs); @@ -116,9 +117,10 @@ public class QSDetail extends LinearLayout { mDetailDoneButton.setOnClickListener(doneListener); } - public void setQsPanel(QSPanel panel, QuickStatusBarHeader header) { + public void setQsPanel(QSPanel panel, QuickStatusBarHeader header, View footer) { mQsPanel = panel; mHeader = header; + mFooter = footer; mHeader.setCallback(mQsPanelCallback); mQsPanel.setCallback(mQsPanelCallback); } @@ -214,6 +216,7 @@ public class QSDetail extends LinearLayout { mDetailAdapter = null; listener = mTeardownDetailWhenDone; mHeader.setVisibility(View.VISIBLE); + mFooter.setVisibility(View.VISIBLE); mQsPanel.setGridContentVisibility(true); mQsPanelCallback.onScanStateChanged(false); } @@ -345,6 +348,7 @@ public class QSDetail extends LinearLayout { if (mDetailAdapter != null) { mQsPanel.setGridContentVisibility(false); mHeader.setVisibility(View.INVISIBLE); + mFooter.setVisibility(View.INVISIBLE); } mAnimatingOpen = false; checkPendingAnimations(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index c9c3a7f9e147..aa01c9e4db8b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -82,7 +82,7 @@ public class QSFragment extends Fragment implements QS { mContainer = view.findViewById(id.quick_settings_container); mGutterHeight = getContext().getResources().getDimensionPixelSize(R.dimen.qs_gutter_height); - mQSDetail.setQsPanel(mQSPanel, mHeader); + mQSDetail.setQsPanel(mQSPanel, mHeader, mFooter); // If the quick settings row is not shown, then there is no need for the animation from // the row to the full QS panel. diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java index 7cbe98594d68..d270de8c50f7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java @@ -23,6 +23,8 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import org.junit.After; +import org.junit.Ignore; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -37,8 +39,6 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.DetailAdapter; -import org.junit.After; -import org.junit.Ignore; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -65,7 +65,7 @@ public class QSDetailTest extends SysuiTestCase { mQsDetail = (QSDetail) LayoutInflater.from(mContext).inflate(R.layout.qs_detail, null); mQsPanel = mock(QSPanel.class); mQuickHeader = mock(QuickStatusBarHeader.class); - mQsDetail.setQsPanel(mQsPanel, mQuickHeader); + mQsDetail.setQsPanel(mQsPanel, mQuickHeader, mock(View.class)); mMockDetailAdapter = mock(DetailAdapter.class); when(mMockDetailAdapter.createDetailView(any(), any(), any())) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index ac68a9ea6dc2..7b55e5f34941 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -10254,11 +10254,11 @@ public class ActivityManagerService extends IActivityManager.Stub if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToFront: moving taskId=" + taskId); synchronized(this) { - moveTaskToFrontLocked(taskId, flags, bOptions); + moveTaskToFrontLocked(taskId, flags, bOptions, false /* fromRecents */); } } - void moveTaskToFrontLocked(int taskId, int flags, Bundle bOptions) { + void moveTaskToFrontLocked(int taskId, int flags, Bundle bOptions, boolean fromRecents) { ActivityOptions options = ActivityOptions.fromBundle(bOptions); if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(), @@ -10291,7 +10291,7 @@ public class ActivityManagerService extends IActivityManager.Stub // We are reshowing a task, use a starting window to hide the initial draw delay // so the transition can start earlier. topActivity.showStartingWindow(null /* prev */, false /* newTask */, - true /* taskSwitch */); + true /* taskSwitch */, fromRecents); } } finally { Binder.restoreCallingIdentity(origId); diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index ec6a4f6b7f7c..a826b6844e9c 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -2153,6 +2153,11 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch) { + showStartingWindow(prev, newTask, taskSwitch, false /* fromRecents */); + } + + void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch, + boolean fromRecents) { if (mWindowContainerController == null) { return; } @@ -2167,7 +2172,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags, prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(), allowTaskSnapshot(), - state.ordinal() >= RESUMED.ordinal() && state.ordinal() <= STOPPED.ordinal()); + state.ordinal() >= RESUMED.ordinal() && state.ordinal() <= STOPPED.ordinal(), + fromRecents); if (shown) { mStartingWindowState = STARTING_WINDOW_SHOWN; } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 53afe78f2ea3..7de56fa17877 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -5131,7 +5131,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D && task.getRootActivity() != null) { mService.mActivityStarter.sendPowerHintForLaunchStartIfNeeded(true /* forceSend */); mActivityMetricsLogger.notifyActivityLaunching(); - mService.moveTaskToFrontLocked(task.taskId, 0, bOptions); + mService.moveTaskToFrontLocked(task.taskId, 0, bOptions, true /* fromRecents */); mActivityMetricsLogger.notifyActivityLaunched(ActivityManager.START_TASK_TO_FRONT, task.getTopActivity()); diff --git a/services/core/java/com/android/server/display/OverlayDisplayWindow.java b/services/core/java/com/android/server/display/OverlayDisplayWindow.java index f23caf2e7a76..0fdf2daf1c8d 100644 --- a/services/core/java/com/android/server/display/OverlayDisplayWindow.java +++ b/services/core/java/com/android/server/display/OverlayDisplayWindow.java @@ -30,6 +30,7 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.TextureView; +import android.view.ThreadedRenderer; import android.view.View; import android.view.WindowManager; import android.view.TextureView.SurfaceTextureListener; @@ -95,6 +96,8 @@ final class OverlayDisplayWindow implements DumpUtils.Dump { public OverlayDisplayWindow(Context context, String name, int width, int height, int densityDpi, int gravity, boolean secure, Listener listener) { + // Workaround device freeze (b/38372997) + ThreadedRenderer.disableVsync(); mContext = context; mName = name; mGravity = gravity; diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java index 8cfbf68e3b5d..e550a5e0912e 100644 --- a/services/core/java/com/android/server/wm/AppWindowContainerController.java +++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java @@ -40,6 +40,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Trace; import android.util.Slog; +import android.view.DisplayInfo; import android.view.IApplicationToken; import android.view.WindowManagerPolicy.StartingSurface; @@ -481,7 +482,7 @@ public class AppWindowContainerController public boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning, - boolean allowTaskSnapshot, boolean activityCreated) { + boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) { synchronized(mWindowMap) { if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "setAppStartingWindow: token=" + mToken + " pkg=" + pkg + " transferFrom=" + transferFrom + " newTask=" + newTask @@ -510,11 +511,14 @@ public class AppWindowContainerController return false; } + final TaskSnapshot snapshot = mService.mTaskSnapshotController.getSnapshot( + mContainer.getTask().mTaskId, mContainer.getTask().mUserId, + false /* restoreFromDisk */, false /* reducedResolution */); final int type = getStartingWindowType(newTask, taskSwitch, processRunning, - allowTaskSnapshot, activityCreated); + allowTaskSnapshot, activityCreated, fromRecents, snapshot); if (type == STARTING_WINDOW_TYPE_SNAPSHOT) { - return createSnapshot(); + return createSnapshot(snapshot); } // If this is a translucent window, then don't show a starting window -- the current @@ -582,7 +586,8 @@ public class AppWindowContainerController } private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning, - boolean allowTaskSnapshot, boolean activityCreated) { + boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents, + TaskSnapshot snapshot) { if (mService.mAppTransition.getAppTransition() == TRANSIT_DOCK_TASK_FROM_RECENTS) { // TODO(b/34099271): Remove this statement to add back the starting window and figure // out why it causes flickering, the starting window appears over the thumbnail while @@ -591,7 +596,9 @@ public class AppWindowContainerController } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) { return STARTING_WINDOW_TYPE_SPLASH_SCREEN; } else if (taskSwitch && allowTaskSnapshot) { - return STARTING_WINDOW_TYPE_SNAPSHOT; + return snapshot == null ? STARTING_WINDOW_TYPE_NONE + : snapshotFillsWidth(snapshot) || fromRecents ? STARTING_WINDOW_TYPE_SNAPSHOT + : STARTING_WINDOW_TYPE_SPLASH_SCREEN; } else { return STARTING_WINDOW_TYPE_NONE; } @@ -605,11 +612,7 @@ public class AppWindowContainerController mService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow); } - private boolean createSnapshot() { - final TaskSnapshot snapshot = mService.mTaskSnapshotController.getSnapshot( - mContainer.getTask().mTaskId, mContainer.getTask().mUserId, - false /* restoreFromDisk */, false /* reducedResolution */); - + private boolean createSnapshot(TaskSnapshot snapshot) { if (snapshot == null) { return false; } @@ -620,6 +623,24 @@ public class AppWindowContainerController return true; } + private boolean snapshotFillsWidth(TaskSnapshot snapshot) { + if (snapshot == null) { + return false; + } + final Rect rect = new Rect(0, 0, snapshot.getSnapshot().getWidth(), + snapshot.getSnapshot().getHeight()); + rect.inset(snapshot.getContentInsets()); + final Rect taskBoundsWithoutInsets = new Rect(); + mContainer.getTask().getBounds(taskBoundsWithoutInsets); + final DisplayInfo di = mContainer.getDisplayContent().getDisplayInfo(); + final Rect displayBounds = new Rect(0, 0, di.logicalWidth, di.logicalHeight); + final Rect stableInsets = new Rect(); + mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, + stableInsets); + displayBounds.inset(stableInsets); + return rect.width() >= displayBounds.width(); + } + public void removeStartingWindow() { synchronized (mWindowMap) { if (mHandler.hasCallbacks(mRemoveStartingWindow)) { diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 71ecaf61da48..350a333cc893 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -891,8 +891,24 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree return mPendingRelaunchCount > 0; } + boolean shouldFreezeBounds() { + final Task task = getTask(); + + // For freeform windows, we can't freeze the bounds at the moment because this would make + // the resizing unresponsive. + if (task == null || task.inFreeformWorkspace()) { + return false; + } + + // We freeze the bounds while drag resizing to deal with the time between + // the divider/drag handle being released, and the handling it's new + // configuration. If we are relaunched outside of the drag resizing state, + // we need to be careful not to do this. + return getTask().isDragResizing(); + } + void startRelaunching() { - if (canFreezeBounds()) { + if (shouldFreezeBounds()) { freezeBounds(); } @@ -909,9 +925,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } void finishRelaunching() { - if (canFreezeBounds()) { - unfreezeBounds(); - } + unfreezeBounds(); + if (mPendingRelaunchCount > 0) { mPendingRelaunchCount--; } else { @@ -926,9 +941,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree if (mPendingRelaunchCount == 0) { return; } - if (canFreezeBounds()) { - unfreezeBounds(); - } + unfreezeBounds(); mPendingRelaunchCount = 0; } @@ -1032,14 +1045,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } } - private boolean canFreezeBounds() { - final Task task = getTask(); - - // For freeform windows, we can't freeze the bounds at the moment because this would make - // the resizing unresponsive. - return task != null && !task.inFreeformWorkspace(); - } - /** * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even @@ -1064,9 +1069,10 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree * Unfreezes the previously frozen bounds. See {@link #freezeBounds}. */ private void unfreezeBounds() { - if (!mFrozenBounds.isEmpty()) { - mFrozenBounds.remove(); + if (mFrozenBounds.isEmpty()) { + return; } + mFrozenBounds.remove(); if (!mFrozenMergedConfig.isEmpty()) { mFrozenMergedConfig.remove(); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 9e3edef768d7..e826aca5e2a7 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1270,14 +1270,6 @@ public class WindowManagerService extends IWindowManager.Stub + token + ". Aborting."); return WindowManagerGlobal.ADD_APP_EXITING; } - if (rootType == TYPE_APPLICATION_STARTING - && (attrs.privateFlags & PRIVATE_FLAG_TASK_SNAPSHOT) == 0 - && atoken.firstWindowDrawn) { - // No need for this guy! - if (DEBUG_STARTING_WINDOW || localLOGV) Slog.v( - TAG_WM, "**** NO NEED TO START: " + attrs.getTitle()); - return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED; - } } else if (rootType == TYPE_INPUT_METHOD) { if (token.windowType != TYPE_INPUT_METHOD) { Slog.w(TAG_WM, "Attempted to add input method window with bad token " diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp index 96c2d7e38232..470cc572e3e5 100644 --- a/services/core/jni/com_android_server_SystemServer.cpp +++ b/services/core/jni/com_android_server_SystemServer.cpp @@ -39,7 +39,7 @@ static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jo } -static void android_server_SystemServer_startHidlServices(JNIEnv* /* env */, jobject /* clazz */) { +static void android_server_SystemServer_startHidlServices(JNIEnv* env, jobject /* clazz */) { using ::android::frameworks::schedulerservice::V1_0::ISchedulingPolicyService; using ::android::frameworks::schedulerservice::V1_0::implementation::SchedulingPolicyService; using ::android::frameworks::sensorservice::V1_0::ISensorManager; @@ -50,7 +50,10 @@ static void android_server_SystemServer_startHidlServices(JNIEnv* /* env */, job configureRpcThreadpool(5, false /* callerWillJoin */); - sp<ISensorManager> sensorService = new SensorManager(); + JavaVM *vm; + LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Cannot get Java VM"); + + sp<ISensorManager> sensorService = new SensorManager(vm); err = sensorService->registerAsService(); ALOGE_IF(err != OK, "Cannot register %s: %d", ISensorManager::descriptor, err); diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java index 65a56327bb24..606088128fc4 100644 --- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java @@ -107,7 +107,7 @@ public class AppWindowContainerControllerTests extends WindowTestsBase { createAppWindowController(); controller.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(), android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true, - false); + false, false); waitUntilHandlersIdle(); final AppWindowToken atoken = controller.getAppWindowToken(mDisplayContent); assertHasStartingWindow(atoken); @@ -125,7 +125,7 @@ public class AppWindowContainerControllerTests extends WindowTestsBase { createAppWindowController(); controller.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(), android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true, - false); + false, false); controller.removeStartingWindow(); waitUntilHandlersIdle(); assertNoStartingWindow(controller.getAppWindowToken(mDisplayContent)); @@ -140,11 +140,11 @@ public class AppWindowContainerControllerTests extends WindowTestsBase { createAppWindowController(); controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(), android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true, - false); + false, false); waitUntilHandlersIdle(); controller2.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(), android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(), - true, true, false, true, false); + true, true, false, true, false, false); waitUntilHandlersIdle(); assertNoStartingWindow(controller1.getAppWindowToken(mDisplayContent)); assertHasStartingWindow(controller2.getAppWindowToken(mDisplayContent)); @@ -161,11 +161,11 @@ public class AppWindowContainerControllerTests extends WindowTestsBase { // Surprise, ...! Transfer window in the middle of the creation flow. controller2.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(), android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(), - true, true, false, true, false); + true, true, false, true, false, false); }); controller1.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(), android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true, - false); + false, false); waitUntilHandlersIdle(); assertNoStartingWindow(controller1.getAppWindowToken(mDisplayContent)); assertHasStartingWindow(controller2.getAppWindowToken(mDisplayContent)); |