Merge "Migrate unfold animation to Shell transitions [Part 1]" into tm-dev
This commit is contained in:
commit
a830367d97
@ -67,6 +67,7 @@ public final class TransitionRequestInfo implements Parcelable {
|
||||
@Nullable private Rect mEndAbsBounds = null;
|
||||
private int mStartRotation = WindowConfiguration.ROTATION_UNDEFINED;
|
||||
private int mEndRotation = WindowConfiguration.ROTATION_UNDEFINED;
|
||||
private boolean mPhysicalDisplayChanged = false;
|
||||
|
||||
/** Create empty display-change. */
|
||||
public DisplayChange(int displayId) {
|
||||
@ -120,6 +121,11 @@ public final class TransitionRequestInfo implements Parcelable {
|
||||
return mEndRotation;
|
||||
}
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public boolean isPhysicalDisplayChanged() {
|
||||
return mPhysicalDisplayChanged;
|
||||
}
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public @android.annotation.NonNull DisplayChange setStartAbsBounds(@android.annotation.NonNull Rect value) {
|
||||
mStartAbsBounds = value;
|
||||
@ -144,6 +150,12 @@ public final class TransitionRequestInfo implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public @android.annotation.NonNull DisplayChange setPhysicalDisplayChanged( boolean value) {
|
||||
mPhysicalDisplayChanged = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public String toString() {
|
||||
@ -155,7 +167,8 @@ public final class TransitionRequestInfo implements Parcelable {
|
||||
"startAbsBounds = " + mStartAbsBounds + ", " +
|
||||
"endAbsBounds = " + mEndAbsBounds + ", " +
|
||||
"startRotation = " + mStartRotation + ", " +
|
||||
"endRotation = " + mEndRotation +
|
||||
"endRotation = " + mEndRotation + ", " +
|
||||
"physicalDisplayChanged = " + mPhysicalDisplayChanged +
|
||||
" }";
|
||||
}
|
||||
|
||||
@ -166,6 +179,7 @@ public final class TransitionRequestInfo implements Parcelable {
|
||||
// void parcelFieldName(Parcel dest, int flags) { ... }
|
||||
|
||||
byte flg = 0;
|
||||
if (mPhysicalDisplayChanged) flg |= 0x20;
|
||||
if (mStartAbsBounds != null) flg |= 0x2;
|
||||
if (mEndAbsBounds != null) flg |= 0x4;
|
||||
dest.writeByte(flg);
|
||||
@ -188,6 +202,7 @@ public final class TransitionRequestInfo implements Parcelable {
|
||||
// static FieldType unparcelFieldName(Parcel in) { ... }
|
||||
|
||||
byte flg = in.readByte();
|
||||
boolean physicalDisplayChanged = (flg & 0x20) != 0;
|
||||
int displayId = in.readInt();
|
||||
Rect startAbsBounds = (flg & 0x2) == 0 ? null : (Rect) in.readTypedObject(Rect.CREATOR);
|
||||
Rect endAbsBounds = (flg & 0x4) == 0 ? null : (Rect) in.readTypedObject(Rect.CREATOR);
|
||||
@ -199,6 +214,7 @@ public final class TransitionRequestInfo implements Parcelable {
|
||||
this.mEndAbsBounds = endAbsBounds;
|
||||
this.mStartRotation = startRotation;
|
||||
this.mEndRotation = endRotation;
|
||||
this.mPhysicalDisplayChanged = physicalDisplayChanged;
|
||||
|
||||
// onConstructed(); // You can define this method to get a callback
|
||||
}
|
||||
@ -218,10 +234,10 @@ public final class TransitionRequestInfo implements Parcelable {
|
||||
};
|
||||
|
||||
@DataClass.Generated(
|
||||
time = 1639445520915L,
|
||||
time = 1648141181315L,
|
||||
codegenVersion = "1.0.23",
|
||||
sourceFile = "frameworks/base/core/java/android/window/TransitionRequestInfo.java",
|
||||
inputSignatures = "private final int mDisplayId\nprivate @android.annotation.Nullable android.graphics.Rect mStartAbsBounds\nprivate @android.annotation.Nullable android.graphics.Rect mEndAbsBounds\nprivate int mStartRotation\nprivate int mEndRotation\nclass DisplayChange extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genBuilder=false, genConstructor=false)")
|
||||
inputSignatures = "private final int mDisplayId\nprivate @android.annotation.Nullable android.graphics.Rect mStartAbsBounds\nprivate @android.annotation.Nullable android.graphics.Rect mEndAbsBounds\nprivate int mStartRotation\nprivate int mEndRotation\nprivate boolean mPhysicalDisplayChanged\nclass DisplayChange extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genBuilder=false, genConstructor=false)")
|
||||
@Deprecated
|
||||
private void __metadata() {}
|
||||
|
||||
|
@ -35,6 +35,7 @@ import com.android.wm.shell.recents.RecentTasksController;
|
||||
import com.android.wm.shell.splitscreen.SplitScreenController;
|
||||
import com.android.wm.shell.startingsurface.StartingWindowController;
|
||||
import com.android.wm.shell.transition.Transitions;
|
||||
import com.android.wm.shell.unfold.UnfoldTransitionHandler;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@ -56,6 +57,7 @@ public class ShellInitImpl {
|
||||
private final Optional<PipTouchHandler> mPipTouchHandlerOptional;
|
||||
private final FullscreenTaskListener mFullscreenTaskListener;
|
||||
private final Optional<FullscreenUnfoldController> mFullscreenUnfoldController;
|
||||
private final Optional<UnfoldTransitionHandler> mUnfoldTransitionHandler;
|
||||
private final Optional<FreeformTaskListener> mFreeformTaskListenerOptional;
|
||||
private final ShellExecutor mMainExecutor;
|
||||
private final Transitions mTransitions;
|
||||
@ -77,6 +79,7 @@ public class ShellInitImpl {
|
||||
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
||||
FullscreenTaskListener fullscreenTaskListener,
|
||||
Optional<FullscreenUnfoldController> fullscreenUnfoldTransitionController,
|
||||
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
|
||||
Optional<FreeformTaskListener> freeformTaskListenerOptional,
|
||||
Optional<RecentTasksController> recentTasks,
|
||||
Transitions transitions,
|
||||
@ -94,6 +97,7 @@ public class ShellInitImpl {
|
||||
mFullscreenTaskListener = fullscreenTaskListener;
|
||||
mPipTouchHandlerOptional = pipTouchHandlerOptional;
|
||||
mFullscreenUnfoldController = fullscreenUnfoldTransitionController;
|
||||
mUnfoldTransitionHandler = unfoldTransitionHandler;
|
||||
mFreeformTaskListenerOptional = freeformTaskListenerOptional;
|
||||
mRecentTasks = recentTasks;
|
||||
mTransitions = transitions;
|
||||
@ -126,6 +130,7 @@ public class ShellInitImpl {
|
||||
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||
mTransitions.register(mShellTaskOrganizer);
|
||||
mUnfoldTransitionHandler.ifPresent(UnfoldTransitionHandler::init);
|
||||
}
|
||||
|
||||
// TODO(b/181599115): This should really be the pip controller, but until we can provide the
|
||||
|
@ -92,6 +92,7 @@ import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelperController;
|
||||
import com.android.wm.shell.transition.ShellTransitions;
|
||||
import com.android.wm.shell.transition.Transitions;
|
||||
import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
|
||||
import com.android.wm.shell.unfold.UnfoldTransitionHandler;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@ -327,6 +328,21 @@ public abstract class WMShellBaseModule {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static Optional<UnfoldTransitionHandler> provideUnfoldTransitionHandler(
|
||||
Optional<ShellUnfoldProgressProvider> progressProvider,
|
||||
TransactionPool transactionPool,
|
||||
Transitions transitions,
|
||||
@ShellMainThread ShellExecutor executor) {
|
||||
if (progressProvider.isPresent()) {
|
||||
return Optional.of(
|
||||
new UnfoldTransitionHandler(progressProvider.get(), transactionPool, executor,
|
||||
transitions));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
//
|
||||
// Freeform (optional feature)
|
||||
//
|
||||
@ -660,6 +676,7 @@ public abstract class WMShellBaseModule {
|
||||
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
||||
FullscreenTaskListener fullscreenTaskListener,
|
||||
Optional<FullscreenUnfoldController> appUnfoldTransitionController,
|
||||
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
|
||||
Optional<FreeformTaskListener> freeformTaskListener,
|
||||
Optional<RecentTasksController> recentTasksOptional,
|
||||
Transitions transitions,
|
||||
@ -677,6 +694,7 @@ public abstract class WMShellBaseModule {
|
||||
pipTouchHandlerOptional,
|
||||
fullscreenTaskListener,
|
||||
appUnfoldTransitionController,
|
||||
unfoldTransitionHandler,
|
||||
freeformTaskListener,
|
||||
recentTasksOptional,
|
||||
transitions,
|
||||
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.wm.shell.unfold;
|
||||
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.view.WindowManager.TRANSIT_CHANGE;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.TransitionInfo;
|
||||
import android.window.TransitionRequestInfo;
|
||||
import android.window.WindowContainerTransaction;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.wm.shell.common.TransactionPool;
|
||||
import com.android.wm.shell.transition.Transitions;
|
||||
import com.android.wm.shell.transition.Transitions.TransitionFinishCallback;
|
||||
import com.android.wm.shell.transition.Transitions.TransitionHandler;
|
||||
import com.android.wm.shell.unfold.ShellUnfoldProgressProvider.UnfoldListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListener {
|
||||
|
||||
private final ShellUnfoldProgressProvider mUnfoldProgressProvider;
|
||||
private final Transitions mTransitions;
|
||||
private final Executor mExecutor;
|
||||
private final TransactionPool mTransactionPool;
|
||||
|
||||
@Nullable
|
||||
private TransitionFinishCallback mFinishCallback;
|
||||
@Nullable
|
||||
private IBinder mTransition;
|
||||
|
||||
private final List<TransitionInfo.Change> mAnimatedFullscreenTasks = new ArrayList<>();
|
||||
|
||||
public UnfoldTransitionHandler(ShellUnfoldProgressProvider unfoldProgressProvider,
|
||||
TransactionPool transactionPool, Executor executor, Transitions transitions) {
|
||||
mUnfoldProgressProvider = unfoldProgressProvider;
|
||||
mTransactionPool = transactionPool;
|
||||
mExecutor = executor;
|
||||
mTransitions = transitions;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
mTransitions.addHandler(this);
|
||||
mUnfoldProgressProvider.addListener(mExecutor, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
|
||||
@NonNull SurfaceControl.Transaction startTransaction,
|
||||
@NonNull SurfaceControl.Transaction finishTransaction,
|
||||
@NonNull TransitionFinishCallback finishCallback) {
|
||||
|
||||
if (transition != mTransition) return false;
|
||||
|
||||
startTransaction.apply();
|
||||
|
||||
mAnimatedFullscreenTasks.clear();
|
||||
info.getChanges().forEach(change -> {
|
||||
final boolean allowedToAnimate = change.getTaskInfo() != null
|
||||
&& change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_FULLSCREEN
|
||||
&& change.getTaskInfo().getActivityType() != ACTIVITY_TYPE_HOME
|
||||
&& change.getMode() == TRANSIT_CHANGE;
|
||||
|
||||
if (allowedToAnimate) {
|
||||
mAnimatedFullscreenTasks.add(change);
|
||||
}
|
||||
});
|
||||
|
||||
mFinishCallback = finishCallback;
|
||||
mTransition = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateChangeProgress(float progress) {
|
||||
mAnimatedFullscreenTasks.forEach(change -> {
|
||||
final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
|
||||
|
||||
// TODO: this is a placeholder animation, replace with a spec version in the next CLs
|
||||
final float testScale = 0.8f + 0.2f * progress;
|
||||
transaction.setScale(change.getLeash(), testScale, testScale);
|
||||
|
||||
transaction.apply();
|
||||
mTransactionPool.release(transaction);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateChangeFinished() {
|
||||
if (mFinishCallback != null) {
|
||||
mFinishCallback.onTransitionFinished(null, null);
|
||||
mFinishCallback = null;
|
||||
mAnimatedFullscreenTasks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
|
||||
@NonNull TransitionRequestInfo request) {
|
||||
if (request.getType() == TRANSIT_CHANGE && request.getDisplayChange() != null
|
||||
&& request.getDisplayChange().isPhysicalDisplayChanged()) {
|
||||
mTransition = transition;
|
||||
return new WindowContainerTransaction();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -551,6 +551,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
final FixedRotationTransitionListener mFixedRotationTransitionListener =
|
||||
new FixedRotationTransitionListener();
|
||||
|
||||
private PhysicalDisplaySwitchTransitionLauncher mDisplaySwitchTransitionLauncher;
|
||||
|
||||
/** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
|
||||
final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
|
||||
|
||||
@ -1043,6 +1045,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
mAppTransitionController = new AppTransitionController(mWmService, this);
|
||||
mTransitionController.registerLegacyListener(mFixedRotationTransitionListener);
|
||||
mUnknownAppVisibilityController = new UnknownAppVisibilityController(mWmService, this);
|
||||
mDisplaySwitchTransitionLauncher = new PhysicalDisplaySwitchTransitionLauncher(this,
|
||||
mTransitionController);
|
||||
|
||||
final InputChannel inputChannel = mWmService.mInputManager.monitorInput(
|
||||
"PointerEventDispatcher" + mDisplayId, mDisplayId);
|
||||
@ -2751,6 +2755,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
// metrics are updated as rotation settings might depend on them
|
||||
mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this,
|
||||
/* includeRotationSettings */ false);
|
||||
mDisplaySwitchTransitionLauncher.requestDisplaySwitchTransitionIfNeeded(mDisplayId,
|
||||
mInitialDisplayWidth, mInitialDisplayHeight, newWidth, newHeight);
|
||||
}
|
||||
|
||||
// If there is an override set for base values - use it, otherwise use new values.
|
||||
@ -2779,6 +2785,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
mInitialRoundedCorners = newRoundedCorners;
|
||||
mCurrentUniqueDisplayId = newUniqueId;
|
||||
reconfigureDisplayLocked();
|
||||
|
||||
if (physicalDisplayChanged) {
|
||||
mDisplaySwitchTransitionLauncher.onDisplayUpdated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3105,6 +3115,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
mTransitionController.unregisterLegacyListener(mFixedRotationTransitionListener);
|
||||
handleAnimatingStoppedAndTransition();
|
||||
mWmService.stopFreezingDisplayLocked();
|
||||
mDisplaySwitchTransitionLauncher.destroy();
|
||||
super.removeImmediately();
|
||||
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
|
||||
mPointerEventDispatcher.dispose();
|
||||
|
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.server.wm;
|
||||
|
||||
import static android.view.WindowManager.TRANSIT_CHANGE;
|
||||
|
||||
import static com.android.internal.R.bool.config_unfoldTransitionEnabled;
|
||||
import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.devicestate.DeviceStateManager;
|
||||
import android.os.HandlerExecutor;
|
||||
import android.window.TransitionRequestInfo;
|
||||
|
||||
public class PhysicalDisplaySwitchTransitionLauncher {
|
||||
|
||||
private final DisplayContent mDisplayContent;
|
||||
private final DeviceStateManager mDeviceStateManager;
|
||||
private final Context mContext;
|
||||
private final TransitionController mTransitionController;
|
||||
|
||||
private DeviceStateListener mDeviceStateListener;
|
||||
|
||||
/**
|
||||
* If on a foldable device represents whether the device is folded or not
|
||||
*/
|
||||
private boolean mIsFolded;
|
||||
private Transition mTransition;
|
||||
|
||||
public PhysicalDisplaySwitchTransitionLauncher(DisplayContent displayContent,
|
||||
TransitionController transitionController) {
|
||||
mDisplayContent = displayContent;
|
||||
mContext = mDisplayContent.mWmService.mContext;
|
||||
mTransitionController = transitionController;
|
||||
|
||||
mDeviceStateManager = mContext.getSystemService(DeviceStateManager.class);
|
||||
|
||||
if (mDeviceStateManager != null) {
|
||||
mDeviceStateListener = new DeviceStateListener(mContext);
|
||||
mDeviceStateManager
|
||||
.registerCallback(new HandlerExecutor(mDisplayContent.mWmService.mH),
|
||||
mDeviceStateListener);
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (mDeviceStateManager != null) {
|
||||
mDeviceStateManager.unregisterCallback(mDeviceStateListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests to start a transition for the physical display switch
|
||||
*/
|
||||
public void requestDisplaySwitchTransitionIfNeeded(int displayId, int oldDisplayWidth,
|
||||
int oldDisplayHeight, int newDisplayWidth, int newDisplayHeight) {
|
||||
if (!mTransitionController.isShellTransitionsEnabled()) return;
|
||||
if (!mDisplayContent.getLastHasContent()) return;
|
||||
|
||||
boolean shouldRequestUnfoldTransition = !mIsFolded
|
||||
&& mContext.getResources().getBoolean(config_unfoldTransitionEnabled)
|
||||
&& ValueAnimator.areAnimatorsEnabled();
|
||||
|
||||
if (!shouldRequestUnfoldTransition) {
|
||||
return;
|
||||
}
|
||||
|
||||
final TransitionRequestInfo.DisplayChange displayChange =
|
||||
new TransitionRequestInfo.DisplayChange(displayId);
|
||||
|
||||
final Rect startAbsBounds = new Rect(0, 0, oldDisplayWidth, oldDisplayHeight);
|
||||
displayChange.setStartAbsBounds(startAbsBounds);
|
||||
final Rect endAbsBounds = new Rect(0, 0, newDisplayWidth, newDisplayHeight);
|
||||
displayChange.setEndAbsBounds(endAbsBounds);
|
||||
displayChange.setPhysicalDisplayChanged(true);
|
||||
|
||||
final Transition t = mTransitionController.requestTransitionIfNeeded(TRANSIT_CHANGE,
|
||||
0 /* flags */,
|
||||
mDisplayContent, mDisplayContent, null /* remoteTransition */,
|
||||
displayChange);
|
||||
|
||||
if (t != null) {
|
||||
mDisplayContent.mAtmService.startLaunchPowerMode(POWER_MODE_REASON_CHANGE_DISPLAY);
|
||||
mTransitionController.collectForDisplayChange(mDisplayContent, t);
|
||||
mTransition = t;
|
||||
}
|
||||
}
|
||||
|
||||
public void onDisplayUpdated() {
|
||||
if (mTransition != null) {
|
||||
mTransition.setAllReady();
|
||||
mTransition = null;
|
||||
}
|
||||
}
|
||||
|
||||
class DeviceStateListener extends DeviceStateManager.FoldStateListener {
|
||||
|
||||
DeviceStateListener(Context context) {
|
||||
super(context, newIsFolded -> mIsFolded = newIsFolded);
|
||||
}
|
||||
}
|
||||
}
|
@ -52,6 +52,7 @@ import android.content.IntentFilter;
|
||||
import android.content.pm.IPackageManager;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.devicestate.DeviceStateManager;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.DisplayManagerInternal;
|
||||
import android.net.Uri;
|
||||
@ -229,6 +230,10 @@ public class SystemServicesTestRule implements TestRule {
|
||||
final AppOpsManager aom = mock(AppOpsManager.class);
|
||||
doReturn(aom).when(mContext).getSystemService(eq(Context.APP_OPS_SERVICE));
|
||||
|
||||
// DeviceStateManager
|
||||
final DeviceStateManager dsm = mock(DeviceStateManager.class);
|
||||
doReturn(dsm).when(mContext).getSystemService(eq(Context.DEVICE_STATE_SERVICE));
|
||||
|
||||
// Prevent "WakeLock finalized while still held: SCREEN_FROZEN".
|
||||
final PowerManager pm = mock(PowerManager.class);
|
||||
doReturn(pm).when(mContext).getSystemService(eq(Context.POWER_SERVICE));
|
||||
|
Loading…
x
Reference in New Issue
Block a user