summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2022-03-14 07:48:21 -0700
committerLinux Build Service Account <lnxbuild@localhost>2022-03-14 07:48:21 -0700
commitb0f43f1535ac4c78fdde99c4805dfd826c2994af (patch)
tree20f7b9cdb57d8604704d41f58a38fe522b488ebb
parent39d5e28517aa09aaf508bb28e235746b952e2b9a (diff)
parentf11eace41803d244226112969a19430fa405039e (diff)
Merge f11eace41803d244226112969a19430fa405039e on remote branch
Change-Id: Ic2011549df66fcb29468779bc8f016d718c35fb3
-rw-r--r--core/java/android/app/ActivityThread.java27
-rw-r--r--core/java/android/app/ContextImpl.java59
-rw-r--r--core/java/android/util/BoostFramework.java2
-rw-r--r--core/java/android/view/IWindowManager.aidl17
-rw-r--r--core/java/android/window/WindowContextController.java38
-rw-r--r--core/java/android/window/WindowTokenClient.java96
-rw-r--r--core/tests/coretests/src/android/window/WindowContextControllerTest.java15
-rw-r--r--packages/SystemUI/AndroidManifest.xml1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java49
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodMenuController.java2
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java8
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java18
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java11
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowContextListenerController.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java36
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java37
19 files changed, 332 insertions, 106 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 8f6f552ad1ff..5c942d217fc4 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -30,6 +30,7 @@ import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE;
import static android.content.ContentResolver.DEPRECATE_DATA_COLUMNS;
import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
@@ -313,7 +314,7 @@ public final class ActivityThread extends ClientTransactionHandler
@UnsupportedAppUsage
private ContextImpl mSystemContext;
- private ContextImpl mSystemUiContext;
+ private final SparseArray<ContextImpl> mDisplaySystemUiContexts = new SparseArray<>();
@UnsupportedAppUsage
static volatile IPackageManager sPackageManager;
@@ -2610,22 +2611,26 @@ public final class ActivityThread extends ClientTransactionHandler
}
@Override
+ @NonNull
public ContextImpl getSystemUiContext() {
- synchronized (this) {
- if (mSystemUiContext == null) {
- mSystemUiContext = ContextImpl.createSystemUiContext(getSystemContext());
- }
- return mSystemUiContext;
- }
+ return getSystemUiContext(DEFAULT_DISPLAY);
}
/**
- * Create the context instance base on system resources & display information which used for UI.
+ * Gets the context instance base on system resources & display information which used for UI.
* @param displayId The ID of the display where the UI is shown.
* @see ContextImpl#createSystemUiContext(ContextImpl, int)
*/
- public ContextImpl createSystemUiContext(int displayId) {
- return ContextImpl.createSystemUiContext(getSystemUiContext(), displayId);
+ @NonNull
+ public ContextImpl getSystemUiContext(int displayId) {
+ synchronized (this) {
+ ContextImpl systemUiContext = mDisplaySystemUiContexts.get(displayId);
+ if (systemUiContext == null) {
+ systemUiContext = ContextImpl.createSystemUiContext(getSystemContext(), displayId);
+ mDisplaySystemUiContexts.put(displayId, systemUiContext);
+ }
+ return systemUiContext;
+ }
}
public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
@@ -3740,7 +3745,7 @@ public final class ActivityThread extends ClientTransactionHandler
if (pkgName != null && !pkgName.isEmpty()
&& r.packageInfo.mPackageName.contains(pkgName)) {
for (int id : dm.getDisplayIds()) {
- if (id != Display.DEFAULT_DISPLAY) {
+ if (id != DEFAULT_DISPLAY) {
Display display =
dm.getCompatibleDisplay(id, appContext.getResources());
appContext = (ContextImpl) appContext.createDisplayContext(display);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 1397f5ea10dc..1093baade42c 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2618,7 +2618,10 @@ class ContextImpl extends Context {
overrideConfig, display.getDisplayAdjustments().getCompatibilityInfo(),
mResources.getLoaders()));
context.mDisplay = display;
- context.mContextType = CONTEXT_TYPE_DISPLAY_CONTEXT;
+ // Inherit context type if the container is from System or System UI context to bypass
+ // UI context check.
+ context.mContextType = mContextType == CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI
+ ? CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI : CONTEXT_TYPE_DISPLAY_CONTEXT;
// Display contexts and any context derived from a display context should always override
// the display that would otherwise be inherited from mToken (or the global configuration if
// mToken is null).
@@ -2671,7 +2674,8 @@ class ContextImpl extends Context {
// Step 2. Create the base context of the window context, it will also create a Resources
// associated with the WindowTokenClient and set the token to the base context.
- final ContextImpl windowContextBase = createWindowContextBase(windowTokenClient, display);
+ final ContextImpl windowContextBase = createWindowContextBase(windowTokenClient,
+ display.getDisplayId());
// Step 3. Create a WindowContext instance and set it as the outer context of the base
// context to make the service obtained by #getSystemService(String) able to query
@@ -2696,9 +2700,7 @@ class ContextImpl extends Context {
if (display == null) {
throw new IllegalArgumentException("Display must not be null");
}
- final ContextImpl tokenContext = createWindowContextBase(token, display);
- tokenContext.setResources(createWindowContextResources(tokenContext));
- return tokenContext;
+ return createWindowContextBase(token, display.getDisplayId());
}
/**
@@ -2706,13 +2708,13 @@ class ContextImpl extends Context {
* window.
*
* @param token The token to associate with {@link Resources}
- * @param display The {@link Display} to associate with.
+ * @param displayId The ID of {@link Display} to associate with.
*
* @see #createWindowContext(Display, int, Bundle)
* @see #createTokenContext(IBinder, Display)
*/
@UiContext
- ContextImpl createWindowContextBase(@NonNull IBinder token, @NonNull Display display) {
+ ContextImpl createWindowContextBase(@NonNull IBinder token, int displayId) {
ContextImpl baseContext = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
mAttributionSource.getAttributionTag(),
mAttributionSource.getNext(),
@@ -2726,8 +2728,8 @@ class ContextImpl extends Context {
baseContext.setResources(windowContextResources);
// Associate the display with window context resources so that configuration update from
// the server side will also apply to the display's metrics.
- baseContext.mDisplay = ResourcesManager.getInstance()
- .getAdjustedDisplay(display.getDisplayId(), windowContextResources);
+ baseContext.mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(displayId,
+ windowContextResources);
return baseContext;
}
@@ -2963,6 +2965,18 @@ class ContextImpl extends Context {
mContentCaptureOptions = options;
}
+ @Override
+ protected void finalize() throws Throwable {
+ // If mToken is a WindowTokenClient, the Context is usually associated with a
+ // WindowContainer. We should detach from WindowContainer when the Context is finalized
+ // if this Context is not a WindowContext. WindowContext finalization is handled in
+ // WindowContext class.
+ if (mToken instanceof WindowTokenClient && mContextType != CONTEXT_TYPE_WINDOW_CONTEXT) {
+ ((WindowTokenClient) mToken).detachFromWindowContainerIfNeeded();
+ }
+ super.finalize();
+ }
+
@UnsupportedAppUsage
static ContextImpl createSystemContext(ActivityThread mainThread) {
LoadedApk packageInfo = new LoadedApk(mainThread);
@@ -2983,22 +2997,13 @@ class ContextImpl extends Context {
* @param displayId The ID of the display where the UI is shown.
*/
static ContextImpl createSystemUiContext(ContextImpl systemContext, int displayId) {
- final LoadedApk packageInfo = systemContext.mPackageInfo;
- ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo,
- ContextParams.EMPTY, null, null, null, null, null, 0, null, null);
- context.setResources(createResources(null, packageInfo, null, displayId, null,
- packageInfo.getCompatibilityInfo(), null));
- context.updateDisplay(displayId);
+ final WindowTokenClient token = new WindowTokenClient();
+ final ContextImpl context = systemContext.createWindowContextBase(token, displayId);
+ token.attachContext(context);
+ token.attachToDisplayContent(displayId);
context.mContextType = CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI;
- return context;
- }
- /**
- * The overloaded method of {@link #createSystemUiContext(ContextImpl, int)}.
- * Uses {@Code Display.DEFAULT_DISPLAY} as the target display.
- */
- static ContextImpl createSystemUiContext(ContextImpl systemContext) {
- return createSystemUiContext(systemContext, Display.DEFAULT_DISPLAY);
+ return context;
}
@UnsupportedAppUsage
@@ -3212,7 +3217,13 @@ class ContextImpl extends Context {
@Override
public IBinder getWindowContextToken() {
- return mContextType == CONTEXT_TYPE_WINDOW_CONTEXT ? mToken : null;
+ switch (mContextType) {
+ case CONTEXT_TYPE_WINDOW_CONTEXT:
+ case CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI:
+ return mToken;
+ default:
+ return null;
+ }
}
private void checkMode(int mode) {
diff --git a/core/java/android/util/BoostFramework.java b/core/java/android/util/BoostFramework.java
index 26964103132d..ee29434f55ca 100644
--- a/core/java/android/util/BoostFramework.java
+++ b/core/java/android/util/BoostFramework.java
@@ -99,6 +99,8 @@ public class BoostFramework {
//perf events
public static final int VENDOR_HINT_FIRST_DRAW = 0x00001042;
public static final int VENDOR_HINT_TAP_EVENT = 0x00001043;
+ public static final int VENDOR_HINT_DRAG_START = 0x00001051;
+ public static final int VENDOR_HINT_DRAG_END = 0x00001052;
//feedback hints
public static final int VENDOR_FEEDBACK_WORKLOAD_TYPE = 0x00001601;
public static final int VENDOR_FEEDBACK_LAUNCH_END_POINT = 0x00001602;
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 19343acc438a..9000fd00e851 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -843,6 +843,23 @@ interface IWindowManager
void attachWindowContextToWindowToken(IBinder clientToken, IBinder token);
/**
+ * Attaches a {@code clientToken} to associate with DisplayContent.
+ * <p>
+ * Note that this API should be invoked after calling
+ * {@link android.window.WindowTokenClient#attachContext(Context)}
+ * </p>
+ *
+ * @param clientToken {@link android.window.WindowContext#getWindowContextToken()
+ * the WindowContext's token}
+ * @param displayId The display associated with the window context
+ *
+ * @return the DisplayContent's {@link android.app.res.Configuration} if the Context is
+ * attached to the DisplayContent successfully. {@code null}, otherwise.
+ * @throws android.view.WindowManager.InvalidDisplayException if the display ID is invalid
+ */
+ Configuration attachToDisplayContent(IBinder clientToken, int displayId);
+
+ /**
* Detaches {@link android.window.WindowContext} from the window manager node it's currently
* attached to. It is no-op if the WindowContext is not attached to a window manager node.
*
diff --git a/core/java/android/window/WindowContextController.java b/core/java/android/window/WindowContextController.java
index 505b45008663..17b675f93f86 100644
--- a/core/java/android/window/WindowContextController.java
+++ b/core/java/android/window/WindowContextController.java
@@ -19,13 +19,10 @@ package android.window;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
-import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
-import android.os.RemoteException;
import android.view.IWindowManager;
import android.view.WindowManager.LayoutParams.WindowType;
-import android.view.WindowManagerGlobal;
import com.android.internal.annotations.VisibleForTesting;
@@ -38,7 +35,6 @@ import com.android.internal.annotations.VisibleForTesting;
* @hide
*/
public class WindowContextController {
- private final IWindowManager mWms;
/**
* {@code true} to indicate that the {@code mToken} is associated with a
* {@link com.android.server.wm.DisplayArea}. Note that {@code mToken} is able to attach a
@@ -56,14 +52,7 @@ public class WindowContextController {
* {@link Context#getWindowContextToken()}.
*/
public WindowContextController(@NonNull WindowTokenClient token) {
- this(token, WindowManagerGlobal.getWindowManagerService());
- }
-
- /** Used for test only. DO NOT USE it in production code. */
- @VisibleForTesting
- public WindowContextController(@NonNull WindowTokenClient token, IWindowManager mockWms) {
mToken = token;
- mWms = mockWms;
}
/**
@@ -80,18 +69,7 @@ public class WindowContextController {
throw new IllegalStateException("A Window Context can be only attached to "
+ "a DisplayArea once.");
}
- try {
- final Configuration configuration = mWms.attachWindowContextToDisplayArea(mToken, type,
- displayId, options);
- if (configuration != null) {
- mAttachedToDisplayArea = true;
- // Send the DisplayArea's configuration to WindowContext directly instead of
- // waiting for dispatching from WMS.
- mToken.onConfigurationChanged(configuration, displayId);
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ mAttachedToDisplayArea = mToken.attachToDisplayArea(type, displayId, options);
}
/**
@@ -119,22 +97,14 @@ public class WindowContextController {
throw new IllegalStateException("The Window Context should have been attached"
+ " to a DisplayArea.");
}
- try {
- mWms.attachWindowContextToWindowToken(mToken, windowToken);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ mToken.attachToWindowToken(windowToken);
}
/** Detaches the window context from the node it's currently associated with. */
public void detachIfNeeded() {
if (mAttachedToDisplayArea) {
- try {
- mWms.detachWindowContextFromWindowContainer(mToken);
- mAttachedToDisplayArea = false;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ mToken.detachFromWindowContainerIfNeeded();
+ mAttachedToDisplayArea = false;
}
}
}
diff --git a/core/java/android/window/WindowTokenClient.java b/core/java/android/window/WindowTokenClient.java
index 4dcd2e74a53f..876272b2b87e 100644
--- a/core/java/android/window/WindowTokenClient.java
+++ b/core/java/android/window/WindowTokenClient.java
@@ -16,6 +16,7 @@
package android.window;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityThread;
import android.app.IWindowToken;
import android.app.ResourcesManager;
@@ -23,6 +24,11 @@ import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.IWindowManager;
+import android.view.WindowManager.LayoutParams.WindowType;
+import android.view.WindowManagerGlobal;
import com.android.internal.annotations.VisibleForTesting;
@@ -48,6 +54,14 @@ public class WindowTokenClient extends IWindowToken.Stub {
private final ResourcesManager mResourcesManager = ResourcesManager.getInstance();
+ private IWindowManager mWms;
+
+ private final Configuration mConfiguration = new Configuration();
+
+ private boolean mShouldDumpConfigForIme;
+
+ private boolean mAttachToWindowContainer;
+
/**
* Attaches {@code context} to this {@link WindowTokenClient}. Each {@link WindowTokenClient}
* can only attach one {@link Context}.
@@ -66,6 +80,88 @@ public class WindowTokenClient extends IWindowToken.Stub {
}
/**
+ * Attaches this {@link WindowTokenClient} to a {@link com.android.server.wm.DisplayArea}.
+ *
+ * @param type The window type of the {@link WindowContext}
+ * @param displayId The {@link Context#getDisplayId() ID of display} to associate with
+ * @param options The window context launched option
+ * @return {@code true} if attaching successfully.
+ */
+ public boolean attachToDisplayArea(@WindowType int type, int displayId,
+ @Nullable Bundle options) {
+ try {
+ final Configuration configuration = getWindowManagerService()
+ .attachWindowContextToDisplayArea(this, type, displayId, options);
+ if (configuration == null) {
+ return false;
+ }
+ onConfigurationChanged(configuration, displayId);
+ mAttachToWindowContainer = true;
+ return true;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Attaches this {@link WindowTokenClient} to a {@code DisplayContent}.
+ *
+ * @param displayId The {@link Context#getDisplayId() ID of display} to associate with
+ * @return {@code true} if attaching successfully.
+ */
+ public boolean attachToDisplayContent(int displayId) {
+ final IWindowManager wms = getWindowManagerService();
+ // #createSystemUiContext may call this method before WindowManagerService is initialized.
+ if (wms == null) {
+ return false;
+ }
+ try {
+ final Configuration configuration = wms.attachToDisplayContent(this, displayId);
+ if (configuration == null) {
+ return false;
+ }
+ onConfigurationChanged(configuration, displayId);
+ mAttachToWindowContainer = true;
+ return true;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Attaches this {@link WindowTokenClient} to a {@code windowToken}.
+ *
+ * @param windowToken the window token to associated with
+ */
+ public void attachToWindowToken(IBinder windowToken) {
+ try {
+ getWindowManagerService().attachWindowContextToWindowToken(this, windowToken);
+ mAttachToWindowContainer = true;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** Detaches this {@link WindowTokenClient} from associated WindowContainer if there's one. */
+ public void detachFromWindowContainerIfNeeded() {
+ if (!mAttachToWindowContainer) {
+ return;
+ }
+ try {
+ getWindowManagerService().detachWindowContextFromWindowContainer(this);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private IWindowManager getWindowManagerService() {
+ if (mWms == null) {
+ mWms = WindowManagerGlobal.getWindowManagerService();
+ }
+ return mWms;
+ }
+
+ /**
* Called when {@link Configuration} updates from the server side receive.
*
* @param newConfig the updated {@link Configuration}
diff --git a/core/tests/coretests/src/android/window/WindowContextControllerTest.java b/core/tests/coretests/src/android/window/WindowContextControllerTest.java
index 073e46827bbb..d7b36a8d7067 100644
--- a/core/tests/coretests/src/android/window/WindowContextControllerTest.java
+++ b/core/tests/coretests/src/android/window/WindowContextControllerTest.java
@@ -23,16 +23,13 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
-import android.content.res.Configuration;
import android.os.Binder;
import android.platform.test.annotations.Presubmit;
-import android.view.IWindowManager;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -58,17 +55,14 @@ import org.mockito.MockitoAnnotations;
public class WindowContextControllerTest {
private WindowContextController mController;
@Mock
- private IWindowManager mMockWms;
- @Mock
private WindowTokenClient mMockToken;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mController = new WindowContextController(mMockToken, mMockWms);
+ mController = new WindowContextController(mMockToken);
doNothing().when(mMockToken).onConfigurationChanged(any(), anyInt());
- doReturn(new Configuration()).when(mMockWms).attachWindowContextToDisplayArea(any(),
- anyInt(), anyInt(), any());
+ doReturn(true).when(mMockToken).attachToDisplayArea(anyInt(), anyInt(), any());
}
@Test(expected = IllegalStateException.class)
@@ -80,10 +74,10 @@ public class WindowContextControllerTest {
}
@Test
- public void testDetachIfNeeded_NotAttachedYet_DoNothing() throws Exception {
+ public void testDetachIfNeeded_NotAttachedYet_DoNothing() {
mController.detachIfNeeded();
- verify(mMockWms, never()).detachWindowContextFromWindowContainer(any());
+ verify(mMockToken, never()).detachFromWindowContainerIfNeeded();
}
@Test
@@ -92,7 +86,6 @@ public class WindowContextControllerTest {
null /* options */);
assertThat(mController.mAttachedToDisplayArea).isTrue();
- verify(mMockToken).onConfigurationChanged(any(), eq(DEFAULT_DISPLAY));
mController.detachIfNeeded();
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 92a711513c1a..d8027b449a54 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -84,7 +84,6 @@
<uses-permission android:name="android.permission.CONTROL_VPN" />
<uses-permission android:name="android.permission.PEERS_MAC_ADDRESS"/>
<uses-permission android:name="android.permission.READ_WIFI_CREDENTIAL"/>
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- Physical hardware -->
<uses-permission android:name="android.permission.MANAGE_USB" />
<uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS" />
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
index 7064b8e22f2a..1d6dce9b1af8 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
@@ -37,6 +37,7 @@ import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.keyguard.dagger.KeyguardBouncerScope;
+import com.android.systemui.R;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -176,6 +177,9 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
}
private void requestCellInfoUpdate(){
+ if(!getContext().getResources().getBoolean(R.bool.kg_hide_emgcy_btn_when_oos)) {
+ return;
+ }
TelephonyManager tmWithoutSim = mTelephonyManager
.createForSubscriptionId(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
try {
@@ -195,7 +199,7 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
updateEmergencyCallButton();
}
});
- } catch (IllegalStateException exception) {
+ } catch (Exception exception) {
Log.e(LOG_TAG, "Fail to call TelephonyManager.requestCellInfoUpdate ", exception);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index d0271f72153e..62f50cb2f5c7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -378,7 +378,8 @@ public class InternetDialog extends SystemUIDialog implements
private void setMobileDataLayout(boolean isCarrierNetworkConnected) {
if (mInternetDialogController.isAirplaneModeEnabled()
- || !mInternetDialogController.hasCarrier()) {
+ || !mInternetDialogController.hasCarrier()
+ || mInternetDialogController.isInCallOnNonDds()) {
mMobileNetworkLayout.setVisibility(View.GONE);
} else {
mMobileDataToggle.setChecked(mInternetDialogController.isMobileDataEnabled());
@@ -619,6 +620,11 @@ public class InternetDialog extends SystemUIDialog implements
}
@Override
+ public void onNonDdsCallStateChanged() {
+ mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+ }
+
+ @Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (mAlertDialog != null && !mAlertDialog.isShowing()) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index 67e34113bebb..2bbb3dfd2394 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -89,6 +89,7 @@ import com.android.wifitrackerlib.WifiEntry;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
@@ -152,6 +153,10 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
private ToastFactory mToastFactory;
private SignalDrawable mSignalDrawable;
private LocationController mLocationController;
+ private int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ private int mVoiceCallState = TelephonyManager.CALL_STATE_IDLE;
+ private HashMap<TelephonyManager, NonDdsTelephonyCallback> mNonDdsCallbacks =
+ new HashMap<>();
@VisibleForTesting
static final float TOAST_PARAMS_HORIZONTAL_WEIGHT = 1.0f;
@@ -247,6 +252,7 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor,
mOnSubscriptionsChangedListener);
mDefaultDataSubId = getDefaultDataSubscriptionId();
+ mActiveDataSubId = mDefaultDataSubId;
if (DEBUG) {
Log.d(TAG, "Init, SubId: " + mDefaultDataSubId);
}
@@ -254,6 +260,19 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId);
mInternetTelephonyCallback = new InternetTelephonyCallback();
mTelephonyManager.registerTelephonyCallback(mExecutor, mInternetTelephonyCallback);
+ final List<SubscriptionInfo> subscriptions =
+ mSubscriptionManager.getActiveSubscriptionInfoList();
+ if (subscriptions != null) {
+ NonDdsTelephonyCallback nonDdscallback = new NonDdsTelephonyCallback();
+ for (SubscriptionInfo info : subscriptions) {
+ if (mDefaultDataSubId != info.getSubscriptionId()) {
+ TelephonyManager tm =
+ mTelephonyManager.createForSubscriptionId(info.getSubscriptionId());
+ tm.registerTelephonyCallback(mExecutor, nonDdscallback);
+ mNonDdsCallbacks.put(tm, nonDdscallback);
+ }
+ }
+ }
// Listen the connectivity changes
mConnectivityManager.registerDefaultNetworkCallback(mConnectivityManagerNetworkCallback);
mCanConfigWifi = canConfigWifi;
@@ -271,6 +290,11 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
mAccessPointController.removeAccessPointCallback(this);
mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateCallback);
mConnectivityManager.unregisterNetworkCallback(mConnectivityManagerNetworkCallback);
+ for (Map.Entry<TelephonyManager, NonDdsTelephonyCallback> entry
+ : mNonDdsCallbacks.entrySet()) {
+ entry.getKey().unregisterTelephonyCallback(entry.getValue());
+ }
+ mNonDdsCallbacks.clear();
}
@VisibleForTesting
@@ -751,6 +775,11 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
return !mKeyguardStateController.isUnlocked();
}
+ public boolean isInCallOnNonDds() {
+ return mDefaultDataSubId != mActiveDataSubId
+ && mVoiceCallState != TelephonyManager.CALL_STATE_IDLE;
+ }
+
boolean activeNetworkIsCellular() {
if (mConnectivityManager == null) {
if (DEBUG) {
@@ -904,7 +933,8 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
TelephonyCallback.DisplayInfoListener,
TelephonyCallback.ServiceStateListener,
TelephonyCallback.SignalStrengthsListener,
- TelephonyCallback.UserMobileDataStateListener {
+ TelephonyCallback.UserMobileDataStateListener,
+ TelephonyCallback.ActiveDataSubscriptionIdListener {
@Override
public void onServiceStateChanged(@NonNull ServiceState serviceState) {
@@ -931,6 +961,12 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
public void onUserMobileDataStateChanged(boolean enabled) {
mCallback.onUserMobileDataStateChanged(enabled);
}
+
+ @Override
+ public void onActiveDataSubscriptionIdChanged(int subId) {
+ mActiveDataSubId = subId;
+ mCallback.onNonDdsCallStateChanged();
+ }
}
private class InternetOnSubscriptionChangedListener
@@ -967,6 +1003,15 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
}
}
+ private class NonDdsTelephonyCallback extends TelephonyCallback implements
+ TelephonyCallback.CallStateListener {
+ @Override
+ public void onCallStateChanged(int state) {
+ mVoiceCallState = state;
+ mCallback.onNonDdsCallStateChanged();
+ }
+ }
+
/**
* Return {@code true} If the Ethernet exists
*/
@@ -1043,6 +1088,8 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
void onAccessPointsChanged(@Nullable List<WifiEntry> wifiEntries,
@Nullable WifiEntry connectedEntry);
+
+ void onNonDdsCallStateChanged();
}
void makeOverlayToast(int stringId) {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
index 73baf79ea4b1..82b34c35cfd2 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
@@ -223,7 +223,7 @@ public class InputMethodMenuController {
public Context getSettingsContext(int displayId) {
if (mSettingsContext == null || mSettingsContext.getDisplayId() != displayId) {
final Context systemUiContext = ActivityThread.currentActivityThread()
- .createSystemUiContext(displayId);
+ .getSystemUiContext(displayId);
final Context windowContext = systemUiContext.createWindowContext(
WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG, null /* options */);
mSettingsContext = new ContextThemeWrapper(
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 9335846e7805..8a9d5d438a47 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -34,6 +34,7 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.os.Build.VERSION_CODES.N;
+import static android.os.Process.SYSTEM_UID;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static android.util.RotationUtils.deltaRotation;
@@ -63,6 +64,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN;
@@ -4813,6 +4815,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
reconfigureDisplayLocked();
onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
mWmService.mDisplayNotificationController.dispatchDisplayAdded(this);
+ // Attach the SystemUiContext to this DisplayContent the get latest configuration.
+ // Note that the SystemUiContext will be removed automatically if this DisplayContent
+ // is detached.
+ mWmService.mWindowContextListenerController.registerWindowContainerListener(
+ getDisplayUiContext().getWindowContextToken(), this, SYSTEM_UID,
+ INVALID_WINDOW_TYPE, null /* options */);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 05356f54b61f..03b5478421cf 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -226,6 +226,7 @@ public class DisplayPolicy {
private final ScreenshotHelper mScreenshotHelper;
private static boolean SCROLL_BOOST_SS_ENABLE = false;
+ private static boolean DRAG_PLH_ENABLE = false;
private static boolean isLowRAM = false;
/*
@@ -475,7 +476,7 @@ public class DisplayPolicy {
: service.mContext.createDisplayContext(displayContent.getDisplay());
mUiContext = displayContent.isDefaultDisplay ? service.mAtmService.mUiContext
: service.mAtmService.mSystemThread
- .createSystemUiContext(displayContent.getDisplayId());
+ .getSystemUiContext(displayContent.getDisplayId());
mDisplayContent = displayContent;
mLock = service.getWindowManagerLock();
@@ -496,8 +497,10 @@ public class DisplayPolicy {
mScreenOnFully = true;
}
- if (mPerf != null)
- SCROLL_BOOST_SS_ENABLE = Boolean.parseBoolean(mPerf.perfGetProp("vendor.perf.gestureflingboost.enable", "false"));
+ if (mPerf != null) {
+ SCROLL_BOOST_SS_ENABLE = Boolean.parseBoolean(mPerf.perfGetProp("vendor.perf.gestureflingboost.enable", "false"));
+ DRAG_PLH_ENABLE = Boolean.parseBoolean(mPerf.perfGetProp("ro.vendor.perf.dplh", "false"));
+ }
isLowRAM = SystemProperties.getBoolean("ro.config.low_ram", false);
final Looper looper = UiThread.getHandler().getLooper();
@@ -649,9 +652,15 @@ public class DisplayPolicy {
}
isGame = isTopAppGame(currentPackage, mPerfBoostDrag);
if (!isGame && started) {
+ if (DRAG_PLH_ENABLE) {
+ mPerfBoostDrag.perfEvent(BoostFramework.VENDOR_HINT_DRAG_START, currentPackage);
+ }
mPerfBoostDrag.perfHint(BoostFramework.VENDOR_HINT_DRAG_BOOST,
currentPackage, -1, 1);
} else {
+ if (DRAG_PLH_ENABLE) {
+ mPerfBoostDrag.perfEvent(BoostFramework.VENDOR_HINT_DRAG_END, currentPackage);
+ }
mPerfBoostDrag.perfLockRelease();
}
}
@@ -2254,7 +2263,8 @@ public class DisplayPolicy {
// user's package info (see ContextImpl.createDisplayContext)
final LoadedApk pi = ActivityThread.currentActivityThread().getPackageInfo(
uiContext.getPackageName(), null, 0, userId);
- mCurrentUserResources = ResourcesManager.getInstance().getResources(null,
+ mCurrentUserResources = ResourcesManager.getInstance().getResources(
+ uiContext.getWindowContextToken(),
pi.getResDir(),
null /* splitResDirs */,
pi.getOverlayDirs(),
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index a9b37c08adfe..9f69fd933c16 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -247,6 +247,13 @@ public class DisplayRotation {
"org.codeaurora.intent.action.WIFI_DISPLAY_VIDEO";
/**
+ * Broadcast Permission for Wifi Display
+ */
+
+ private static final String WIFI_DISPLAY_PERMISSION =
+ "com.qualcomm.permission.wfd.QC_WFD";
+
+ /**
* Wifi Display specific variables
*/
private boolean mWifiDisplayConnected = false;
@@ -319,7 +326,9 @@ public class DisplayRotation {
false/* forceRelayout */);
}
}
- }, new IntentFilter(ACTION_WIFI_DISPLAY_VIDEO), null, UiThread.getHandler());
+ }, new IntentFilter(ACTION_WIFI_DISPLAY_VIDEO),
+ WIFI_DISPLAY_PERMISSION,
+ UiThread.getHandler());
}
};
t.start();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index e159bfbf1811..6844656b6e09 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2659,7 +2659,7 @@ public class RootWindowContainer extends WindowContainer<DisplayContent>
// starts. Instead, we expect home activities to be launched when the system is ready
// (ActivityManagerService#systemReady).
if (mService.isBooted() || mService.isBooting()) {
- startSystemDecorations(display.mDisplayContent);
+ startSystemDecorations(display);
}
}
}
diff --git a/services/core/java/com/android/server/wm/WindowContextListenerController.java b/services/core/java/com/android/server/wm/WindowContextListenerController.java
index bc530416c8cd..86e356a876b5 100644
--- a/services/core/java/com/android/server/wm/WindowContextListenerController.java
+++ b/services/core/java/com/android/server/wm/WindowContextListenerController.java
@@ -45,7 +45,7 @@ import java.util.Objects;
*
* <ul>
* <li>When a {@link WindowContext} is created, it registers the listener via
- * {@link WindowManagerService#registerWindowContextListener(IBinder, int, int, Bundle)}
+ * {@link WindowManagerService#attachWindowContextToDisplayArea(IBinder, int, int, Bundle)}
* automatically.</li>
* <li>When the {@link WindowContext} adds the first window to the screen via
* {@link android.view.WindowManager#addView(View, android.view.ViewGroup.LayoutParams)},
@@ -53,7 +53,7 @@ import java.util.Objects;
* to corresponding {@link WindowToken} via this controller.</li>
* <li>When the {@link WindowContext} is GCed, it unregisters the previously
* registered listener via
- * {@link WindowManagerService#unregisterWindowContextListener(IBinder)}.
+ * {@link WindowManagerService#detachWindowContextFromWindowContainer(IBinder)}.
* {@link WindowManagerService} is also responsible for removing the
* {@link WindowContext} created {@link WindowToken}.</li>
* </ul>
@@ -68,7 +68,7 @@ class WindowContextListenerController {
/**
* Registers the listener to a {@code container} which is associated with
- * a {@code clientToken}, which is a {@link android.app.WindowContext} representation. If the
+ * a {@code clientToken}, which is a {@link android.window.WindowContext} representation. If the
* listener associated with {@code clientToken} hasn't been initialized yet, create one
* {@link WindowContextListenerImpl}. Otherwise, the listener associated with
* {@code clientToken} switches to listen to the {@code container}.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1289ca3804e6..45e833e84789 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2723,6 +2723,9 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public Configuration attachWindowContextToDisplayArea(IBinder clientToken, int
type, int displayId, Bundle options) {
+ if (clientToken == null) {
+ throw new IllegalArgumentException("clientToken must not be null!");
+ }
final boolean callerCanManageAppTokens = checkCallingPermission(MANAGE_APP_TOKENS,
"attachWindowContextToDisplayArea", false /* printLog */);
final int callingUid = Binder.getCallingUid();
@@ -2813,6 +2816,39 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ @Override
+ public Configuration attachToDisplayContent(IBinder clientToken, int displayId) {
+ if (clientToken == null) {
+ throw new IllegalArgumentException("clientToken must not be null!");
+ }
+ final int callingUid = Binder.getCallingUid();
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ // We use "getDisplayContent" instead of "getDisplayContentOrCreate" because
+ // this method may be called in DisplayPolicy's constructor and may cause
+ // infinite loop. In this scenario, we early return here and switch to do the
+ // registration in DisplayContent#onParentChanged at DisplayContent initialization.
+ final DisplayContent dc = mRoot.getDisplayContent(displayId);
+ if (dc == null) {
+ if (Binder.getCallingPid() != myPid()) {
+ throw new WindowManager.InvalidDisplayException("attachToDisplayContent: "
+ + "trying to attach to a non-existing display:" + displayId);
+ }
+ // Early return if this method is invoked from system process.
+ // See above comments for more detail.
+ return null;
+ }
+
+ mWindowContextListenerController.registerWindowContainerListener(clientToken, dc,
+ callingUid, INVALID_WINDOW_TYPE, null /* options */);
+ return dc.getConfiguration();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
/** Returns {@code true} if this binder is a registered window token. */
@Override
public boolean isWindowToken(IBinder binder) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java
index a8ede13e5de6..d7daa57cc9da 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java
@@ -29,7 +29,9 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import android.app.ActivityThread;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
@@ -44,6 +46,7 @@ import android.view.WindowManagerGlobal;
import com.android.server.inputmethod.InputMethodManagerService;
import com.android.server.inputmethod.InputMethodMenuController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -62,6 +65,9 @@ public class InputMethodMenuControllerTest extends WindowTestsBase {
private InputMethodMenuController mController;
private DualDisplayAreaGroupPolicyTest.DualDisplayContent mSecondaryDisplay;
+ private IWindowManager mIWindowManager;
+ private DisplayManagerGlobal mDisplayManagerGlobal;
+
@Before
public void setUp() throws Exception {
// Let the Display to be created with the DualDisplay policy.
@@ -70,10 +76,12 @@ public class InputMethodMenuControllerTest extends WindowTestsBase {
Mockito.doReturn(policyProvider).when(mWm).getDisplayAreaPolicyProvider();
mController = new InputMethodMenuController(mock(InputMethodManagerService.class));
+ mSecondaryDisplay = new DualDisplayAreaGroupPolicyTest.DualDisplayContent
+ .Builder(mAtm, 1000, 1000).build();
// Mock addWindowTokenWithOptions to create a test window token.
- IWindowManager wms = WindowManagerGlobal.getWindowManagerService();
- spyOn(wms);
+ mIWindowManager = WindowManagerGlobal.getWindowManagerService();
+ spyOn(mIWindowManager);
doAnswer(invocation -> {
Object[] args = invocation.getArguments();
IBinder clientToken = (IBinder) args[0];
@@ -83,19 +91,24 @@ public class InputMethodMenuControllerTest extends WindowTestsBase {
dc.getImeContainer(), 1000 /* ownerUid */, TYPE_INPUT_METHOD_DIALOG,
null /* options */);
return dc.getImeContainer().getConfiguration();
- }).when(wms).attachWindowContextToDisplayArea(any(), eq(TYPE_INPUT_METHOD_DIALOG),
- anyInt(), any());
-
- mSecondaryDisplay = new DualDisplayAreaGroupPolicyTest.DualDisplayContent
- .Builder(mAtm, 1000, 1000).build();
-
- // Mock DisplayManagerGlobal to return test display when obtaining Display instance.
+ }).when(mIWindowManager).attachWindowContextToDisplayArea(any(),
+ eq(TYPE_INPUT_METHOD_DIALOG), anyInt(), any());
+ mDisplayManagerGlobal = DisplayManagerGlobal.getInstance();
+ spyOn(mDisplayManagerGlobal);
final int displayId = mSecondaryDisplay.getDisplayId();
final Display display = mSecondaryDisplay.getDisplay();
- DisplayManagerGlobal displayManagerGlobal = DisplayManagerGlobal.getInstance();
- spyOn(displayManagerGlobal);
- doReturn(display).when(displayManagerGlobal).getCompatibleDisplay(eq(displayId),
+ doReturn(display).when(mDisplayManagerGlobal).getCompatibleDisplay(eq(displayId),
(Resources) any());
+ Context systemUiContext = ActivityThread.currentActivityThread()
+ .getSystemUiContext(displayId);
+ spyOn(systemUiContext);
+ doReturn(display).when(systemUiContext).getDisplay();
+ }
+
+ @After
+ public void tearDown() {
+ reset(mIWindowManager);
+ reset(mDisplayManagerGlobal);
}
@Test