Merge "Letterbox Reacheability Multiplier Persistence" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
a8117a579f
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
option java_package = "com.android.server.wm";
|
||||
option java_outer_classname = "WindowManagerProtos";
|
||||
|
||||
message TaskSnapshotProto {
|
||||
int32 orientation = 1;
|
||||
int32 inset_left = 2;
|
||||
int32 inset_top = 3;
|
||||
int32 inset_right = 4;
|
||||
int32 inset_bottom = 5;
|
||||
bool is_real_snapshot = 6;
|
||||
int32 windowing_mode = 7;
|
||||
int32 system_ui_visibility = 8 [deprecated=true];
|
||||
bool is_translucent = 9;
|
||||
string top_activity_component = 10;
|
||||
// deprecated because original width and height are stored now instead of the scale.
|
||||
float legacy_scale = 11 [deprecated=true];
|
||||
int64 id = 12;
|
||||
int32 rotation = 13;
|
||||
// The task width when the snapshot was taken
|
||||
int32 task_width = 14;
|
||||
// The task height when the snapshot was taken
|
||||
int32 task_height = 15;
|
||||
int32 appearance = 16;
|
||||
int32 letterbox_inset_left = 17;
|
||||
int32 letterbox_inset_top = 18;
|
||||
int32 letterbox_inset_right = 19;
|
||||
int32 letterbox_inset_bottom = 20;
|
||||
}
|
||||
71
proto/src/windowmanager.proto
Normal file
71
proto/src/windowmanager.proto
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
option java_package = "com.android.server.wm";
|
||||
option java_outer_classname = "WindowManagerProtos";
|
||||
|
||||
message TaskSnapshotProto {
|
||||
int32 orientation = 1;
|
||||
int32 inset_left = 2;
|
||||
int32 inset_top = 3;
|
||||
int32 inset_right = 4;
|
||||
int32 inset_bottom = 5;
|
||||
bool is_real_snapshot = 6;
|
||||
int32 windowing_mode = 7;
|
||||
int32 system_ui_visibility = 8 [deprecated=true];
|
||||
bool is_translucent = 9;
|
||||
string top_activity_component = 10;
|
||||
// deprecated because original width and height are stored now instead of the scale.
|
||||
float legacy_scale = 11 [deprecated=true];
|
||||
int64 id = 12;
|
||||
int32 rotation = 13;
|
||||
// The task width when the snapshot was taken
|
||||
int32 task_width = 14;
|
||||
// The task height when the snapshot was taken
|
||||
int32 task_height = 15;
|
||||
int32 appearance = 16;
|
||||
int32 letterbox_inset_left = 17;
|
||||
int32 letterbox_inset_top = 18;
|
||||
int32 letterbox_inset_right = 19;
|
||||
int32 letterbox_inset_bottom = 20;
|
||||
}
|
||||
|
||||
// Persistent letterboxing configurations
|
||||
message LetterboxProto {
|
||||
|
||||
// Possible values for the letterbox horizontal reachability
|
||||
enum LetterboxHorizontalReachability {
|
||||
LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT = 0;
|
||||
LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER = 1;
|
||||
LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT = 2;
|
||||
}
|
||||
|
||||
// Possible values for the letterbox vertical reachability
|
||||
enum LetterboxVerticalReachability {
|
||||
LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP = 0;
|
||||
LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER = 1;
|
||||
LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM = 2;
|
||||
}
|
||||
|
||||
// Represents the current horizontal position for the letterboxed activity
|
||||
LetterboxHorizontalReachability letterbox_position_for_horizontal_reachability = 1;
|
||||
// Represents the current vertical position for the letterboxed activity
|
||||
LetterboxVerticalReachability letterbox_position_for_vertical_reachability = 2;
|
||||
}
|
||||
@@ -17,14 +17,17 @@
|
||||
package com.android.server.wm;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.function.Function;
|
||||
|
||||
/** Reads letterbox configs from resources and controls their overrides at runtime. */
|
||||
final class LetterboxConfiguration {
|
||||
@@ -156,34 +159,25 @@ final class LetterboxConfiguration {
|
||||
// portrait device orientation.
|
||||
private boolean mIsVerticalReachabilityEnabled;
|
||||
|
||||
|
||||
// Horizontal position of a center of the letterboxed app window which is global to prevent
|
||||
// "jumps" when switching between letterboxed apps. It's updated to reposition the app window
|
||||
// in response to a double tap gesture (see LetterboxUiController#handleDoubleTap). Used in
|
||||
// LetterboxUiController#getHorizontalPositionMultiplier which is called from
|
||||
// ActivityRecord#updateResolvedBoundsPosition.
|
||||
// TODO(b/199426138): Global reachability setting causes a jump when resuming an app from
|
||||
// Overview after changing position in another app.
|
||||
@LetterboxHorizontalReachabilityPosition
|
||||
private volatile int mLetterboxPositionForHorizontalReachability;
|
||||
|
||||
// Vertical position of a center of the letterboxed app window which is global to prevent
|
||||
// "jumps" when switching between letterboxed apps. It's updated to reposition the app window
|
||||
// in response to a double tap gesture (see LetterboxUiController#handleDoubleTap). Used in
|
||||
// LetterboxUiController#getVerticalPositionMultiplier which is called from
|
||||
// ActivityRecord#updateResolvedBoundsPosition.
|
||||
// TODO(b/199426138): Global reachability setting causes a jump when resuming an app from
|
||||
// Overview after changing position in another app.
|
||||
@LetterboxVerticalReachabilityPosition
|
||||
private volatile int mLetterboxPositionForVerticalReachability;
|
||||
|
||||
// Whether education is allowed for letterboxed fullscreen apps.
|
||||
private boolean mIsEducationEnabled;
|
||||
|
||||
// Whether using split screen aspect ratio as a default aspect ratio for unresizable apps.
|
||||
private boolean mIsSplitScreenAspectRatioForUnresizableAppsEnabled;
|
||||
|
||||
// Responsible for the persistence of letterbox[Horizontal|Vertical]PositionMultiplier
|
||||
@NonNull
|
||||
private final LetterboxConfigurationPersister mLetterboxConfigurationPersister;
|
||||
|
||||
LetterboxConfiguration(Context systemUiContext) {
|
||||
this(systemUiContext, new LetterboxConfigurationPersister(systemUiContext,
|
||||
() -> readLetterboxHorizontalReachabilityPositionFromConfig(systemUiContext),
|
||||
() -> readLetterboxVerticalReachabilityPositionFromConfig(systemUiContext)));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
LetterboxConfiguration(Context systemUiContext,
|
||||
LetterboxConfigurationPersister letterboxConfigurationPersister) {
|
||||
mContext = systemUiContext;
|
||||
mFixedOrientationLetterboxAspectRatio = mContext.getResources().getFloat(
|
||||
R.dimen.config_fixedOrientationLetterboxAspectRatio);
|
||||
@@ -206,14 +200,14 @@ final class LetterboxConfiguration {
|
||||
readLetterboxHorizontalReachabilityPositionFromConfig(mContext);
|
||||
mDefaultPositionForVerticalReachability =
|
||||
readLetterboxVerticalReachabilityPositionFromConfig(mContext);
|
||||
mLetterboxPositionForHorizontalReachability = mDefaultPositionForHorizontalReachability;
|
||||
mLetterboxPositionForVerticalReachability = mDefaultPositionForVerticalReachability;
|
||||
mIsEducationEnabled = mContext.getResources().getBoolean(
|
||||
R.bool.config_letterboxIsEducationEnabled);
|
||||
setDefaultMinAspectRatioForUnresizableApps(mContext.getResources().getFloat(
|
||||
R.dimen.config_letterboxDefaultMinAspectRatioForUnresizableApps));
|
||||
mIsSplitScreenAspectRatioForUnresizableAppsEnabled = mContext.getResources().getBoolean(
|
||||
R.bool.config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled);
|
||||
mLetterboxConfigurationPersister = letterboxConfigurationPersister;
|
||||
mLetterboxConfigurationPersister.start();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -653,7 +647,9 @@ final class LetterboxConfiguration {
|
||||
* <p>The position multiplier is changed after each double tap in the letterbox area.
|
||||
*/
|
||||
float getHorizontalMultiplierForReachability() {
|
||||
switch (mLetterboxPositionForHorizontalReachability) {
|
||||
final int letterboxPositionForHorizontalReachability =
|
||||
mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability();
|
||||
switch (letterboxPositionForHorizontalReachability) {
|
||||
case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT:
|
||||
return 0.0f;
|
||||
case LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER:
|
||||
@@ -662,10 +658,11 @@ final class LetterboxConfiguration {
|
||||
return 1.0f;
|
||||
default:
|
||||
throw new AssertionError(
|
||||
"Unexpected letterbox position type: "
|
||||
+ mLetterboxPositionForHorizontalReachability);
|
||||
"Unexpected letterbox position type: "
|
||||
+ letterboxPositionForHorizontalReachability);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets vertical position of a center of the letterboxed app window when reachability
|
||||
* is enabled specified. 0 corresponds to the top side of the screen and 1 to the bottom side.
|
||||
@@ -673,7 +670,9 @@ final class LetterboxConfiguration {
|
||||
* <p>The position multiplier is changed after each double tap in the letterbox area.
|
||||
*/
|
||||
float getVerticalMultiplierForReachability() {
|
||||
switch (mLetterboxPositionForVerticalReachability) {
|
||||
final int letterboxPositionForVerticalReachability =
|
||||
mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability();
|
||||
switch (letterboxPositionForVerticalReachability) {
|
||||
case LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP:
|
||||
return 0.0f;
|
||||
case LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER:
|
||||
@@ -683,7 +682,7 @@ final class LetterboxConfiguration {
|
||||
default:
|
||||
throw new AssertionError(
|
||||
"Unexpected letterbox position type: "
|
||||
+ mLetterboxPositionForVerticalReachability);
|
||||
+ letterboxPositionForVerticalReachability);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -693,7 +692,7 @@ final class LetterboxConfiguration {
|
||||
*/
|
||||
@LetterboxHorizontalReachabilityPosition
|
||||
int getLetterboxPositionForHorizontalReachability() {
|
||||
return mLetterboxPositionForHorizontalReachability;
|
||||
return mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -702,7 +701,7 @@ final class LetterboxConfiguration {
|
||||
*/
|
||||
@LetterboxVerticalReachabilityPosition
|
||||
int getLetterboxPositionForVerticalReachability() {
|
||||
return mLetterboxPositionForVerticalReachability;
|
||||
return mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability();
|
||||
}
|
||||
|
||||
/** Returns a string representing the given {@link LetterboxHorizontalReachabilityPosition}. */
|
||||
@@ -742,9 +741,8 @@ final class LetterboxConfiguration {
|
||||
* right side.
|
||||
*/
|
||||
void movePositionForHorizontalReachabilityToNextRightStop() {
|
||||
mLetterboxPositionForHorizontalReachability = Math.min(
|
||||
mLetterboxPositionForHorizontalReachability + 1,
|
||||
LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT);
|
||||
updatePositionForHorizontalReachability(prev -> Math.min(
|
||||
prev + 1, LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -752,8 +750,7 @@ final class LetterboxConfiguration {
|
||||
* side.
|
||||
*/
|
||||
void movePositionForHorizontalReachabilityToNextLeftStop() {
|
||||
mLetterboxPositionForHorizontalReachability =
|
||||
Math.max(mLetterboxPositionForHorizontalReachability - 1, 0);
|
||||
updatePositionForHorizontalReachability(prev -> Math.max(prev - 1, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -761,9 +758,8 @@ final class LetterboxConfiguration {
|
||||
* side.
|
||||
*/
|
||||
void movePositionForVerticalReachabilityToNextBottomStop() {
|
||||
mLetterboxPositionForVerticalReachability = Math.min(
|
||||
mLetterboxPositionForVerticalReachability + 1,
|
||||
LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM);
|
||||
updatePositionForVerticalReachability(prev -> Math.min(
|
||||
prev + 1, LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -771,8 +767,7 @@ final class LetterboxConfiguration {
|
||||
* side.
|
||||
*/
|
||||
void movePositionForVerticalReachabilityToNextTopStop() {
|
||||
mLetterboxPositionForVerticalReachability =
|
||||
Math.max(mLetterboxPositionForVerticalReachability - 1, 0);
|
||||
updatePositionForVerticalReachability(prev -> Math.max(prev - 1, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -822,4 +817,26 @@ final class LetterboxConfiguration {
|
||||
R.bool.config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled);
|
||||
}
|
||||
|
||||
/** Calculates a new letterboxPositionForHorizontalReachability value and updates the store */
|
||||
private void updatePositionForHorizontalReachability(
|
||||
Function<Integer, Integer> newHorizonalPositionFun) {
|
||||
final int letterboxPositionForHorizontalReachability =
|
||||
mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability();
|
||||
final int nextHorizontalPosition = newHorizonalPositionFun.apply(
|
||||
letterboxPositionForHorizontalReachability);
|
||||
mLetterboxConfigurationPersister.setLetterboxPositionForHorizontalReachability(
|
||||
nextHorizontalPosition);
|
||||
}
|
||||
|
||||
/** Calculates a new letterboxPositionForVerticalReachability value and updates the store */
|
||||
private void updatePositionForVerticalReachability(
|
||||
Function<Integer, Integer> newVerticalPositionFun) {
|
||||
final int letterboxPositionForVerticalReachability =
|
||||
mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability();
|
||||
final int nextVerticalPosition = newVerticalPositionFun.apply(
|
||||
letterboxPositionForVerticalReachability);
|
||||
mLetterboxConfigurationPersister.setLetterboxPositionForVerticalReachability(
|
||||
nextVerticalPosition);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* 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 com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
import android.util.AtomicFile;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.wm.LetterboxConfiguration.LetterboxHorizontalReachabilityPosition;
|
||||
import com.android.server.wm.LetterboxConfiguration.LetterboxVerticalReachabilityPosition;
|
||||
import com.android.server.wm.nano.WindowManagerProtos;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Persists the values of letterboxPositionForHorizontalReachability and
|
||||
* letterboxPositionForVerticalReachability for {@link LetterboxConfiguration}.
|
||||
*/
|
||||
class LetterboxConfigurationPersister {
|
||||
|
||||
private static final String TAG =
|
||||
TAG_WITH_CLASS_NAME ? "LetterboxConfigurationPersister" : TAG_WM;
|
||||
|
||||
@VisibleForTesting
|
||||
static final String LETTERBOX_CONFIGURATION_FILENAME = "letterbox_config";
|
||||
|
||||
private final Context mContext;
|
||||
private final Supplier<Integer> mDefaultHorizontalReachabilitySupplier;
|
||||
private final Supplier<Integer> mDefaultVerticalReachabilitySupplier;
|
||||
|
||||
// Horizontal position of a center of the letterboxed app window which is global to prevent
|
||||
// "jumps" when switching between letterboxed apps. It's updated to reposition the app window
|
||||
// in response to a double tap gesture (see LetterboxUiController#handleDoubleTap). Used in
|
||||
// LetterboxUiController#getHorizontalPositionMultiplier which is called from
|
||||
// ActivityRecord#updateResolvedBoundsPosition.
|
||||
@LetterboxHorizontalReachabilityPosition
|
||||
private volatile int mLetterboxPositionForHorizontalReachability;
|
||||
|
||||
// Vertical position of a center of the letterboxed app window which is global to prevent
|
||||
// "jumps" when switching between letterboxed apps. It's updated to reposition the app window
|
||||
// in response to a double tap gesture (see LetterboxUiController#handleDoubleTap). Used in
|
||||
// LetterboxUiController#getVerticalPositionMultiplier which is called from
|
||||
// ActivityRecord#updateResolvedBoundsPosition.
|
||||
@LetterboxVerticalReachabilityPosition
|
||||
private volatile int mLetterboxPositionForVerticalReachability;
|
||||
|
||||
@NonNull
|
||||
private final AtomicFile mConfigurationFile;
|
||||
|
||||
@Nullable
|
||||
private final Consumer<String> mCompletionCallback;
|
||||
|
||||
@NonNull
|
||||
private final PersisterQueue mPersisterQueue;
|
||||
|
||||
LetterboxConfigurationPersister(Context systemUiContext,
|
||||
Supplier<Integer> defaultHorizontalReachabilitySupplier,
|
||||
Supplier<Integer> defaultVerticalReachabilitySupplier) {
|
||||
this(systemUiContext, defaultHorizontalReachabilitySupplier,
|
||||
defaultVerticalReachabilitySupplier,
|
||||
Environment.getDataSystemDirectory(), new PersisterQueue(),
|
||||
/* completionCallback */ null);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
LetterboxConfigurationPersister(Context systemUiContext,
|
||||
Supplier<Integer> defaultHorizontalReachabilitySupplier,
|
||||
Supplier<Integer> defaultVerticalReachabilitySupplier, File configFolder,
|
||||
PersisterQueue persisterQueue, @Nullable Consumer<String> completionCallback) {
|
||||
mContext = systemUiContext.createDeviceProtectedStorageContext();
|
||||
mDefaultHorizontalReachabilitySupplier = defaultHorizontalReachabilitySupplier;
|
||||
mDefaultVerticalReachabilitySupplier = defaultVerticalReachabilitySupplier;
|
||||
mCompletionCallback = completionCallback;
|
||||
final File prefFiles = new File(configFolder, LETTERBOX_CONFIGURATION_FILENAME);
|
||||
mConfigurationFile = new AtomicFile(prefFiles);
|
||||
mPersisterQueue = persisterQueue;
|
||||
readCurrentConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Startes the persistence queue
|
||||
*/
|
||||
void start() {
|
||||
mPersisterQueue.startPersisting();
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the horizontal position of the letterboxed app window when horizontal reachability is
|
||||
* enabled.
|
||||
*/
|
||||
@LetterboxHorizontalReachabilityPosition
|
||||
int getLetterboxPositionForHorizontalReachability() {
|
||||
return mLetterboxPositionForHorizontalReachability;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the vertical position of the letterboxed app window when vertical reachability is
|
||||
* enabled.
|
||||
*/
|
||||
@LetterboxVerticalReachabilityPosition
|
||||
int getLetterboxPositionForVerticalReachability() {
|
||||
return mLetterboxPositionForVerticalReachability;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates letterboxPositionForVerticalReachability if different from the current value
|
||||
*/
|
||||
void setLetterboxPositionForHorizontalReachability(
|
||||
int letterboxPositionForHorizontalReachability) {
|
||||
if (mLetterboxPositionForHorizontalReachability
|
||||
!= letterboxPositionForHorizontalReachability) {
|
||||
mLetterboxPositionForHorizontalReachability =
|
||||
letterboxPositionForHorizontalReachability;
|
||||
updateConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates letterboxPositionForVerticalReachability if different from the current value
|
||||
*/
|
||||
void setLetterboxPositionForVerticalReachability(
|
||||
int letterboxPositionForVerticalReachability) {
|
||||
if (mLetterboxPositionForVerticalReachability != letterboxPositionForVerticalReachability) {
|
||||
mLetterboxPositionForVerticalReachability = letterboxPositionForVerticalReachability;
|
||||
updateConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void useDefaultValue() {
|
||||
mLetterboxPositionForHorizontalReachability = mDefaultHorizontalReachabilitySupplier.get();
|
||||
mLetterboxPositionForVerticalReachability = mDefaultVerticalReachabilitySupplier.get();
|
||||
}
|
||||
|
||||
private void readCurrentConfiguration() {
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
fis = mConfigurationFile.openRead();
|
||||
byte[] protoData = readInputStream(fis);
|
||||
final WindowManagerProtos.LetterboxProto letterboxData =
|
||||
WindowManagerProtos.LetterboxProto.parseFrom(protoData);
|
||||
mLetterboxPositionForHorizontalReachability =
|
||||
letterboxData.letterboxPositionForHorizontalReachability;
|
||||
mLetterboxPositionForVerticalReachability =
|
||||
letterboxData.letterboxPositionForVerticalReachability;
|
||||
} catch (IOException ioe) {
|
||||
Slog.e(TAG,
|
||||
"Error reading from LetterboxConfigurationPersister. "
|
||||
+ "Using default values!", ioe);
|
||||
useDefaultValue();
|
||||
} finally {
|
||||
if (fis != null) {
|
||||
try {
|
||||
fis.close();
|
||||
} catch (IOException e) {
|
||||
useDefaultValue();
|
||||
Slog.e(TAG, "Error reading from LetterboxConfigurationPersister ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateConfiguration() {
|
||||
mPersisterQueue.addItem(new UpdateValuesCommand(mConfigurationFile,
|
||||
mLetterboxPositionForHorizontalReachability,
|
||||
mLetterboxPositionForVerticalReachability,
|
||||
mCompletionCallback), /* flush */ true);
|
||||
}
|
||||
|
||||
private static byte[] readInputStream(InputStream in) throws IOException {
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
try {
|
||||
byte[] buffer = new byte[1024];
|
||||
int size = in.read(buffer);
|
||||
while (size > 0) {
|
||||
outputStream.write(buffer, 0, size);
|
||||
size = in.read(buffer);
|
||||
}
|
||||
return outputStream.toByteArray();
|
||||
} finally {
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static class UpdateValuesCommand implements
|
||||
PersisterQueue.WriteQueueItem<UpdateValuesCommand> {
|
||||
|
||||
@NonNull
|
||||
private final AtomicFile mFileToUpdate;
|
||||
@Nullable
|
||||
private final Consumer<String> mOnComplete;
|
||||
|
||||
|
||||
private final int mHorizontalReachability;
|
||||
private final int mVerticalReachability;
|
||||
|
||||
UpdateValuesCommand(@NonNull AtomicFile fileToUpdate,
|
||||
int horizontalReachability, int verticalReachability,
|
||||
@Nullable Consumer<String> onComplete) {
|
||||
mFileToUpdate = fileToUpdate;
|
||||
mHorizontalReachability = horizontalReachability;
|
||||
mVerticalReachability = verticalReachability;
|
||||
mOnComplete = onComplete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
final WindowManagerProtos.LetterboxProto letterboxData =
|
||||
new WindowManagerProtos.LetterboxProto();
|
||||
letterboxData.letterboxPositionForHorizontalReachability = mHorizontalReachability;
|
||||
letterboxData.letterboxPositionForVerticalReachability = mVerticalReachability;
|
||||
final byte[] bytes = WindowManagerProtos.LetterboxProto.toByteArray(letterboxData);
|
||||
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = mFileToUpdate.startWrite();
|
||||
fos.write(bytes);
|
||||
mFileToUpdate.finishWrite(fos);
|
||||
} catch (IOException ioe) {
|
||||
mFileToUpdate.failWrite(fos);
|
||||
Slog.e(TAG,
|
||||
"Error writing to LetterboxConfigurationPersister. "
|
||||
+ "Using default values!", ioe);
|
||||
} finally {
|
||||
if (mOnComplete != null) {
|
||||
mOnComplete.accept("UpdateValuesCommand");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* 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 androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
|
||||
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT;
|
||||
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP;
|
||||
import static com.android.server.wm.LetterboxConfigurationPersister.LETTERBOX_CONFIGURATION_FILENAME;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.util.AtomicFile;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
public class LetterboxConfigurationPersisterTest {
|
||||
|
||||
private static final long TIMEOUT = 2000L; // 2 secs
|
||||
|
||||
private LetterboxConfigurationPersister mLetterboxConfigurationPersister;
|
||||
private Context mContext;
|
||||
private PersisterQueue mPersisterQueue;
|
||||
private QueueState mQueueState;
|
||||
private PersisterQueue.Listener mQueueListener;
|
||||
private File mConfigFolder;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mContext = getInstrumentation().getTargetContext();
|
||||
mConfigFolder = mContext.getFilesDir();
|
||||
mPersisterQueue = new PersisterQueue();
|
||||
mQueueState = new QueueState();
|
||||
mLetterboxConfigurationPersister = new LetterboxConfigurationPersister(mContext,
|
||||
() -> mContext.getResources().getInteger(
|
||||
R.integer.config_letterboxDefaultPositionForHorizontalReachability),
|
||||
() -> mContext.getResources().getInteger(
|
||||
R.integer.config_letterboxDefaultPositionForVerticalReachability),
|
||||
mConfigFolder, mPersisterQueue, mQueueState);
|
||||
mQueueListener = queueEmpty -> mQueueState.onItemAdded();
|
||||
mPersisterQueue.addListener(mQueueListener);
|
||||
mLetterboxConfigurationPersister.start();
|
||||
}
|
||||
|
||||
public void tearDown() throws InterruptedException {
|
||||
deleteConfiguration(mLetterboxConfigurationPersister, mPersisterQueue);
|
||||
waitForCompletion(mPersisterQueue);
|
||||
mPersisterQueue.removeListener(mQueueListener);
|
||||
stopPersisterSafe(mPersisterQueue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_whenStoreIsCreated_valuesAreDefaults() {
|
||||
final int positionForHorizontalReachability =
|
||||
mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability();
|
||||
final int defaultPositionForHorizontalReachability =
|
||||
mContext.getResources().getInteger(
|
||||
R.integer.config_letterboxDefaultPositionForHorizontalReachability);
|
||||
Assert.assertEquals(defaultPositionForHorizontalReachability,
|
||||
positionForHorizontalReachability);
|
||||
final int positionForVerticalReachability =
|
||||
mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability();
|
||||
final int defaultPositionForVerticalReachability =
|
||||
mContext.getResources().getInteger(
|
||||
R.integer.config_letterboxDefaultPositionForVerticalReachability);
|
||||
Assert.assertEquals(defaultPositionForVerticalReachability,
|
||||
positionForVerticalReachability);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_whenUpdatedWithNewValues_valuesAreWritten() {
|
||||
mLetterboxConfigurationPersister.setLetterboxPositionForHorizontalReachability(
|
||||
LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT);
|
||||
mLetterboxConfigurationPersister.setLetterboxPositionForVerticalReachability(
|
||||
LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP);
|
||||
waitForCompletion(mPersisterQueue);
|
||||
final int newPositionForHorizontalReachability =
|
||||
mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability();
|
||||
final int newPositionForVerticalReachability =
|
||||
mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability();
|
||||
Assert.assertEquals(LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT,
|
||||
newPositionForHorizontalReachability);
|
||||
Assert.assertEquals(LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP,
|
||||
newPositionForVerticalReachability);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_whenUpdatedWithNewValues_valuesAreReadAfterRestart() {
|
||||
final PersisterQueue firstPersisterQueue = new PersisterQueue();
|
||||
final LetterboxConfigurationPersister firstPersister = new LetterboxConfigurationPersister(
|
||||
mContext, () -> -1, () -> -1, mContext.getFilesDir(), firstPersisterQueue,
|
||||
mQueueState);
|
||||
firstPersister.start();
|
||||
firstPersister.setLetterboxPositionForHorizontalReachability(
|
||||
LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT);
|
||||
firstPersister.setLetterboxPositionForVerticalReachability(
|
||||
LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP);
|
||||
waitForCompletion(firstPersisterQueue);
|
||||
stopPersisterSafe(firstPersisterQueue);
|
||||
final PersisterQueue secondPersisterQueue = new PersisterQueue();
|
||||
final LetterboxConfigurationPersister secondPersister = new LetterboxConfigurationPersister(
|
||||
mContext, () -> -1, () -> -1, mContext.getFilesDir(), secondPersisterQueue,
|
||||
mQueueState);
|
||||
secondPersister.start();
|
||||
final int newPositionForHorizontalReachability =
|
||||
secondPersister.getLetterboxPositionForHorizontalReachability();
|
||||
final int newPositionForVerticalReachability =
|
||||
secondPersister.getLetterboxPositionForVerticalReachability();
|
||||
Assert.assertEquals(LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT,
|
||||
newPositionForHorizontalReachability);
|
||||
Assert.assertEquals(LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP,
|
||||
newPositionForVerticalReachability);
|
||||
deleteConfiguration(secondPersister, secondPersisterQueue);
|
||||
waitForCompletion(secondPersisterQueue);
|
||||
stopPersisterSafe(secondPersisterQueue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_whenUpdatedWithNewValuesAndDeleted_valuesAreDefaults() {
|
||||
mLetterboxConfigurationPersister.setLetterboxPositionForHorizontalReachability(
|
||||
LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT);
|
||||
mLetterboxConfigurationPersister.setLetterboxPositionForVerticalReachability(
|
||||
LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP);
|
||||
waitForCompletion(mPersisterQueue);
|
||||
final int newPositionForHorizontalReachability =
|
||||
mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability();
|
||||
final int newPositionForVerticalReachability =
|
||||
mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability();
|
||||
Assert.assertEquals(LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT,
|
||||
newPositionForHorizontalReachability);
|
||||
Assert.assertEquals(LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP,
|
||||
newPositionForVerticalReachability);
|
||||
deleteConfiguration(mLetterboxConfigurationPersister, mPersisterQueue);
|
||||
waitForCompletion(mPersisterQueue);
|
||||
final int positionForHorizontalReachability =
|
||||
mLetterboxConfigurationPersister.getLetterboxPositionForHorizontalReachability();
|
||||
final int defaultPositionForHorizontalReachability =
|
||||
mContext.getResources().getInteger(
|
||||
R.integer.config_letterboxDefaultPositionForHorizontalReachability);
|
||||
Assert.assertEquals(defaultPositionForHorizontalReachability,
|
||||
positionForHorizontalReachability);
|
||||
final int positionForVerticalReachability =
|
||||
mLetterboxConfigurationPersister.getLetterboxPositionForVerticalReachability();
|
||||
final int defaultPositionForVerticalReachability =
|
||||
mContext.getResources().getInteger(
|
||||
R.integer.config_letterboxDefaultPositionForVerticalReachability);
|
||||
Assert.assertEquals(defaultPositionForVerticalReachability,
|
||||
positionForVerticalReachability);
|
||||
}
|
||||
|
||||
private void stopPersisterSafe(PersisterQueue persisterQueue) {
|
||||
try {
|
||||
persisterQueue.stopPersisting();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForCompletion(PersisterQueue persisterQueue) {
|
||||
final long endTime = System.currentTimeMillis() + TIMEOUT;
|
||||
// The queue could be empty but the last item still processing and not completed. For this
|
||||
// reason the completion happens when there are not more items to process and the last one
|
||||
// has completed.
|
||||
while (System.currentTimeMillis() < endTime && (!isQueueEmpty(persisterQueue)
|
||||
|| !hasLastItemCompleted())) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ie) { /* Nope */}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isQueueEmpty(PersisterQueue persisterQueue) {
|
||||
return persisterQueue.findLastItem(
|
||||
writeQueueItem -> true, PersisterQueue.WriteQueueItem.class) != null;
|
||||
}
|
||||
|
||||
private boolean hasLastItemCompleted() {
|
||||
return mQueueState.isEmpty();
|
||||
}
|
||||
|
||||
private void deleteConfiguration(LetterboxConfigurationPersister persister,
|
||||
PersisterQueue persisterQueue) {
|
||||
final AtomicFile fileToDelete = new AtomicFile(
|
||||
new File(mConfigFolder, LETTERBOX_CONFIGURATION_FILENAME));
|
||||
persisterQueue.addItem(
|
||||
new DeleteFileCommand(fileToDelete, mQueueState.andThen(
|
||||
s -> persister.useDefaultValue())), true);
|
||||
}
|
||||
|
||||
private static class DeleteFileCommand implements
|
||||
PersisterQueue.WriteQueueItem<DeleteFileCommand> {
|
||||
|
||||
@NonNull
|
||||
private final AtomicFile mFileToDelete;
|
||||
@Nullable
|
||||
private final Consumer<String> mOnComplete;
|
||||
|
||||
DeleteFileCommand(@NonNull AtomicFile fileToDelete, Consumer<String> onComplete) {
|
||||
mFileToDelete = fileToDelete;
|
||||
mOnComplete = onComplete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process() {
|
||||
mFileToDelete.delete();
|
||||
if (mOnComplete != null) {
|
||||
mOnComplete.accept("DeleteFileCommand");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Contains the current length of the persister queue
|
||||
private static class QueueState implements Consumer<String> {
|
||||
|
||||
// The current number of commands in the queue
|
||||
@VisibleForTesting
|
||||
private final AtomicInteger mCounter = new AtomicInteger(0);
|
||||
|
||||
@Override
|
||||
public void accept(String s) {
|
||||
mCounter.decrementAndGet();
|
||||
}
|
||||
|
||||
void onItemAdded() {
|
||||
mCounter.incrementAndGet();
|
||||
}
|
||||
|
||||
boolean isEmpty() {
|
||||
return mCounter.get() == 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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 androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
|
||||
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER;
|
||||
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT;
|
||||
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT;
|
||||
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM;
|
||||
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER;
|
||||
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
public class LetterboxConfigurationTest {
|
||||
|
||||
private LetterboxConfiguration mLetterboxConfiguration;
|
||||
private LetterboxConfigurationPersister mLetterboxConfigurationPersister;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
Context context = getInstrumentation().getTargetContext();
|
||||
mLetterboxConfigurationPersister = mock(LetterboxConfigurationPersister.class);
|
||||
mLetterboxConfiguration = new LetterboxConfiguration(context,
|
||||
mLetterboxConfigurationPersister);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_whenReadingValues_storeIsInvoked() {
|
||||
mLetterboxConfiguration.getLetterboxPositionForHorizontalReachability();
|
||||
verify(mLetterboxConfigurationPersister).getLetterboxPositionForHorizontalReachability();
|
||||
mLetterboxConfiguration.getLetterboxPositionForVerticalReachability();
|
||||
verify(mLetterboxConfigurationPersister).getLetterboxPositionForVerticalReachability();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_whenSettingValues_updateConfigurationIsInvoked() {
|
||||
mLetterboxConfiguration.movePositionForHorizontalReachabilityToNextRightStop();
|
||||
verify(mLetterboxConfigurationPersister).setLetterboxPositionForHorizontalReachability(
|
||||
anyInt());
|
||||
mLetterboxConfiguration.movePositionForVerticalReachabilityToNextBottomStop();
|
||||
verify(mLetterboxConfigurationPersister).setLetterboxPositionForVerticalReachability(
|
||||
anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_whenMovedHorizontally_updatePositionAccordingly() {
|
||||
// Starting from center
|
||||
assertForHorizontalMove(
|
||||
/* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER,
|
||||
/* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT,
|
||||
/* expectedTime */ 1,
|
||||
LetterboxConfiguration::movePositionForHorizontalReachabilityToNextLeftStop);
|
||||
assertForHorizontalMove(
|
||||
/* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER,
|
||||
/* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT,
|
||||
/* expectedTime */ 1,
|
||||
LetterboxConfiguration::movePositionForHorizontalReachabilityToNextRightStop);
|
||||
// Starting from left
|
||||
assertForHorizontalMove(
|
||||
/* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT,
|
||||
/* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT,
|
||||
/* expectedTime */ 2,
|
||||
LetterboxConfiguration::movePositionForHorizontalReachabilityToNextLeftStop);
|
||||
assertForHorizontalMove(
|
||||
/* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_LEFT,
|
||||
/* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER,
|
||||
/* expectedTime */ 1,
|
||||
LetterboxConfiguration::movePositionForHorizontalReachabilityToNextRightStop);
|
||||
// Starting from right
|
||||
assertForHorizontalMove(
|
||||
/* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT,
|
||||
/* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT,
|
||||
/* expectedTime */ 2,
|
||||
LetterboxConfiguration::movePositionForHorizontalReachabilityToNextRightStop);
|
||||
assertForHorizontalMove(
|
||||
/* from */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_RIGHT,
|
||||
/* expected */ LETTERBOX_HORIZONTAL_REACHABILITY_POSITION_CENTER,
|
||||
/* expectedTime */ 2,
|
||||
LetterboxConfiguration::movePositionForHorizontalReachabilityToNextLeftStop);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_whenMovedVertically_updatePositionAccordingly() {
|
||||
// Starting from center
|
||||
assertForVerticalMove(
|
||||
/* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER,
|
||||
/* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM,
|
||||
/* expectedTime */ 1,
|
||||
LetterboxConfiguration::movePositionForVerticalReachabilityToNextBottomStop);
|
||||
assertForVerticalMove(
|
||||
/* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER,
|
||||
/* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP,
|
||||
/* expectedTime */ 1,
|
||||
LetterboxConfiguration::movePositionForVerticalReachabilityToNextTopStop);
|
||||
// Starting from top
|
||||
assertForVerticalMove(
|
||||
/* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP,
|
||||
/* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER,
|
||||
/* expectedTime */ 1,
|
||||
LetterboxConfiguration::movePositionForVerticalReachabilityToNextBottomStop);
|
||||
assertForVerticalMove(
|
||||
/* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP,
|
||||
/* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_TOP,
|
||||
/* expectedTime */ 2,
|
||||
LetterboxConfiguration::movePositionForVerticalReachabilityToNextTopStop);
|
||||
// Starting from bottom
|
||||
assertForVerticalMove(
|
||||
/* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM,
|
||||
/* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_CENTER,
|
||||
/* expectedTime */ 2,
|
||||
LetterboxConfiguration::movePositionForVerticalReachabilityToNextTopStop);
|
||||
assertForVerticalMove(
|
||||
/* from */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM,
|
||||
/* expected */ LETTERBOX_VERTICAL_REACHABILITY_POSITION_BOTTOM,
|
||||
/* expectedTime */ 2,
|
||||
LetterboxConfiguration::movePositionForVerticalReachabilityToNextBottomStop);
|
||||
}
|
||||
|
||||
private void assertForHorizontalMove(int from, int expected, int expectedTime,
|
||||
Consumer<LetterboxConfiguration> move) {
|
||||
// We are in the current position
|
||||
when(mLetterboxConfiguration.getLetterboxPositionForHorizontalReachability())
|
||||
.thenReturn(from);
|
||||
move.accept(mLetterboxConfiguration);
|
||||
verify(mLetterboxConfigurationPersister,
|
||||
times(expectedTime)).setLetterboxPositionForHorizontalReachability(
|
||||
expected);
|
||||
}
|
||||
|
||||
private void assertForVerticalMove(int from, int expected, int expectedTime,
|
||||
Consumer<LetterboxConfiguration> move) {
|
||||
// We are in the current position
|
||||
when(mLetterboxConfiguration.getLetterboxPositionForVerticalReachability())
|
||||
.thenReturn(from);
|
||||
move.accept(mLetterboxConfiguration);
|
||||
verify(mLetterboxConfigurationPersister,
|
||||
times(expectedTime)).setLetterboxPositionForVerticalReachability(
|
||||
expected);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user