Merge "remove the lock-use for prunePrintService in case blocking main thread" into oc-dev
diff --git a/cmds/am/src/com/android/commands/am/Instrument.java b/cmds/am/src/com/android/commands/am/Instrument.java
index 8eefd25..4966b43 100644
--- a/cmds/am/src/com/android/commands/am/Instrument.java
+++ b/cmds/am/src/com/android/commands/am/Instrument.java
@@ -382,6 +382,7 @@
oldAnims = mWm.getAnimationScales();
mWm.setAnimationScale(0, 0.0f);
mWm.setAnimationScale(1, 0.0f);
+ mWm.setAnimationScale(2, 0.0f);
}
// Figure out which component we are tring to do.
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 5fedc9e..c4f17fa 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -214,5 +214,7 @@
if (mapbase != MAP_FAILED) {
munmap((void *)mapbase, mapsize);
}
- return 0;
+
+ // b/36066697: Avoid running static destructors.
+ _exit(1);
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 24c144c..bc6e9cd 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -16,17 +16,9 @@
package android.app;
-import android.graphics.Rect;
-import android.view.ViewRootImpl.ActivityConfigCallback;
-import android.view.autofill.AutofillManager;
-import android.view.autofill.AutofillPopupWindow;
-import android.view.autofill.IAutofillWindowPresenter;
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.app.IVoiceInteractor;
-import com.android.internal.app.ToolbarActionBar;
-import com.android.internal.app.WindowDecorActionBar;
-import com.android.internal.policy.DecorView;
-import com.android.internal.policy.PhoneWindow;
+import static android.os.Build.VERSION_CODES.O;
+
+import static java.lang.Character.MIN_VALUE;
import android.annotation.CallSuper;
import android.annotation.DrawableRes;
@@ -62,6 +54,7 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.session.MediaController;
@@ -114,15 +107,26 @@
import android.view.ViewGroup.LayoutParams;
import android.view.ViewManager;
import android.view.ViewRootImpl;
+import android.view.ViewRootImpl.ActivityConfigCallback;
import android.view.Window;
import android.view.Window.WindowControllerCallback;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillPopupWindow;
+import android.view.autofill.IAutofillWindowPresenter;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.Toolbar;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.app.ToolbarActionBar;
+import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.policy.DecorView;
+import com.android.internal.policy.PhoneWindow;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -131,9 +135,6 @@
import java.util.HashMap;
import java.util.List;
-import static android.os.Build.VERSION_CODES.O;
-import static java.lang.Character.MIN_VALUE;
-
/**
* An activity is a single, focused thing that the user can do. Almost all
* activities interact with the user, so the Activity class takes care of
@@ -999,7 +1000,8 @@
}
if (savedInstanceState != null) {
mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false);
- mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID, View.NO_ID);
+ mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID,
+ View.LAST_APP_AUTOFILL_ID);
if (mAutoFillResetNeeded) {
getAutofillManager().onCreate(savedInstanceState);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 268a105b..1b25e65 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -256,28 +256,34 @@
@Override
public void setTheme(int resId) {
- if (mThemeResource != resId) {
- mThemeResource = resId;
- initializeTheme();
+ synchronized (mSync) {
+ if (mThemeResource != resId) {
+ mThemeResource = resId;
+ initializeTheme();
+ }
}
}
@Override
public int getThemeResId() {
- return mThemeResource;
+ synchronized (mSync) {
+ return mThemeResource;
+ }
}
@Override
public Resources.Theme getTheme() {
- if (mTheme != null) {
+ synchronized (mSync) {
+ if (mTheme != null) {
+ return mTheme;
+ }
+
+ mThemeResource = Resources.selectDefaultTheme(mThemeResource,
+ getOuterContext().getApplicationInfo().targetSdkVersion);
+ initializeTheme();
+
return mTheme;
}
-
- mThemeResource = Resources.selectDefaultTheme(mThemeResource,
- getOuterContext().getApplicationInfo().targetSdkVersion);
- initializeTheme();
-
- return mTheme;
}
private void initializeTheme() {
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 266fa7e..4e8277c 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -1051,6 +1051,9 @@
public void updateAutofillValue(AutofillValue value) {
mAutofillValue = value;
if (value.isText()) {
+ if (mText == null) {
+ mText = new ViewNodeText();
+ }
mText.mText = value.getTextValue();
}
}
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 67d56d5..dfd5996 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -208,6 +208,8 @@
if (wrapper == null) return;
stopAdvertisingSet(wrapper);
+
+ mLegacyAdvertisers.remove(callback);
}
}
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 9df315b..a90ee93 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -25,7 +25,6 @@
import android.app.Service;
import android.app.assist.AssistStructure;
import android.content.Intent;
-import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.IBinder;
import android.os.ICancellationSignal;
@@ -35,9 +34,6 @@
import com.android.internal.os.SomeArgs;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* Top-level service of the current autofill service for a given user.
*
@@ -192,6 +188,11 @@
* {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
* to notify the result of the request.
*
+ * <p><b>NOTE: </b>to retrieve the actual value of the field, the service should call
+ * {@link android.app.assist.AssistStructure.ViewNode#getAutofillValue()}; if it calls
+ * {@link android.app.assist.AssistStructure.ViewNode#getText()} or other methods, there is no
+ * guarantee such method will return the most recent value of the field.
+ *
* @param request the {@link SaveRequest request} to handle.
* See {@link FillResponse} for examples of multiple-sections requests.
* @param callback object used to notify the result of the request.
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index caadc36..cb98c88 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -72,6 +72,15 @@
* Creates a display event receiver.
*
* @param looper The looper to use when invoking callbacks.
+ */
+ public DisplayEventReceiver(Looper looper) {
+ this(looper, VSYNC_SOURCE_APP);
+ }
+
+ /**
+ * Creates a display event receiver.
+ *
+ * @param looper The looper to use when invoking callbacks.
* @param vsyncSource The source of the vsync tick. Must be on of the VSYNC_SOURCE_* values.
*/
public DisplayEventReceiver(Looper looper, int vsyncSource) {
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 5f55bdc..04fa637 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -224,6 +224,14 @@
* Constant for {@link #getActionMasked}: A movement has happened outside of the
* normal bounds of the UI element. This does not provide a full gesture,
* but only the initial location of the movement/touch.
+ * <p>
+ * Note: Because the location of any event will be outside the
+ * bounds of the view hierarchy, it will not get dispatched to
+ * any children of a ViewGroup by default. Therefore,
+ * movements with ACTION_OUTSIDE should be handled in either the
+ * root {@link View} or in the appropriate {@link Window.Callback}
+ * (e.g. {@link android.app.Activity} or {@link android.app.Dialog}).
+ * </p>
*/
public static final int ACTION_OUTSIDE = 4;
diff --git a/packages/SystemUI/res/layout/navigation_bar_window.xml b/packages/SystemUI/res/layout/navigation_bar_window.xml
index 051bf3a..6fa46d4 100644
--- a/packages/SystemUI/res/layout/navigation_bar_window.xml
+++ b/packages/SystemUI/res/layout/navigation_bar_window.xml
@@ -16,11 +16,11 @@
** limitations under the License.
*/
-->
-<FrameLayout
+<com.android.systemui.statusbar.phone.NavigationBarFrame
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/navigation_bar_frame"
android:layout_height="match_parent"
android:layout_width="match_parent">
-</FrameLayout>
+</com.android.systemui.statusbar.phone.NavigationBarFrame>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index 2d0fe6f..4d0e60d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -32,6 +32,7 @@
import com.android.systemui.R;
import com.android.systemui.plugins.qs.*;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView {
@@ -44,6 +45,7 @@
private String mAccessibilityClass;
private boolean mTileState;
private boolean mCollapsedView;
+ private boolean mClicked;
public QSTileBaseView(Context context, QSIconView icon) {
this(context, icon, false);
@@ -153,7 +155,11 @@
setContentDescription(state.contentDescription);
mAccessibilityClass = state.expandedAccessibilityClassName;
if (state instanceof QSTile.BooleanState) {
- mTileState = ((QSTile.BooleanState) state).value;
+ boolean newState = ((BooleanState) state).value;
+ if (mTileState != newState) {
+ mClicked = false;
+ mTileState = newState;
+ }
}
}
@@ -173,15 +179,22 @@
}
@Override
+ public boolean performClick() {
+ mClicked = true;
+ return super.performClick();
+ }
+
+ @Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
if (!TextUtils.isEmpty(mAccessibilityClass)) {
event.setClassName(mAccessibilityClass);
if (Switch.class.getName().equals(mAccessibilityClass)) {
+ boolean b = mClicked ? !mTileState : mTileState;
String label = getResources()
- .getString(!mTileState ? R.string.switch_bar_on : R.string.switch_bar_off);
+ .getString(b ? R.string.switch_bar_on : R.string.switch_bar_off);
event.setContentDescription(label);
- event.setChecked(!mTileState);
+ event.setChecked(b);
}
}
}
@@ -192,10 +205,11 @@
if (!TextUtils.isEmpty(mAccessibilityClass)) {
info.setClassName(mAccessibilityClass);
if (Switch.class.getName().equals(mAccessibilityClass)) {
+ boolean b = mClicked ? !mTileState : mTileState;
String label = getResources()
- .getString(mTileState ? R.string.switch_bar_on : R.string.switch_bar_off);
+ .getString(b ? R.string.switch_bar_on : R.string.switch_bar_off);
info.setText(label);
- info.setChecked(mTileState);
+ info.setChecked(b);
info.setCheckable(true);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 76f6e7d..f26afcc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -32,17 +32,16 @@
import com.android.settingslib.wifi.AccessPoint;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.R.string;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
-import com.android.systemui.qs.QSDetailItems;
-import com.android.systemui.qs.QSDetailItems.Item;
-import com.android.systemui.qs.QSHost;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.SignalState;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.qs.QSDetailItems;
+import com.android.systemui.qs.QSDetailItems.Item;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.SignalTileView;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
@@ -180,7 +179,7 @@
minimalContentDescription.append(removeDoubleQuotes(cb.enabledDesc));
}
}
- state.contentDescription = minimalContentDescription;
+ state.contentDescription = minimalContentDescription.toString();
state.dualLabelContentDescription = r.getString(
R.string.accessibility_quick_settings_open_settings, getTileLabel());
state.expandedAccessibilityClassName = Switch.class.getName();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFrame.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFrame.java
new file mode 100644
index 0000000..741f783
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFrame.java
@@ -0,0 +1,59 @@
+/*
+ * 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 android.view.MotionEvent.ACTION_OUTSIDE;
+
+import android.annotation.AttrRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.FrameLayout;
+
+import com.android.systemui.statusbar.policy.DeadZone;
+
+public class NavigationBarFrame extends FrameLayout {
+
+ private DeadZone mDeadZone = null;
+
+ public NavigationBarFrame(@NonNull Context context) {
+ super(context);
+ }
+
+ public NavigationBarFrame(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public NavigationBarFrame(@NonNull Context context, @Nullable AttributeSet attrs,
+ @AttrRes int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public void setDeadZone(@NonNull DeadZone deadZone) {
+ mDeadZone = deadZone;
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ if (event.getAction() == ACTION_OUTSIDE) {
+ if (mDeadZone != null) {
+ return mDeadZone.onTouchEvent(event);
+ }
+ }
+ return super.dispatchTouchEvent(event);
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 8d9d461..0557cb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -250,9 +250,6 @@
if (mGestureHelper.onTouchEvent(event)) {
return true;
}
- if (mDeadZone != null && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
- mDeadZone.poke(event);
- }
return super.onTouchEvent(event);
}
@@ -614,9 +611,8 @@
public void reorient() {
updateCurrentView();
- getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
-
mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
+ ((NavigationBarFrame) getRootView()).setDeadZone(mDeadZone);
mDeadZone.setDisplayRotation(mCurrentRotation);
// force the low profile & disabled states into compliance
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
index 4c879c6..13ee23f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
@@ -127,6 +127,7 @@
final int action = event.getAction();
if (action == MotionEvent.ACTION_OUTSIDE) {
poke(event);
+ return true;
} else if (action == MotionEvent.ACTION_DOWN) {
if (DEBUG) {
Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
@@ -158,7 +159,7 @@
return false;
}
- public void poke(MotionEvent event) {
+ private void poke(MotionEvent event) {
mLastPokeTime = event.getEventTime();
if (DEBUG)
Slog.v(TAG, "poked! size=" + getSize(mLastPokeTime));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index a120cec..4cc83f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -14,7 +14,6 @@
package com.android.systemui.statusbar.phone;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -33,17 +32,13 @@
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
-import com.android.systemui.utils.leaks.BaseLeakChecker;
import android.testing.TestableLooper.RunWithLooper;
-import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
@RunWith(AndroidTestingRunner.class)
@RunWithLooper(setAsMainLooper = true)
@@ -54,6 +49,10 @@
super(NavigationBarFragment.class);
}
+ protected void createRootView() {
+ mView = new NavigationBarFrame(mContext);
+ }
+
@Before
public void setup() {
mDependency.injectTestDependency(Dependency.BG_LOOPER, Looper.getMainLooper());
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 7de56fa..f379791 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2257,6 +2257,31 @@
return null;
}
+ /**
+ * Get next valid stack for launching provided activity in the system. This will search across
+ * displays and stacks in last-focused order for a focusable and visible stack, except those
+ * that are on a currently focused display.
+ *
+ * @param r The activity that is being launched.
+ * @param currentFocus The display that previously had focus and thus needs to be ignored when
+ * searching for the next candidate.
+ * @return Next valid {@link ActivityStack}, null if not found.
+ */
+ ActivityStack getNextValidLaunchStackLocked(@NonNull ActivityRecord r, int currentFocus) {
+ mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds);
+ for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
+ final int displayId = mTmpOrderedDisplayIds.get(i);
+ if (displayId == currentFocus) {
+ continue;
+ }
+ final ActivityStack stack = getValidLaunchStackOnDisplay(displayId, r);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
+ }
+
ActivityRecord getHomeActivity() {
return getHomeActivityForUser(mCurrentUser);
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index d74d1d6..c7ee149 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -2027,7 +2027,18 @@
return mSupervisor.mFocusedStack;
}
- if (mSourceDisplayId == DEFAULT_DISPLAY) {
+ if (mSourceDisplayId != DEFAULT_DISPLAY) {
+ // Try to put the activity in a stack on a secondary display.
+ stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
+ if (stack == null) {
+ // If source display is not suitable - look for topmost valid stack in the system.
+ if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
+ "computeStackFocus: Can't launch on mSourceDisplayId=" + mSourceDisplayId
+ + ", looking on all displays.");
+ stack = mSupervisor.getNextValidLaunchStackLocked(r, mSourceDisplayId);
+ }
+ }
+ if (stack == null) {
// We first try to put the task in the first dynamic stack on home display.
final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
@@ -2043,8 +2054,6 @@
bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
FULLSCREEN_WORKSPACE_STACK_ID;
stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
- } else {
- stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
}
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
+ r + " stackId=" + stack.mStackId);
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 5d3f6f7..107475f 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -438,7 +438,21 @@
switch (message.what) {
case MSG_TIMEOUT:
synchronized (mLock) {
- handleOpTimeoutLocked();
+ if (message.obj == mRunningCallback) {
+ handleOpTimeoutLocked();
+ } else {
+ JobCallback jc = (JobCallback)message.obj;
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("Ignoring timeout of no longer active job");
+ if (jc.mStoppedReason != null) {
+ sb.append(", stopped ");
+ TimeUtils.formatDuration(SystemClock.elapsedRealtime()
+ - jc.mStoppedTime, sb);
+ sb.append(" because: ");
+ sb.append(jc.mStoppedReason);
+ }
+ Slog.w(TAG, sb.toString());
+ }
}
break;
default:
@@ -621,7 +635,7 @@
private void handleOpTimeoutLocked() {
switch (mVerb) {
case VERB_BINDING:
- Slog.e(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() +
+ Slog.w(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() +
", dropping.");
closeAndCleanupJobLocked(false /* needsReschedule */, "timed out while binding");
break;
@@ -629,26 +643,28 @@
// Client unresponsive - wedged or failed to respond in time. We don't really
// know what happened so let's log it and notify the JobScheduler
// FINISHED/NO-RETRY.
- Slog.e(TAG, "No response from client for onStartJob '" +
- mRunningJob.toShortString());
+ Slog.w(TAG, "No response from client for onStartJob " +
+ mRunningJob != null ? mRunningJob.toShortString() : "<null>");
closeAndCleanupJobLocked(false /* needsReschedule */, "timed out while starting");
break;
case VERB_STOPPING:
// At least we got somewhere, so fail but ask the JobScheduler to reschedule.
- Slog.e(TAG, "No response from client for onStopJob, '" +
- mRunningJob.toShortString());
+ Slog.w(TAG, "No response from client for onStopJob " +
+ mRunningJob != null ? mRunningJob.toShortString() : "<null>");
closeAndCleanupJobLocked(true /* needsReschedule */, "timed out while stopping");
break;
case VERB_EXECUTING:
// Not an error - client ran out of time.
- Slog.i(TAG, "Client timed out while executing (no jobFinished received)." +
- " sending onStop. " + mRunningJob.toShortString());
+ Slog.i(TAG, "Client timed out while executing (no jobFinished received), " +
+ "sending onStop: " +
+ mRunningJob != null ? mRunningJob.toShortString() : "<null>");
mParams.setStopReason(JobParameters.REASON_TIMEOUT);
sendStopMessageLocked("timeout while executing");
break;
default:
Slog.e(TAG, "Handling timeout for an invalid job state: " +
- mRunningJob.toShortString() + ", dropping.");
+ mRunningJob != null ? mRunningJob.toShortString() : "<null>"
+ + ", dropping.");
closeAndCleanupJobLocked(false /* needsReschedule */, "invalid timeout");
}
}
@@ -749,7 +765,7 @@
mRunningJob.getServiceComponent().getShortClassName() + "' jId: " +
mParams.getJobId() + ", in " + (timeoutMillis / 1000) + " s");
}
- Message m = mCallbackHandler.obtainMessage(MSG_TIMEOUT);
+ Message m = mCallbackHandler.obtainMessage(MSG_TIMEOUT, mRunningCallback);
mCallbackHandler.sendMessageDelayed(m, timeoutMillis);
mTimeoutElapsed = SystemClock.elapsedRealtime() + timeoutMillis;
}
diff --git a/tests/testables/src/android/testing/BaseFragmentTest.java b/tests/testables/src/android/testing/BaseFragmentTest.java
index 32ee091..f1e4d21 100644
--- a/tests/testables/src/android/testing/BaseFragmentTest.java
+++ b/tests/testables/src/android/testing/BaseFragmentTest.java
@@ -50,7 +50,7 @@
private static final int VIEW_ID = 42;
private final Class<? extends Fragment> mCls;
private Handler mHandler;
- private FrameLayout mView;
+ protected FrameLayout mView;
protected FragmentController mFragments;
protected Fragment mFragment;
@@ -61,9 +61,13 @@
mCls = cls;
}
+ protected void createRootView() {
+ mView = new FrameLayout(mContext);
+ }
+
@Before
public void setupFragment() throws Exception {
- mView = new FrameLayout(mContext);
+ createRootView();
mView.setId(VIEW_ID);
assertNotNull("BaseFragmentTest must be tagged with @RunWithLooper",