Merge "[Media Rec] Update the background to be colorSurface." into tm-dev
diff --git a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
index 53a3889..c572f82 100644
--- a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
+++ b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java
@@ -32,8 +32,6 @@
import android.annotation.UserHandleAware;
import android.content.Context;
-import com.android.internal.util.FrameworkStatsLog;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
@@ -453,62 +451,6 @@
@Retention(RetentionPolicy.SOURCE)
public @interface ReasonCode {}
- private static final int EXEMPTION_REASON_SYSTEM_UID = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_SYSTEM_UID;
- private static final int EXEMPTION_REASON_ALLOWLISTED_PACKAGE = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_ALLOWLISTED_PACKAGE;
- private static final int EXEMPTION_REASON_COMPANION_DEVICE_MANAGER = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_COMPANION_DEVICE_MANAGER;
- private static final int EXEMPTION_REASON_DEVICE_DEMO_MODE = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_DEVICE_DEMO_MODE;
- private static final int EXEMPTION_REASON_DEVICE_OWNER = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_DEVICE_OWNER;
- private static final int EXEMPTION_REASON_PROFILE_OWNER = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_PROFILE_OWNER;
- private static final int EXEMPTION_REASON_PROC_STATE_PERSISTENT = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_PROC_STATE_PERSISTENT;
- private static final int EXEMPTION_REASON_PROC_STATE_PERSISTENT_UI = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_PROC_STATE_PERSISTENT_UI;
- private static final int EXEMPTION_REASON_OP_ACTIVATE_VPN = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_OP_ACTIVATE_VPN;
- private static final int EXEMPTION_REASON_OP_ACTIVATE_PLATFORM_VPN = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_OP_ACTIVATE_PLATFORM_VPN;
- private static final int EXEMPTION_REASON_SYSTEM_MODULE = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_SYSTEM_MODULE;
- private static final int EXEMPTION_REASON_CARRIER_PRIVILEGED_APP = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_CARRIER_PRIVILEGED_APP;
- private static final int EXEMPTION_REASON_SYSTEM_ALLOW_LISTED = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_SYSTEM_ALLOW_LISTED;
- private static final int EXEMPTION_REASON_ROLE_DIALER = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_ROLE_DIALER;
- private static final int EXEMPTION_REASON_ROLE_EMERGENCY = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_ROLE_EMERGENCY;
- private static final int EXEMPTION_REASON_DENIED = FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_DENIED;
- /**
- * List of exemption reason codes used for statsd logging in AppBackgroundRestrictionsInfo atom.
- * @hide
- */
- @IntDef(prefix = { "EXEMPTION_REASON_" }, value = {
- EXEMPTION_REASON_SYSTEM_UID,
- EXEMPTION_REASON_ALLOWLISTED_PACKAGE,
- EXEMPTION_REASON_COMPANION_DEVICE_MANAGER,
- EXEMPTION_REASON_DEVICE_DEMO_MODE,
- EXEMPTION_REASON_DEVICE_OWNER,
- EXEMPTION_REASON_PROFILE_OWNER,
- EXEMPTION_REASON_PROC_STATE_PERSISTENT,
- EXEMPTION_REASON_PROC_STATE_PERSISTENT_UI,
- EXEMPTION_REASON_OP_ACTIVATE_VPN,
- EXEMPTION_REASON_OP_ACTIVATE_PLATFORM_VPN,
- EXEMPTION_REASON_SYSTEM_MODULE,
- EXEMPTION_REASON_CARRIER_PRIVILEGED_APP,
- EXEMPTION_REASON_SYSTEM_ALLOW_LISTED,
- EXEMPTION_REASON_ROLE_DIALER,
- EXEMPTION_REASON_ROLE_EMERGENCY,
- EXEMPTION_REASON_DENIED,
- })
- public @interface ExemptionReason {}
-
/**
* @hide
*/
@@ -679,40 +621,40 @@
* @hide
* @return the reason code mapped to statsd for the AppBackgroundRestrictionsInfo atom.
*/
- public static @ExemptionReason int getExemptionReasonForStatsd(@ReasonCode int reasonCode) {
+ public static int getExemptionReasonForStatsd(@ReasonCode int reasonCode) {
switch (reasonCode) {
case REASON_SYSTEM_UID:
- return EXEMPTION_REASON_SYSTEM_UID;
+ return AppBackgroundRestrictionsInfo.REASON_SYSTEM_UID;
case REASON_ALLOWLISTED_PACKAGE:
- return EXEMPTION_REASON_ALLOWLISTED_PACKAGE;
+ return AppBackgroundRestrictionsInfo.REASON_ALLOWLISTED_PACKAGE;
case REASON_COMPANION_DEVICE_MANAGER:
- return EXEMPTION_REASON_COMPANION_DEVICE_MANAGER;
+ return AppBackgroundRestrictionsInfo.REASON_COMPANION_DEVICE_MANAGER;
case REASON_DEVICE_DEMO_MODE:
- return EXEMPTION_REASON_DEVICE_DEMO_MODE;
+ return AppBackgroundRestrictionsInfo.REASON_DEVICE_DEMO_MODE;
case REASON_DEVICE_OWNER:
- return EXEMPTION_REASON_DEVICE_OWNER;
+ return AppBackgroundRestrictionsInfo.REASON_DEVICE_OWNER;
case REASON_PROFILE_OWNER:
- return EXEMPTION_REASON_PROFILE_OWNER;
+ return AppBackgroundRestrictionsInfo.REASON_PROFILE_OWNER;
case REASON_PROC_STATE_PERSISTENT:
- return EXEMPTION_REASON_PROC_STATE_PERSISTENT;
+ return AppBackgroundRestrictionsInfo.REASON_PROC_STATE_PERSISTENT;
case REASON_PROC_STATE_PERSISTENT_UI:
- return EXEMPTION_REASON_PROC_STATE_PERSISTENT_UI;
+ return AppBackgroundRestrictionsInfo.REASON_PROC_STATE_PERSISTENT_UI;
case REASON_OP_ACTIVATE_VPN:
- return EXEMPTION_REASON_OP_ACTIVATE_VPN;
+ return AppBackgroundRestrictionsInfo.REASON_OP_ACTIVATE_VPN;
case REASON_OP_ACTIVATE_PLATFORM_VPN:
- return EXEMPTION_REASON_OP_ACTIVATE_PLATFORM_VPN;
+ return AppBackgroundRestrictionsInfo.REASON_OP_ACTIVATE_PLATFORM_VPN;
case REASON_SYSTEM_MODULE:
- return EXEMPTION_REASON_SYSTEM_MODULE;
+ return AppBackgroundRestrictionsInfo.REASON_SYSTEM_MODULE;
case REASON_CARRIER_PRIVILEGED_APP:
- return EXEMPTION_REASON_CARRIER_PRIVILEGED_APP;
+ return AppBackgroundRestrictionsInfo.REASON_CARRIER_PRIVILEGED_APP;
case REASON_SYSTEM_ALLOW_LISTED:
- return EXEMPTION_REASON_SYSTEM_ALLOW_LISTED;
+ return AppBackgroundRestrictionsInfo.REASON_SYSTEM_ALLOW_LISTED;
case REASON_ROLE_DIALER:
- return EXEMPTION_REASON_ROLE_DIALER;
+ return AppBackgroundRestrictionsInfo.REASON_ROLE_DIALER;
case REASON_ROLE_EMERGENCY:
- return EXEMPTION_REASON_ROLE_EMERGENCY;
+ return AppBackgroundRestrictionsInfo.REASON_ROLE_EMERGENCY;
default:
- return EXEMPTION_REASON_DENIED;
+ return AppBackgroundRestrictionsInfo.REASON_DENIED;
}
}
diff --git a/core/java/android/accessibilityservice/InputMethod.java b/core/java/android/accessibilityservice/InputMethod.java
index 647a266..79bac9b 100644
--- a/core/java/android/accessibilityservice/InputMethod.java
+++ b/core/java/android/accessibilityservice/InputMethod.java
@@ -181,14 +181,14 @@
final void startInput(@Nullable InputConnection ic, @NonNull EditorInfo attribute) {
Log.v(LOG_TAG, "startInput(): editor=" + attribute);
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.startInput");
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AccessibilityService.startInput");
doStartInput(ic, attribute, false /* restarting */);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
final void restartInput(@Nullable InputConnection ic, @NonNull EditorInfo attribute) {
Log.v(LOG_TAG, "restartInput(): editor=" + attribute);
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.restartInput");
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AccessibilityService.restartInput");
doStartInput(ic, attribute, true /* restarting */);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 6be6f9d..96b1abb 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -1274,6 +1274,7 @@
private class SurfaceViewPositionUpdateListener implements RenderNode.PositionUpdateListener {
private final int mRtSurfaceWidth;
private final int mRtSurfaceHeight;
+ private boolean mRtFirst = true;
private final SurfaceControl.Transaction mPositionChangedTransaction =
new SurfaceControl.Transaction();
@@ -1284,14 +1285,15 @@
@Override
public void positionChanged(long frameNumber, int left, int top, int right, int bottom) {
- if (mRTLastReportedPosition.left == left
+ if (!mRtFirst && (mRTLastReportedPosition.left == left
&& mRTLastReportedPosition.top == top
&& mRTLastReportedPosition.right == right
&& mRTLastReportedPosition.bottom == bottom
&& mRTLastReportedSurfaceSize.x == mRtSurfaceWidth
- && mRTLastReportedSurfaceSize.y == mRtSurfaceHeight) {
+ && mRTLastReportedSurfaceSize.y == mRtSurfaceHeight)) {
return;
}
+ mRtFirst = false;
try {
if (DEBUG_POSITION) {
Log.d(TAG, String.format(
diff --git a/core/java/android/window/BackEvent.java b/core/java/android/window/BackEvent.java
index 14985c9..1024e2e 100644
--- a/core/java/android/window/BackEvent.java
+++ b/core/java/android/window/BackEvent.java
@@ -46,8 +46,8 @@
@Retention(RetentionPolicy.SOURCE)
public @interface SwipeEdge{}
- private final int mTouchX;
- private final int mTouchY;
+ private final float mTouchX;
+ private final float mTouchY;
private final float mProgress;
@SwipeEdge
@@ -58,14 +58,14 @@
/**
* Creates a new {@link BackEvent} instance.
*
- * @param touchX Absolute X location of the touch point.
- * @param touchY Absolute Y location of the touch point.
+ * @param touchX Absolute X location of the touch point of this event.
+ * @param touchY Absolute Y location of the touch point of this event.
* @param progress Value between 0 and 1 on how far along the back gesture is.
* @param swipeEdge Indicates which edge the swipe starts from.
* @param departingAnimationTarget The remote animation target of the departing application
* window.
*/
- public BackEvent(int touchX, int touchY, float progress, @SwipeEdge int swipeEdge,
+ public BackEvent(float touchX, float touchY, float progress, @SwipeEdge int swipeEdge,
@Nullable RemoteAnimationTarget departingAnimationTarget) {
mTouchX = touchX;
mTouchY = touchY;
@@ -75,8 +75,8 @@
}
private BackEvent(@NonNull Parcel in) {
- mTouchX = in.readInt();
- mTouchY = in.readInt();
+ mTouchX = in.readFloat();
+ mTouchY = in.readFloat();
mProgress = in.readFloat();
mSwipeEdge = in.readInt();
mDepartingAnimationTarget = in.readTypedObject(RemoteAnimationTarget.CREATOR);
@@ -101,8 +101,8 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mTouchX);
- dest.writeInt(mTouchY);
+ dest.writeFloat(mTouchX);
+ dest.writeFloat(mTouchY);
dest.writeFloat(mProgress);
dest.writeInt(mSwipeEdge);
dest.writeTypedObject(mDepartingAnimationTarget, flags);
@@ -118,14 +118,14 @@
/**
* Returns the absolute X location of the touch point.
*/
- public int getTouchX() {
+ public float getTouchX() {
return mTouchX;
}
/**
* Returns the absolute Y location of the touch point.
*/
- public int getTouchY() {
+ public float getTouchY() {
return mTouchY;
}
diff --git a/core/java/com/android/internal/policy/ForceShowNavigationBarSettingsObserver.java b/core/java/com/android/internal/policy/KidsModeSettingsObserver.java
similarity index 85%
rename from core/java/com/android/internal/policy/ForceShowNavigationBarSettingsObserver.java
rename to core/java/com/android/internal/policy/KidsModeSettingsObserver.java
index 75dce5a..8a1d407 100644
--- a/core/java/com/android/internal/policy/ForceShowNavigationBarSettingsObserver.java
+++ b/core/java/com/android/internal/policy/KidsModeSettingsObserver.java
@@ -24,17 +24,17 @@
import android.provider.Settings;
/**
- * A ContentObserver for listening force show navigation bar relative setting keys:
+ * A ContentObserver for listening kids mode relative setting keys:
* - {@link Settings.Secure#NAVIGATION_MODE}
- * - {@link Settings.Secure#NAV_BAR_FORCE_VISIBLE}
+ * - {@link Settings.Secure#NAV_BAR_KIDS_MODE}
*
* @hide
*/
-public class ForceShowNavigationBarSettingsObserver extends ContentObserver {
+public class KidsModeSettingsObserver extends ContentObserver {
private Context mContext;
private Runnable mOnChangeRunnable;
- public ForceShowNavigationBarSettingsObserver(Handler handler, Context context) {
+ public KidsModeSettingsObserver(Handler handler, Context context) {
super(handler);
mContext = context;
}
@@ -52,7 +52,7 @@
Settings.Secure.getUriFor(Settings.Secure.NAVIGATION_MODE),
false, this, UserHandle.USER_ALL);
r.registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_FORCE_VISIBLE),
+ Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_KIDS_MODE),
false, this, UserHandle.USER_ALL);
}
@@ -78,6 +78,6 @@
return Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.NAVIGATION_MODE, 0, UserHandle.USER_CURRENT) == 0
&& Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.NAV_BAR_FORCE_VISIBLE, 0, UserHandle.USER_CURRENT) == 1;
+ Settings.Secure.NAV_BAR_KIDS_MODE, 0, UserHandle.USER_CURRENT) == 1;
}
}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4284e7e..757f409 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -5682,8 +5682,8 @@
restricted level.
-->
<array name="config_bg_current_drain_threshold_to_bg_restricted">
- <item>10.0</item> <!-- regular device -->
- <item>20.0</item> <!-- low ram device -->
+ <item>4.0</item> <!-- regular device -->
+ <item>8.0</item> <!-- low ram device -->
</array>
<!-- The background current drain monitoring window size. -->
@@ -5744,6 +5744,12 @@
-->
<bool name="config_bg_prompt_fgs_with_noti_to_bg_restricted">false</bool>
+ <!-- The behavior when the system detects it's abusive, should the system prompt the user
+ to put it into the bg restricted level.
+ True - we'll show the prompt to user, False - we'll not show it.
+ -->
+ <bool name="config_bg_prompt_abusive_apps_to_bg_restricted">false</bool>
+
<!-- The types of state where we'll exempt its battery usage during that state.
The state here must be one or a combination of STATE_TYPE_* in BaseAppStateTracker.
-->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 41d340f..3334822 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4765,6 +4765,7 @@
<java-symbol type="integer" name="config_bg_current_drain_media_playback_min_duration" />
<java-symbol type="integer" name="config_bg_current_drain_location_min_duration" />
<java-symbol type="bool" name="config_bg_prompt_fgs_with_noti_to_bg_restricted" />
+ <java-symbol type="bool" name="config_bg_prompt_abusive_apps_to_bg_restricted" />
<java-symbol type="integer" name="config_bg_current_drain_exempted_types" />
<java-symbol type="bool" name="config_bg_current_drain_high_threshold_by_bg_location" />
<java-symbol type="drawable" name="ic_swap_horiz" />
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 42ac195..cfd0624 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -301,7 +301,8 @@
int backType = mBackNavigationInfo.getType();
RemoteAnimationTarget animationTarget = mBackNavigationInfo.getDepartingAnimationTarget();
- BackEvent backEvent = new BackEvent(0, 0, progress, swipeEdge, animationTarget);
+ BackEvent backEvent = new BackEvent(
+ event.getX(), event.getY(), progress, swipeEdge, animationTarget);
IOnBackInvokedCallback targetCallback = null;
if (shouldDispatchToLauncher(backType)) {
targetCallback = mBackToLauncherCallback;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index b6fb828..5ef2413 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -385,7 +385,9 @@
mMainExecutor.execute(() -> {
int expandedId = INVALID_TASK_ID;
if (mStackView != null && mStackView.getExpandedBubble() != null
- && isStackExpanded() && !mStackView.isExpansionAnimating()) {
+ && isStackExpanded()
+ && !mStackView.isExpansionAnimating()
+ && !mStackView.isSwitchAnimating()) {
expandedId = mStackView.getExpandedBubble().getTaskId();
}
if (expandedId != INVALID_TASK_ID && expandedId != taskId) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index cb88203..b7c5eb0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -1608,6 +1608,13 @@
}
/**
+ * Whether the stack of bubbles is animating a switch between bubbles.
+ */
+ public boolean isSwitchAnimating() {
+ return mIsBubbleSwitchAnimating;
+ }
+
+ /**
* The {@link Bubble} that is expanded, null if one does not exist.
*/
@VisibleForTesting
@@ -2467,6 +2474,10 @@
private void dismissBubbleIfExists(@Nullable BubbleViewProvider bubble) {
if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) {
+ if (mIsExpanded && mBubbleData.getBubbles().size() > 1) {
+ // If we have more than 1 bubble we will perform the switch animation
+ mIsBubbleSwitchAnimating = true;
+ }
mBubbleData.dismissBubbleWithKey(bubble.getKey(), Bubbles.DISMISS_USER_GESTURE);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
index 003c559..4bb5805 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizer.java
@@ -40,7 +40,7 @@
import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.policy.ForceShowNavigationBarSettingsObserver;
+import com.android.internal.policy.KidsModeSettingsObserver;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayInsetsController;
@@ -85,7 +85,7 @@
private int mDisplayWidth;
private int mDisplayHeight;
- private ForceShowNavigationBarSettingsObserver mForceShowNavigationBarSettingsObserver;
+ private KidsModeSettingsObserver mKidsModeSettingsObserver;
private boolean mEnabled;
DisplayController.OnDisplaysChangedListener mOnDisplaysChangedListener =
@@ -138,14 +138,14 @@
DisplayController displayController,
DisplayInsetsController displayInsetsController,
Optional<RecentTasksController> recentTasks,
- ForceShowNavigationBarSettingsObserver forceShowNavigationBarSettingsObserver) {
+ KidsModeSettingsObserver kidsModeSettingsObserver) {
super(taskOrganizerController, mainExecutor, context, /* compatUI= */ null, recentTasks);
mContext = context;
mMainHandler = mainHandler;
mSyncQueue = syncTransactionQueue;
mDisplayController = displayController;
mDisplayInsetsController = displayInsetsController;
- mForceShowNavigationBarSettingsObserver = forceShowNavigationBarSettingsObserver;
+ mKidsModeSettingsObserver = kidsModeSettingsObserver;
}
public KidsModeTaskOrganizer(
@@ -169,13 +169,13 @@
*/
public void initialize(StartingWindowController startingWindowController) {
initStartingWindow(startingWindowController);
- if (mForceShowNavigationBarSettingsObserver == null) {
- mForceShowNavigationBarSettingsObserver = new ForceShowNavigationBarSettingsObserver(
+ if (mKidsModeSettingsObserver == null) {
+ mKidsModeSettingsObserver = new KidsModeSettingsObserver(
mMainHandler, mContext);
}
- mForceShowNavigationBarSettingsObserver.setOnChangeRunnable(() -> updateKidsModeState());
+ mKidsModeSettingsObserver.setOnChangeRunnable(() -> updateKidsModeState());
updateKidsModeState();
- mForceShowNavigationBarSettingsObserver.register();
+ mKidsModeSettingsObserver.register();
}
@Override
@@ -211,7 +211,7 @@
@VisibleForTesting
void updateKidsModeState() {
- final boolean enabled = mForceShowNavigationBarSettingsObserver.isEnabled();
+ final boolean enabled = mKidsModeSettingsObserver.isEnabled();
if (mEnabled == enabled) {
return;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index b6635f3..9dc861c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -924,6 +924,7 @@
removeContentOverlay(mSwipePipToHomeOverlay, null /* callback */);
mSwipePipToHomeOverlay = null;
}
+ resetShadowRadius();
mPipTransitionState.setInSwipePipToHomeTransition(false);
mPictureInPictureParams = null;
mPipTransitionState.setTransitionState(PipTransitionState.UNDEFINED);
@@ -1569,13 +1570,28 @@
// Avoid double removal, which is fatal.
return;
}
- final SurfaceControl.Transaction tx =
- mSurfaceControlTransactionFactory.getTransaction();
+ final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
tx.remove(surface);
tx.apply();
if (callback != null) callback.run();
}
+ private void resetShadowRadius() {
+ if (mPipTransitionState.getTransitionState() == PipTransitionState.UNDEFINED) {
+ // mLeash is undefined when in PipTransitionState.UNDEFINED
+ return;
+ }
+ final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
+ tx.setShadowRadius(mLeash, 0f);
+ tx.apply();
+ }
+
+ @VisibleForTesting
+ public void setSurfaceControlTransactionFactory(
+ PipSurfaceTransactionHelper.SurfaceControlTransactionFactory factory) {
+ mSurfaceControlTransactionFactory = factory;
+ }
+
/**
* Dumps internal states.
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 10dfdc3..dd2634c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -414,7 +414,7 @@
}
RemoteAnimationTarget[] onGoingToRecentsLegacy(boolean cancel, RemoteAnimationTarget[] apps) {
- if (ENABLE_SHELL_TRANSITIONS || apps.length < 2) return null;
+ if (ENABLE_SHELL_TRANSITIONS || !isSplitScreenVisible()) return null;
// TODO(b/206487881): Integrate this with shell transition.
SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
if (mSplitTasksContainerLayer != null) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java
index ff6dfdb..5526d5b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/kidsmode/KidsModeTaskOrganizerTest.java
@@ -44,7 +44,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.internal.policy.ForceShowNavigationBarSettingsObserver;
+import com.android.internal.policy.KidsModeSettingsObserver;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.ShellExecutor;
@@ -72,7 +72,7 @@
@Mock private SurfaceControl mLeash;
@Mock private WindowContainerToken mToken;
@Mock private WindowContainerTransaction mTransaction;
- @Mock private ForceShowNavigationBarSettingsObserver mObserver;
+ @Mock private KidsModeSettingsObserver mObserver;
@Mock private StartingWindowController mStartingWindowController;
@Mock private DisplayInsetsController mDisplayInsetsController;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
index 8ef1df6..c685fdc 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
@@ -30,7 +30,6 @@
import static org.mockito.Mockito.verify;
import android.app.TaskInfo;
-import android.graphics.Matrix;
import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -104,7 +103,7 @@
final PipAnimationController.PipTransitionAnimator oldAnimator = mPipAnimationController
.getAnimator(mTaskInfo, mLeash, baseValue, startValue, endValue1, null,
TRANSITION_DIRECTION_TO_PIP, 0, ROTATION_0);
- oldAnimator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
+ oldAnimator.setSurfaceControlTransactionFactory(PipDummySurfaceControlTx::new);
oldAnimator.start();
final PipAnimationController.PipTransitionAnimator newAnimator = mPipAnimationController
@@ -134,7 +133,7 @@
@Test
public void pipTransitionAnimator_rotatedEndValue() {
- final DummySurfaceControlTx tx = new DummySurfaceControlTx();
+ final PipDummySurfaceControlTx tx = new PipDummySurfaceControlTx();
final Rect startBounds = new Rect(200, 700, 400, 800);
final Rect endBounds = new Rect(0, 0, 500, 1000);
// Fullscreen to PiP.
@@ -184,7 +183,7 @@
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
.getAnimator(mTaskInfo, mLeash, baseValue, startValue, endValue, null,
TRANSITION_DIRECTION_TO_PIP, 0, ROTATION_0);
- animator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
+ animator.setSurfaceControlTransactionFactory(PipDummySurfaceControlTx::new);
animator.setPipAnimationCallback(mPipAnimationCallback);
@@ -201,44 +200,4 @@
verify(mPipAnimationCallback).onPipAnimationEnd(eq(mTaskInfo),
any(SurfaceControl.Transaction.class), eq(animator));
}
-
- /**
- * A dummy {@link SurfaceControl.Transaction} class.
- * This is created as {@link Mock} does not support method chaining.
- */
- public static class DummySurfaceControlTx extends SurfaceControl.Transaction {
- @Override
- public SurfaceControl.Transaction setAlpha(SurfaceControl leash, float alpha) {
- return this;
- }
-
- @Override
- public SurfaceControl.Transaction setPosition(SurfaceControl leash, float x, float y) {
- return this;
- }
-
- @Override
- public SurfaceControl.Transaction setWindowCrop(SurfaceControl leash, int w, int h) {
- return this;
- }
-
- @Override
- public SurfaceControl.Transaction setCornerRadius(SurfaceControl leash, float radius) {
- return this;
- }
-
- @Override
- public SurfaceControl.Transaction setMatrix(SurfaceControl leash, Matrix matrix,
- float[] float9) {
- return this;
- }
-
- @Override
- public SurfaceControl.Transaction setFrameTimelineVsync(long frameTimelineVsyncId) {
- return this;
- }
-
- @Override
- public void apply() {}
- }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipDummySurfaceControlTx.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipDummySurfaceControlTx.java
new file mode 100644
index 0000000..ccf8f6e
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipDummySurfaceControlTx.java
@@ -0,0 +1,66 @@
+/*
+ * 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.pip;
+
+import android.graphics.Matrix;
+import android.view.SurfaceControl;
+
+/**
+ * A dummy {@link SurfaceControl.Transaction} class for testing purpose and supports
+ * method chaining.
+ */
+public class PipDummySurfaceControlTx extends SurfaceControl.Transaction {
+ @Override
+ public SurfaceControl.Transaction setAlpha(SurfaceControl leash, float alpha) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setPosition(SurfaceControl leash, float x, float y) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setWindowCrop(SurfaceControl leash, int w, int h) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setCornerRadius(SurfaceControl leash, float radius) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setShadowRadius(SurfaceControl leash, float radius) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setMatrix(SurfaceControl leash, Matrix matrix,
+ float[] float9) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setFrameTimelineVsync(long frameTimelineVsyncId) {
+ return this;
+ }
+
+ @Override
+ public void apply() {}
+}
+
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
index 14d9fb9..def9ad2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
@@ -242,6 +242,7 @@
mPipBoundsState.setDisplayLayout(new DisplayLayout(info,
mContext.getResources(), true, true));
mSpiedPipTaskOrganizer.setOneShotAnimationType(PipAnimationController.ANIM_TYPE_ALPHA);
+ mSpiedPipTaskOrganizer.setSurfaceControlTransactionFactory(PipDummySurfaceControlTx::new);
doNothing().when(mSpiedPipTaskOrganizer).enterPipWithAlphaAnimation(any(), anyLong());
doNothing().when(mSpiedPipTaskOrganizer).scheduleAnimateResizePip(any(), anyInt(), any());
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtils.java
index 6535665..d97c819 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtils.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.os.Build;
-import android.os.Bundle;
import android.os.UserManager;
import android.util.Log;
@@ -37,13 +36,9 @@
* @return whether the device is permitted to use Wi-Fi Tethering
*/
public static boolean isWifiTetheringAllowed(Context context) {
- final UserManager userManager = context.getSystemService(UserManager.class);
- final Bundle restrictions = userManager.getUserRestrictions();
- if (isAtLeastT() && restrictions.getBoolean(UserManager.DISALLOW_WIFI_TETHERING)) {
- Log.i(TAG, "Wi-Fi Tethering isn't available due to user restriction.");
- return false;
- }
- return true;
+ if (!hasUserRestrictionFromT(context, UserManager.DISALLOW_WIFI_TETHERING)) return true;
+ Log.w(TAG, "Wi-Fi Tethering isn't available due to user restriction.");
+ return false;
}
/**
@@ -53,13 +48,9 @@
* @return whether the device is permitted to use Wi-Fi Direct
*/
public static boolean isWifiDirectAllowed(Context context) {
- final UserManager userManager = context.getSystemService(UserManager.class);
- final Bundle restrictions = userManager.getUserRestrictions();
- if (isAtLeastT() && restrictions.getBoolean(UserManager.DISALLOW_WIFI_DIRECT)) {
- Log.i(TAG, "Wi-Fi Direct isn't available due to user restriction.");
- return false;
- }
- return true;
+ if (!hasUserRestrictionFromT(context, UserManager.DISALLOW_WIFI_DIRECT)) return true;
+ Log.w(TAG, "Wi-Fi Direct isn't available due to user restriction.");
+ return false;
}
/**
@@ -69,13 +60,9 @@
* @return whether the device is permitted to add new Wi-Fi config
*/
public static boolean isAddWifiConfigAllowed(Context context) {
- final UserManager userManager = context.getSystemService(UserManager.class);
- final Bundle restrictions = userManager.getUserRestrictions();
- if (isAtLeastT() && restrictions.getBoolean(UserManager.DISALLOW_ADD_WIFI_CONFIG)) {
- Log.i(TAG, "Wi-Fi Add network isn't available due to user restriction.");
- return false;
- }
- return true;
+ if (!hasUserRestrictionFromT(context, UserManager.DISALLOW_ADD_WIFI_CONFIG)) return true;
+ Log.w(TAG, "Wi-Fi Add network isn't available due to user restriction.");
+ return false;
}
/**
@@ -98,7 +85,7 @@
return userManager.hasUserRestriction(restrictionKey);
}
- @ChecksSdkIntAtLeast(api=Build.VERSION_CODES.TIRAMISU)
+ @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
private static boolean isAtLeastT() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU;
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtilsTest.java
index e9326dd..af9e69a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtilsTest.java
@@ -15,122 +15,91 @@
*/
package com.android.settingslib.wifi;
+import static android.os.UserManager.DISALLOW_ADD_WIFI_CONFIG;
import static android.os.UserManager.DISALLOW_CHANGE_WIFI_STATE;
+import static android.os.UserManager.DISALLOW_WIFI_DIRECT;
+import static android.os.UserManager.DISALLOW_WIFI_TETHERING;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Build;
-import android.os.Bundle;
import android.os.UserManager;
import androidx.test.core.app.ApplicationProvider;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
public class WifiEnterpriseRestrictionUtilsTest {
- private Context mContext;
+ static final String SDK_INT = "SDK_INT";
+ static final int VERSION_CODES_S = Build.VERSION_CODES.S;
+ static final int VERSION_CODES_T = Build.VERSION_CODES.TIRAMISU;
+
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Spy
+ Context mContext = ApplicationProvider.getApplicationContext();
@Mock
private UserManager mUserManager;
- @Mock
- private Bundle mBundle;
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
- when(mUserManager.getUserRestrictions()).thenReturn(mBundle);
- ReflectionHelpers.setStaticField(
- Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU);
+ ReflectionHelpers.setStaticField(Build.VERSION.class, SDK_INT, VERSION_CODES_T);
}
@Test
- public void isWifiTetheringAllowed_setSDKForS_shouldReturnTrue() {
- ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.S);
- when(mBundle.getBoolean(UserManager.DISALLOW_WIFI_TETHERING)).thenReturn(true);
-
- assertThat(WifiEnterpriseRestrictionUtils.isWifiTetheringAllowed(mContext)).isTrue();
- }
-
- @Test
- public void isWifiTetheringAllowed_setSDKForTAndDisallowForRestriction_shouldReturnFalse() {
- ReflectionHelpers.setStaticField(
- Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU);
- when(mBundle.getBoolean(UserManager.DISALLOW_WIFI_TETHERING)).thenReturn(true);
+ public void isWifiTetheringAllowed_hasDisallowRestriction_shouldReturnFalse() {
+ when(mUserManager.hasUserRestriction(DISALLOW_WIFI_TETHERING)).thenReturn(true);
assertThat(WifiEnterpriseRestrictionUtils.isWifiTetheringAllowed(mContext)).isFalse();
}
@Test
- public void isWifiTetheringAllowed_setSDKForTAndAllowForRestriction_shouldReturnTrue() {
- ReflectionHelpers.setStaticField(
- Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU);
- when(mBundle.getBoolean(UserManager.DISALLOW_WIFI_TETHERING)).thenReturn(false);
+ public void isWifiTetheringAllowed_noDisallowRestriction_shouldReturnTrue() {
+ when(mUserManager.hasUserRestriction(DISALLOW_WIFI_TETHERING)).thenReturn(false);
assertThat(WifiEnterpriseRestrictionUtils.isWifiTetheringAllowed(mContext)).isTrue();
}
@Test
- public void isWifiDirectAllowed_setSDKForS_shouldReturnTrue() {
- ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.S);
- when(mBundle.getBoolean(UserManager.DISALLOW_WIFI_DIRECT)).thenReturn(true);
-
- assertThat(WifiEnterpriseRestrictionUtils.isWifiDirectAllowed(mContext)).isTrue();
- }
-
- @Test
- public void isWifiDirectAllowed_setSDKForTAndDisallowForRestriction_shouldReturnFalse() {
- ReflectionHelpers.setStaticField(
- Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU);
- when(mBundle.getBoolean(UserManager.DISALLOW_WIFI_DIRECT)).thenReturn(true);
+ public void isWifiDirectAllowed_hasDisallowRestriction_shouldReturnFalse() {
+ when(mUserManager.hasUserRestriction(DISALLOW_WIFI_DIRECT)).thenReturn(true);
assertThat(WifiEnterpriseRestrictionUtils.isWifiDirectAllowed(mContext)).isFalse();
}
@Test
- public void isWifiDirectAllowed_setSDKForTAndAllowForRestriction_shouldReturnTrue() {
- ReflectionHelpers.setStaticField(
- Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU);
- when(mBundle.getBoolean(UserManager.DISALLOW_WIFI_DIRECT)).thenReturn(false);
+ public void isWifiDirectAllowed_noDisallowRestriction_shouldReturnTrue() {
+ when(mUserManager.hasUserRestriction(DISALLOW_WIFI_DIRECT)).thenReturn(false);
assertThat(WifiEnterpriseRestrictionUtils.isWifiDirectAllowed(mContext)).isTrue();
}
@Test
- public void isAddWifiConfigAllowed_setSDKForS_shouldReturnTrue() {
- ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.S);
- when(mBundle.getBoolean(UserManager.DISALLOW_ADD_WIFI_CONFIG)).thenReturn(true);
-
- assertThat(WifiEnterpriseRestrictionUtils.isAddWifiConfigAllowed(mContext)).isTrue();
- }
-
- @Test
- public void isAddWifiConfigAllowed_setSDKForTAndDisallowForRestriction_shouldReturnFalse() {
- ReflectionHelpers.setStaticField(
- Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU);
- when(mBundle.getBoolean(UserManager.DISALLOW_ADD_WIFI_CONFIG)).thenReturn(true);
+ public void isAddWifiConfigAllowed_hasDisallowRestriction_shouldReturnFalse() {
+ when(mUserManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)).thenReturn(true);
assertThat(WifiEnterpriseRestrictionUtils.isAddWifiConfigAllowed(mContext)).isFalse();
}
@Test
- public void isAddWifiConfigAllowed_setSDKForTAndAllowForRestriction_shouldReturnTrue() {
- ReflectionHelpers.setStaticField(
- Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU);
- when(mBundle.getBoolean(UserManager.DISALLOW_ADD_WIFI_CONFIG)).thenReturn(false);
+ public void isAddWifiConfigAllowed_noDisallowRestriction_shouldReturnTrue() {
+ when(mUserManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)).thenReturn(false);
assertThat(WifiEnterpriseRestrictionUtils.isAddWifiConfigAllowed(mContext)).isTrue();
}
@@ -143,7 +112,7 @@
}
@Test
- public void isChangeWifiStateAllowed_hasNoDisallowRestriction_shouldReturnTrue() {
+ public void isChangeWifiStateAllowed_noDisallowRestriction_shouldReturnTrue() {
when(mUserManager.hasUserRestriction(DISALLOW_CHANGE_WIFI_STATE)).thenReturn(false);
assertThat(WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(mContext)).isTrue();
@@ -151,7 +120,7 @@
@Test
public void hasUserRestrictionFromT_setSDKForS_shouldReturnTrue() {
- ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.S);
+ ReflectionHelpers.setStaticField(Build.VERSION.class, SDK_INT, VERSION_CODES_S);
assertThat(WifiEnterpriseRestrictionUtils.hasUserRestrictionFromT(mContext, "key"))
.isFalse();
@@ -159,8 +128,7 @@
@Test
public void hasUserRestrictionFromT_setSDKForT_shouldReturnHasUserRestriction() {
- ReflectionHelpers.setStaticField(
- Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU);
+ ReflectionHelpers.setStaticField(Build.VERSION.class, SDK_INT, VERSION_CODES_T);
when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
assertThat(WifiEnterpriseRestrictionUtils.hasUserRestrictionFromT(mContext, "key"))
diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
index f72a8dc..5b96159 100644
--- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
+++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
@@ -198,20 +198,29 @@
android:clickable="false"
android:focusable="false">
- <FrameLayout
- android:layout_weight="1"
- android:orientation="vertical"
- android:clickable="false"
+ <LinearLayout
android:layout_width="wrap_content"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="start|center_vertical"
+ android:orientation="vertical"
+ android:clickable="false">
<TextView
android:id="@+id/wifi_toggle_title"
android:text="@string/turn_on_wifi"
android:layout_width="wrap_content"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
android:gravity="start|center_vertical"
android:textAppearance="@style/TextAppearance.InternetDialog"/>
- </FrameLayout>
+ <TextView
+ android:id="@+id/wifi_toggle_summary"
+ android:text="@string/wifitrackerlib_admin_restricted_network"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="start|center_vertical"
+ android:textAppearance="@style/TextAppearance.InternetDialog.Secondary"
+ android:visibility="gone"/>
+ </LinearLayout>
<FrameLayout
android:layout_width="@dimen/settingslib_switch_track_width"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 80582ef..a0115e8 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -561,6 +561,9 @@
<!-- The height of the gap between adjacent notification sections. -->
<dimen name="notification_section_divider_height">@dimen/notification_side_paddings</dimen>
+ <!-- The height of the gap between adjacent notification sections on lockscreen. -->
+ <dimen name="notification_section_divider_height_lockscreen">4dp</dimen>
+
<!-- Size of the face pile shown on one-line (children of a group) conversation notifications -->
<dimen name="conversation_single_line_face_pile_size">24dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AlternateUdfpsTouchProvider.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AlternateUdfpsTouchProvider.kt
new file mode 100644
index 0000000..f4f39a1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AlternateUdfpsTouchProvider.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.systemui.biometrics
+
+/**
+ * Interface for controlling the on finger down & on finger up events.
+ */
+interface AlternateUdfpsTouchProvider {
+
+ /**
+ * This operation is used to notify the Fingerprint HAL that
+ * a fingerprint has been detected on the device's screen.
+ *
+ * See fingerprint/ISession#onPointerDown for more details.
+ */
+ fun onPointerDown(pointerId: Long, x: Int, y: Int, minor: Float, major: Float)
+
+ /**
+ * onPointerUp:
+ *
+ * This operation can be invoked when the HAL is performing any one of: ISession#authenticate,
+ * ISession#enroll, ISession#detectInteraction. This operation is used to indicate
+ * that a fingerprint that was previously down, is now up.
+ *
+ * See fingerprint/ISession#onPointerUp for more details.
+ */
+ fun onPointerUp(pointerId: Long)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index eba87e4..2847246 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -133,6 +133,7 @@
// sensors, this, in addition to a lot of the code here, will be updated.
@VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps;
@NonNull private final ActivityLaunchAnimator mActivityLaunchAnimator;
+ @Nullable private final AlternateUdfpsTouchProvider mAlternateTouchProvider;
// Tracks the velocity of a touch to help filter out the touches that move too fast.
@Nullable private VelocityTracker mVelocityTracker;
@@ -384,6 +385,7 @@
mActivePointerId = event.getPointerId(0);
mVelocityTracker.addMovement(event);
handled = true;
+ mAcquiredReceived = false;
}
if ((withinSensorArea || fromUdfpsView) && shouldTryToDismissKeyguard()) {
Log.v(TAG, "onTouch | dismiss keyguard ACTION_DOWN");
@@ -537,7 +539,8 @@
@NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
@NonNull SystemUIDialogManager dialogManager,
@NonNull LatencyTracker latencyTracker,
- @NonNull ActivityLaunchAnimator activityLaunchAnimator) {
+ @NonNull ActivityLaunchAnimator activityLaunchAnimator,
+ @NonNull Optional<AlternateUdfpsTouchProvider> aternateTouchProvider) {
mContext = context;
mExecution = execution;
mVibrator = vibrator;
@@ -566,6 +569,7 @@
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
mLatencyTracker = latencyTracker;
mActivityLaunchAnimator = activityLaunchAnimator;
+ mAlternateTouchProvider = aternateTouchProvider.orElse(null);
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
@@ -782,6 +786,7 @@
private void onFingerDown(long requestId, int x, int y, float minor, float major) {
mExecution.assertIsMainThread();
+
if (mOverlay == null) {
Log.w(TAG, "Null request in onFingerDown");
return;
@@ -806,7 +811,11 @@
}
}
mOnFingerDown = true;
- mFingerprintManager.onPointerDown(requestId, mSensorProps.sensorId, x, y, minor, major);
+ if (mAlternateTouchProvider != null) {
+ mAlternateTouchProvider.onPointerDown(requestId, x, y, minor, major);
+ } else {
+ mFingerprintManager.onPointerDown(requestId, mSensorProps.sensorId, x, y, minor, major);
+ }
Trace.endAsyncSection("UdfpsController.e2e.onPointerDown", 0);
final UdfpsView view = mOverlay.getOverlayView();
@@ -827,7 +836,11 @@
mActivePointerId = -1;
mAcquiredReceived = false;
if (mOnFingerDown) {
- mFingerprintManager.onPointerUp(requestId, mSensorProps.sensorId);
+ if (mAlternateTouchProvider != null) {
+ mAlternateTouchProvider.onPointerUp(requestId);
+ } else {
+ mFingerprintManager.onPointerUp(requestId, mSensorProps.sensorId);
+ }
for (Callback cb : mCallbacks) {
cb.onFingerUp();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 7b65f45..bbeb66c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -29,6 +29,7 @@
import com.android.systemui.SystemUIFactory;
import com.android.systemui.appops.dagger.AppOpsModule;
import com.android.systemui.assist.AssistModule;
+import com.android.systemui.biometrics.AlternateUdfpsTouchProvider;
import com.android.systemui.biometrics.UdfpsHbmProvider;
import com.android.systemui.biometrics.dagger.BiometricsModule;
import com.android.systemui.classifier.FalsingModule;
@@ -182,6 +183,9 @@
@BindsOptionalOf
abstract UdfpsHbmProvider optionalUdfpsHbmProvider();
+ @BindsOptionalOf
+ abstract AlternateUdfpsTouchProvider optionalUdfpsTouchProvider();
+
@SysUISingleton
@Binds
abstract SystemClock bindSystemClock(SystemClockImpl systemClock);
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
index c147fde..54b9430 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
@@ -42,6 +42,7 @@
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.wm.shell.animation.FlingAnimationUtils;
+import java.util.Optional;
import javax.inject.Inject;
import javax.inject.Named;
@@ -77,7 +78,7 @@
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private float mCurrentExpansion;
- private final CentralSurfaces mCentralSurfaces;
+ private final Optional<CentralSurfaces> mCentralSurfaces;
private VelocityTracker mVelocityTracker;
@@ -107,7 +108,9 @@
// If the user scrolling favors a vertical direction, begin capturing
// scrolls.
mCapture = Math.abs(distanceY) > Math.abs(distanceX);
- mBouncerInitiallyShowing = mCentralSurfaces.isBouncerShowing();
+ mBouncerInitiallyShowing = mCentralSurfaces
+ .map(CentralSurfaces::isBouncerShowing)
+ .orElse(false);
if (mCapture) {
// Since the user is dragging the bouncer up, set scrimmed to false.
@@ -129,13 +132,17 @@
return true;
}
+ if (!mCentralSurfaces.isPresent()) {
+ return true;
+ }
+
// For consistency, we adopt the expansion definition found in the
// PanelViewController. In this case, expansion refers to the view above the
// bouncer. As that view's expansion shrinks, the bouncer appears. The bouncer
// is fully hidden at full expansion (1) and fully visible when fully collapsed
// (0).
final float screenTravelPercentage = Math.abs(e1.getY() - e2.getY())
- / mCentralSurfaces.getDisplayHeight();
+ / mCentralSurfaces.get().getDisplayHeight();
setPanelExpansion(mBouncerInitiallyShowing
? screenTravelPercentage : 1 - screenTravelPercentage);
return true;
@@ -171,7 +178,7 @@
public BouncerSwipeTouchHandler(
DisplayMetrics displayMetrics,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
- CentralSurfaces centralSurfaces,
+ Optional<CentralSurfaces> centralSurfaces,
NotificationShadeWindowController notificationShadeWindowController,
ValueAnimatorCreator valueAnimatorCreator,
VelocityTrackerFactory velocityTrackerFactory,
@@ -195,7 +202,7 @@
@Override
public void getTouchInitiationRegion(Region region) {
- if (mCentralSurfaces.isBouncerShowing()) {
+ if (mCentralSurfaces.map(CentralSurfaces::isBouncerShowing).orElse(false)) {
region.op(new Rect(0, 0, mDisplayMetrics.widthPixels,
Math.round(
mDisplayMetrics.heightPixels * mBouncerZoneScreenPercentage)),
@@ -306,8 +313,12 @@
}
protected void flingToExpansion(float velocity, float expansion) {
+ if (!mCentralSurfaces.isPresent()) {
+ return;
+ }
+
// The animation utils deal in pixel units, rather than expansion height.
- final float viewHeight = mCentralSurfaces.getDisplayHeight();
+ final float viewHeight = mCentralSurfaces.get().getDisplayHeight();
final float currentHeight = viewHeight * mCurrentExpansion;
final float targetHeight = viewHeight * expansion;
diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
index c9d300b..60ef85d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
@@ -89,6 +89,7 @@
holder.seekBar.thumb.alpha = if (data.seekAvailable) 255 else 0
holder.seekBar.isEnabled = data.seekAvailable
progressDrawable?.animate = data.playing && !data.scrubbing
+ progressDrawable?.transitionEnabled = !data.seekAvailable
if (holder.seekBar.maxHeight != seekBarEnabledMaxHeight) {
holder.seekBar.maxHeight = seekBarEnabledMaxHeight
diff --git a/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt b/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt
index fbd17d7..88f6f3d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt
@@ -5,13 +5,15 @@
import android.animation.ValueAnimator
import android.content.res.ColorStateList
import android.graphics.Canvas
-import android.graphics.Color
import android.graphics.ColorFilter
import android.graphics.Paint
import android.graphics.Path
import android.graphics.PixelFormat
import android.graphics.drawable.Drawable
import android.os.SystemClock
+import android.util.MathUtils.lerp
+import android.util.MathUtils.lerpInv
+import android.util.MathUtils.lerpInvSat
import androidx.annotation.VisibleForTesting
import com.android.internal.graphics.ColorUtils
import com.android.systemui.animation.Interpolators
@@ -34,6 +36,13 @@
private var phaseOffset = 0f
private var lastFrameTime = -1L
+ /* distance over which amplitude drops to zero, measured in wavelengths */
+ private val transitionPeriods = 1.5f
+ /* wave endpoint as percentage of bar when play position is zero */
+ private val minWaveEndpoint = 0.2f
+ /* wave endpoint as percentage of bar when play position matches wave endpoint */
+ private val matchedWaveEndpoint = 0.6f
+
// Horizontal length of the sine wave
var waveLength = 0f
// Height of each peak of the sine wave
@@ -51,6 +60,12 @@
linePaint.strokeWidth = value
}
+ var transitionEnabled = true
+ set(value) {
+ field = value
+ invalidateSelf()
+ }
+
init {
wavePaint.strokeCap = Paint.Cap.ROUND
linePaint.strokeCap = Paint.Cap.ROUND
@@ -95,57 +110,90 @@
if (animate) {
invalidateSelf()
val now = SystemClock.uptimeMillis()
- phaseOffset -= (now - lastFrameTime) / 1000f * phaseSpeed
+ phaseOffset += (now - lastFrameTime) / 1000f * phaseSpeed
phaseOffset %= waveLength
lastFrameTime = now
}
- val totalProgressPx = (bounds.width() * (level / 10_000f))
+ val progress = level / 10_000f
+ val totalProgressPx = bounds.width() * progress
+ val waveProgressPx = bounds.width() * (
+ if (!transitionEnabled || progress > matchedWaveEndpoint) progress else
+ lerp(minWaveEndpoint, matchedWaveEndpoint, lerpInv(0f, matchedWaveEndpoint, progress)))
+
+ // Build Wiggly Path
+ val waveStart = -phaseOffset
+ val waveEnd = waveProgressPx
+ val transitionLength = if (transitionEnabled) transitionPeriods * waveLength else 0.01f
+
+ // helper function, computes amplitude for wave segment
+ val computeAmplitude: (Float, Float) -> Float = { x, sign ->
+ sign * heightFraction * lineAmplitude *
+ lerpInvSat(waveEnd, waveEnd - transitionLength, x)
+ }
+
+ var currentX = waveEnd
+ var waveSign = if (phaseOffset < waveLength / 2) 1f else -1f
+ path.rewind()
+
+ // Draw flat line from end to wave endpoint
+ path.moveTo(bounds.width().toFloat(), 0f)
+ path.lineTo(waveEnd, 0f)
+
+ // First wave has shortened wavelength
+ // approx quarter wave gets us to first wave peak
+ // shouldn't be big enough to notice it's not a sin wave
+ currentX -= phaseOffset % (waveLength / 2)
+ val controlRatio = 0.25f
+ var currentAmp = computeAmplitude(currentX, waveSign)
+ path.cubicTo(
+ waveEnd, currentAmp * controlRatio,
+ lerp(currentX, waveEnd, controlRatio), currentAmp,
+ currentX, currentAmp)
+
+ // Other waves have full wavelength
+ val dist = -1 * waveLength / 2f
+ while (currentX > waveStart) {
+ waveSign = -waveSign
+ val nextX = currentX + dist
+ val midX = currentX + dist / 2
+ val nextAmp = computeAmplitude(nextX, waveSign)
+ path.cubicTo(
+ midX, currentAmp,
+ midX, nextAmp,
+ nextX, nextAmp)
+ currentAmp = nextAmp
+ currentX = nextX
+ }
+
+ // Draw path; clip to progress position
canvas.save()
canvas.translate(bounds.left.toFloat(), bounds.centerY().toFloat())
- // Clip drawing, so we stop at the thumb
canvas.clipRect(
0f,
-lineAmplitude - strokeWidth,
totalProgressPx,
lineAmplitude + strokeWidth)
-
- // The squiggly line
- val start = phaseOffset
- var currentX = start
- var waveSign = 1f
- path.rewind()
- path.moveTo(start, lineAmplitude * heightFraction)
- while (currentX < totalProgressPx) {
- val nextX = currentX + waveLength / 2f
- val nextWaveSign = waveSign * -1
- path.cubicTo(
- currentX + waveLength / 4f, lineAmplitude * waveSign * heightFraction,
- nextX - waveLength / 4f, lineAmplitude * nextWaveSign * heightFraction,
- nextX, lineAmplitude * nextWaveSign * heightFraction)
- currentX = nextX
- waveSign = nextWaveSign
- }
- wavePaint.style = Paint.Style.STROKE
canvas.drawPath(path, wavePaint)
canvas.restore()
+ // Draw path; clip between progression position & far edge
+ canvas.save()
+ canvas.translate(bounds.left.toFloat(), bounds.centerY().toFloat())
+ canvas.clipRect(
+ totalProgressPx,
+ -lineAmplitude - strokeWidth,
+ bounds.width().toFloat(),
+ lineAmplitude + strokeWidth)
+ canvas.drawPath(path, linePaint)
+ canvas.restore()
+
// Draw round line cap at the beginning of the wave
- val startAmp = cos(abs(phaseOffset) / waveLength * TWO_PI)
- val p = Paint()
- p.color = Color.WHITE
+ val startAmp = cos(abs(waveEnd - phaseOffset) / waveLength * TWO_PI)
canvas.drawPoint(
bounds.left.toFloat(),
bounds.centerY() + startAmp * lineAmplitude * heightFraction,
wavePaint)
-
- // Draw continuous line, to the right of the thumb
- canvas.drawLine(
- bounds.left.toFloat() + totalProgressPx,
- bounds.centerY().toFloat(),
- bounds.width().toFloat(),
- bounds.centerY().toFloat(),
- linePaint)
}
override fun getOpacity(): Int {
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 8921e95..8ca095d 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
@@ -58,6 +58,7 @@
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.settingslib.Utils;
+import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.accessibility.floatingmenu.AnnotationLinkSpan;
@@ -136,6 +137,7 @@
private Drawable mBackgroundOff = null;
private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private boolean mCanConfigMobileData;
+ private boolean mCanChangeWifiState;
// Wi-Fi entries
private int mWifiNetworkHeight;
@@ -180,6 +182,7 @@
mWifiManager = mInternetDialogController.getWifiManager();
mCanConfigMobileData = canConfigMobileData;
mCanConfigWifi = canConfigWifi;
+ mCanChangeWifiState = WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(context);
mKeyguard = keyguardStateController;
mUiEventLogger = uiEventLogger;
@@ -449,6 +452,14 @@
}
mTurnWifiOnLayout.setBackground(
(isDeviceLocked && mConnectedWifiEntry != null) ? mBackgroundOn : null);
+
+ if (!mCanChangeWifiState && mWiFiToggle.isEnabled()) {
+ mWiFiToggle.setEnabled(false);
+ mWifiToggleTitleText.setEnabled(false);
+ final TextView summaryText = mDialogView.requireViewById(R.id.wifi_toggle_summary);
+ summaryText.setEnabled(false);
+ summaryText.setVisibility(View.VISIBLE);
+ }
}
@MainThread
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index f15df8e..c1ea6bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -72,6 +72,9 @@
dumpManager: DumpManager
) : Dumpable {
private var pulseHeight: Float = 0f
+ @get:VisibleForTesting
+ var fractionToShade: Float = 0f
+ private set
private var useSplitShade: Boolean = false
private lateinit var nsslController: NotificationStackScrollLayoutController
lateinit var notificationPanelController: NotificationPanelViewController
@@ -405,9 +408,9 @@
if (field != value || forceApplyAmount) {
field = value
if (!nsslController.isInLockedDownShade() || field == 0f || forceApplyAmount) {
- val notificationShelfProgress =
+ fractionToShade =
MathUtils.saturate(dragDownAmount / notificationShelfTransitionDistance)
- nsslController.setTransitionToFullShadeAmount(notificationShelfProgress)
+ nsslController.setTransitionToFullShadeAmount(fractionToShade)
qSDragProgress = MathUtils.saturate(dragDownAmount / qsTransitionDistance)
qS.setTransitionToFullShadeAmount(field, qSDragProgress)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 633786f..afce945 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -85,9 +85,6 @@
private NotificationShelfController mController;
private float mActualWidth = -1;
- /** Fraction of lockscreen to shade animation (on lockscreen swipe down). */
- private float mFractionToShade;
-
public NotificationShelf(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -234,13 +231,6 @@
}
/**
- * @param fractionToShade Fraction of lockscreen to shade transition
- */
- public void setFractionToShade(float fractionToShade) {
- mFractionToShade = fractionToShade;
- }
-
- /**
* @return Actual width of shelf, accounting for possible ongoing width animation
*/
public int getActualWidth() {
@@ -411,7 +401,8 @@
|| !mShowNotificationShelf
|| numViewsInShelf < 1f;
- final float fractionToShade = Interpolators.STANDARD.getInterpolation(mFractionToShade);
+ final float fractionToShade = Interpolators.STANDARD.getInterpolation(
+ mAmbientState.getFractionToShade());
final float shortestWidth = mShelfIcons.calculateWidthFor(numViewsInShelf);
updateActualWidth(fractionToShade, shortestWidth);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index efb46b96..7245cb2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -2658,9 +2658,6 @@
return;
}
- // bail out if no public version
- if (mPublicLayout.getChildCount() == 0) return;
-
if (!animated) {
mPublicLayout.animate().cancel();
mPrivateLayout.animate().cancel();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index 25999a7..9acd60e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -82,6 +82,23 @@
private boolean mAppearing;
private float mPulseHeight = MAX_PULSE_HEIGHT;
+ /** Fraction of lockscreen to shade animation (on lockscreen swipe down). */
+ private float mFractionToShade;
+
+ /**
+ * @param fractionToShade Fraction of lockscreen to shade transition
+ */
+ public void setFractionToShade(float fractionToShade) {
+ mFractionToShade = fractionToShade;
+ }
+
+ /**
+ * @return fractionToShade Fraction of lockscreen to shade transition
+ */
+ public float getFractionToShade() {
+ return mFractionToShade;
+ }
+
/** How we much we are sleeping. 1f fully dozing (AOD), 0f fully awake (for all other states) */
private float mDozeAmount = 0.0f;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index b52fd61..851794c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -2295,7 +2295,7 @@
int visibleIndex
) {
return mStackScrollAlgorithm.getGapHeightForChild(mSectionsManager, visibleIndex, current,
- previous);
+ previous, mAmbientState.getFractionToShade(), mAmbientState.isOnKeyguard());
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@@ -5501,7 +5501,7 @@
* where it remains until the next lockscreen-to-shade transition.
*/
public void setFractionToShade(float fraction) {
- mShelf.setFractionToShade(fraction);
+ mAmbientState.setFractionToShade(fraction);
requestChildrenUpdate();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
index 9417aac..2b11f69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
@@ -19,9 +19,11 @@
import android.content.res.Resources
import android.util.Log
import android.view.View.GONE
+import androidx.annotation.VisibleForTesting
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.statusbar.LockscreenShadeTransitionController
import com.android.systemui.statusbar.StatusBarState.KEYGUARD
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
@@ -41,6 +43,7 @@
@Inject
constructor(
private val statusBarStateController: SysuiStatusBarStateController,
+ private val lockscreenShadeTransitionController: LockscreenShadeTransitionController,
@Main private val resources: Resources
) {
@@ -129,7 +132,7 @@
yield(dividerHeight + shelfIntrinsicHeight) // Only shelf.
children.forEachIndexed { i, currentNotification ->
- height += currentNotification.spaceNeeded(i, previous, stack, onLockscreen)
+ height += spaceNeeded(currentNotification, i, previous, stack, onLockscreen)
previous = currentNotification
val shelfHeight =
@@ -156,22 +159,28 @@
private val NotificationStackScrollLayout.childrenSequence: Sequence<ExpandableView>
get() = children.map { it as ExpandableView }
- private fun onLockscreen() = statusBarStateController.state == KEYGUARD
+ @VisibleForTesting
+ fun onLockscreen() : Boolean {
+ return statusBarStateController.state == KEYGUARD
+ && lockscreenShadeTransitionController.fractionToShade == 0f
+ }
- private fun ExpandableView.spaceNeeded(
+ @VisibleForTesting
+ fun spaceNeeded(
+ view: ExpandableView,
visibleIndex: Int,
previousView: ExpandableView?,
stack: NotificationStackScrollLayout,
onLockscreen: Boolean
): Float {
- assert(isShowable(onLockscreen))
+ assert(view.isShowable(onLockscreen))
var size =
if (onLockscreen) {
- getMinHeight(/* ignoreTemporaryStates= */ true).toFloat()
+ view.getMinHeight(/* ignoreTemporaryStates= */ true).toFloat()
} else {
- intrinsicHeight.toFloat()
+ view.intrinsicHeight.toFloat()
}
- size += calculateGapAndDividerHeight(stack, previousView, current = this, visibleIndex)
+ size += calculateGapAndDividerHeight(stack, previousView, current = view, visibleIndex)
return size
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 9204c45e..22242b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -54,6 +54,7 @@
private int mPaddingBetweenElements;
private int mGapHeight;
+ private int mGapHeightOnLockscreen;
private int mCollapsedSize;
private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
@@ -87,6 +88,8 @@
mPinnedZTranslationExtra = res.getDimensionPixelSize(
R.dimen.heads_up_pinned_elevation);
mGapHeight = res.getDimensionPixelSize(R.dimen.notification_section_divider_height);
+ mGapHeightOnLockscreen = res.getDimensionPixelSize(
+ R.dimen.notification_section_divider_height_lockscreen);
mNotificationScrimPadding = res.getDimensionPixelSize(R.dimen.notification_side_paddings);
mMarginBottom = res.getDimensionPixelSize(R.dimen.notification_panel_margin_bottom);
}
@@ -305,7 +308,8 @@
ambientState.getSectionProvider(), i,
view, getPreviousView(i, state));
if (applyGapHeight) {
- currentY += mGapHeight;
+ currentY += getGapForLocation(
+ ambientState.getFractionToShade(), ambientState.isOnKeyguard());
}
if (ambientState.getShelf() != null) {
@@ -454,8 +458,10 @@
ambientState.getSectionProvider(), i,
view, getPreviousView(i, algorithmState));
if (applyGapHeight) {
- algorithmState.mCurrentYPosition += expansionFraction * mGapHeight;
- algorithmState.mCurrentExpandedYPosition += mGapHeight;
+ final float gap = getGapForLocation(
+ ambientState.getFractionToShade(), ambientState.isOnKeyguard());
+ algorithmState.mCurrentYPosition += expansionFraction * gap;
+ algorithmState.mCurrentExpandedYPosition += gap;
}
viewState.yTranslation = algorithmState.mCurrentYPosition;
@@ -539,16 +545,29 @@
SectionProvider sectionProvider,
int visibleIndex,
View child,
- View previousChild) {
+ View previousChild,
+ float fractionToShade,
+ boolean onKeyguard) {
if (childNeedsGapHeight(sectionProvider, visibleIndex, child,
previousChild)) {
- return mGapHeight;
+ return getGapForLocation(fractionToShade, onKeyguard);
} else {
return 0;
}
}
+ @VisibleForTesting
+ float getGapForLocation(float fractionToShade, boolean onKeyguard) {
+ if (fractionToShade > 0f) {
+ return MathUtils.lerp(mGapHeightOnLockscreen, mGapHeight, fractionToShade);
+ }
+ if (onKeyguard) {
+ return mGapHeightOnLockscreen;
+ }
+ return mGapHeight;
+ }
+
/**
* Does a given child need a gap, i.e spacing before a view?
*
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java
index 6fdce1a..640adcc 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java
@@ -22,6 +22,12 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.SystemUIBinder;
import com.android.systemui.dagger.SystemUIModule;
+import com.android.systemui.statusbar.dagger.CentralSurfacesDependenciesModule;
+import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
+import com.android.systemui.statusbar.notification.row.NotificationRowModule;
+
+import com.android.systemui.keyguard.dagger.KeyguardModule;
+import com.android.systemui.recents.RecentsModule;
import dagger.Subcomponent;
@@ -30,13 +36,17 @@
*/
@SysUISingleton
@Subcomponent(modules = {
+ CentralSurfacesDependenciesModule.class,
DefaultComponentBinder.class,
DependencyProvider.class,
- SystemUIBinder.class,
+ KeyguardModule.class,
+ NotificationRowModule.class,
+ NotificationsModule.class,
+ RecentsModule.class,
SystemUIModule.class,
+ TvSystemUIBinder.class,
TVSystemUICoreStartableModule.class,
- TvSystemUIModule.class,
- TvSystemUIBinder.class})
+ TvSystemUIModule.class})
public interface TvSysUIComponent extends SysUIComponent {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java
index 9b2702f..1243c47 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java
@@ -215,6 +215,7 @@
logoView.setImageDrawable(mContext.getDrawable(R.drawable.ic_qs_plus));
mEmptyStateView.<TextView>requireViewById(R.id.empty_state_title).setText(label);
mEmptyStateView.setOnClickListener(clickListener);
+ mAppButton.setOnClickListener(clickListener);
}
void showErrorMessage(@Nullable CharSequence message) {
@@ -256,6 +257,11 @@
}
@VisibleForTesting
+ Button getAppButton() {
+ return mAppButton;
+ }
+
+ @VisibleForTesting
TextView getErrorView() {
return mErrorView;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 05cf6a50..5d624cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -22,6 +22,7 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
@@ -183,6 +184,8 @@
private SystemUIDialogManager mSystemUIDialogManager;
@Mock
private ActivityLaunchAnimator mActivityLaunchAnimator;
+ @Mock
+ private AlternateUdfpsTouchProvider mTouchProvider;
// Capture listeners so that they can be used to send events
@Captor private ArgumentCaptor<IUdfpsOverlayController> mOverlayCaptor;
@@ -256,7 +259,8 @@
mUnlockedScreenOffAnimationController,
mSystemUIDialogManager,
mLatencyTracker,
- mActivityLaunchAnimator);
+ mActivityLaunchAnimator,
+ Optional.of(mTouchProvider));
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
mOverlayController = mOverlayCaptor.getValue();
verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
@@ -418,9 +422,10 @@
mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent);
moveEvent.recycle();
// THEN FingerprintManager is notified about onPointerDown
- verify(mFingerprintManager).onPointerDown(eq(TEST_REQUEST_ID),
- eq(mUdfpsController.mSensorProps.sensorId),
+ verify(mTouchProvider).onPointerDown(eq(TEST_REQUEST_ID),
eq(0), eq(0), eq(0f), eq(0f));
+ verify(mFingerprintManager, never()).onPointerDown(anyLong(), anyInt(), anyInt(), anyInt(),
+ anyFloat(), anyFloat());
verify(mLatencyTracker).onActionStart(eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE));
// AND illumination begins
verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture());
@@ -447,9 +452,10 @@
// AND onIlluminatedRunnable that notifies FingerprintManager is set
verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture());
mOnIlluminatedRunnableCaptor.getValue().run();
- verify(mFingerprintManager).onPointerDown(eq(TEST_REQUEST_ID),
- eq(mUdfpsController.mSensorProps.sensorId),
+ verify(mTouchProvider).onPointerDown(eq(TEST_REQUEST_ID),
eq(0), eq(0), eq(3f) /* minor */, eq(2f) /* major */);
+ verify(mFingerprintManager, never()).onPointerDown(anyLong(), anyInt(), anyInt(), anyInt(),
+ anyFloat(), anyFloat());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
index e175af7..d0b3d6d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
@@ -57,6 +57,8 @@
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.Optional;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
@@ -110,7 +112,7 @@
mTouchHandler = new BouncerSwipeTouchHandler(
mDisplayMetrics,
mStatusBarKeyguardViewManager,
- mCentralSurfaces,
+ Optional.of(mCentralSurfaces),
mNotificationShadeWindowController,
mValueAnimatorCreator,
mVelocityTrackerFactory,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt
index e3cd90b..d087b0f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt
@@ -19,7 +19,7 @@
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
-import org.mockito.Mockito.anyFloat
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
@@ -35,8 +35,7 @@
lateinit var squigglyProgress: SquigglyProgress
@Mock lateinit var canvas: Canvas
- @Captor lateinit var wavePaintCaptor: ArgumentCaptor<Paint>
- @Captor lateinit var linePaintCaptor: ArgumentCaptor<Paint>
+ @Captor lateinit var paintCaptor: ArgumentCaptor<Paint>
@JvmField @Rule val mockitoRule = MockitoJUnit.rule()
@Before
@@ -53,9 +52,7 @@
fun testDrawPathAndLine() {
squigglyProgress.draw(canvas)
- verify(canvas).drawPath(any(), wavePaintCaptor.capture())
- verify(canvas).drawLine(anyFloat(), anyFloat(), anyFloat(), anyFloat(),
- linePaintCaptor.capture())
+ verify(canvas, times(2)).drawPath(any(), paintCaptor.capture())
}
@Test
@@ -69,12 +66,11 @@
fun testStrokeWidth() {
squigglyProgress.draw(canvas)
- verify(canvas).drawPath(any(), wavePaintCaptor.capture())
- verify(canvas).drawLine(anyFloat(), anyFloat(), anyFloat(), anyFloat(),
- linePaintCaptor.capture())
+ verify(canvas, times(2)).drawPath(any(), paintCaptor.capture())
+ val (wavePaint, linePaint) = paintCaptor.getAllValues()
- assertThat(wavePaintCaptor.value.strokeWidth).isEqualTo(strokeWidth)
- assertThat(linePaintCaptor.value.strokeWidth).isEqualTo(strokeWidth)
+ assertThat(wavePaint.strokeWidth).isEqualTo(strokeWidth)
+ assertThat(linePaint.strokeWidth).isEqualTo(strokeWidth)
}
@Test
@@ -82,13 +78,12 @@
squigglyProgress.alpha = alpha
squigglyProgress.draw(canvas)
- verify(canvas).drawPath(any(), wavePaintCaptor.capture())
- verify(canvas).drawLine(anyFloat(), anyFloat(), anyFloat(), anyFloat(),
- linePaintCaptor.capture())
+ verify(canvas, times(2)).drawPath(any(), paintCaptor.capture())
+ val (wavePaint, linePaint) = paintCaptor.getAllValues()
assertThat(squigglyProgress.alpha).isEqualTo(alpha)
- assertThat(wavePaintCaptor.value.alpha).isEqualTo(alpha)
- assertThat(linePaintCaptor.value.alpha).isEqualTo((alpha / 255f * DISABLED_ALPHA).toInt())
+ assertThat(wavePaint.alpha).isEqualTo(alpha)
+ assertThat(linePaint.alpha).isEqualTo((alpha / 255f * DISABLED_ALPHA).toInt())
}
@Test
@@ -96,12 +91,11 @@
squigglyProgress.colorFilter = colorFilter
squigglyProgress.draw(canvas)
- verify(canvas).drawPath(any(), wavePaintCaptor.capture())
- verify(canvas).drawLine(anyFloat(), anyFloat(), anyFloat(), anyFloat(),
- linePaintCaptor.capture())
+ verify(canvas, times(2)).drawPath(any(), paintCaptor.capture())
+ val (wavePaint, linePaint) = paintCaptor.getAllValues()
- assertThat(wavePaintCaptor.value.colorFilter).isEqualTo(colorFilter)
- assertThat(linePaintCaptor.value.colorFilter).isEqualTo(colorFilter)
+ assertThat(wavePaint.colorFilter).isEqualTo(colorFilter)
+ assertThat(linePaint.colorFilter).isEqualTo(colorFilter)
}
@Test
@@ -109,12 +103,11 @@
squigglyProgress.setTint(tint)
squigglyProgress.draw(canvas)
- verify(canvas).drawPath(any(), wavePaintCaptor.capture())
- verify(canvas).drawLine(anyFloat(), anyFloat(), anyFloat(), anyFloat(),
- linePaintCaptor.capture())
+ verify(canvas, times(2)).drawPath(any(), paintCaptor.capture())
+ val (wavePaint, linePaint) = paintCaptor.getAllValues()
- assertThat(wavePaintCaptor.value.color).isEqualTo(tint)
- assertThat(linePaintCaptor.value.color).isEqualTo(
+ assertThat(wavePaint.color).isEqualTo(tint)
+ assertThat(linePaint.color).isEqualTo(
ColorUtils.setAlphaComponent(tint, DISABLED_ALPHA))
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
index cf97bda..616f894 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
@@ -21,12 +21,15 @@
import android.testing.TestableLooper;
import android.view.View;
import android.widget.LinearLayout;
+import android.widget.Switch;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import androidx.test.filters.SmallTest;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.logging.UiEventLogger;
+import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -42,6 +45,7 @@
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
import java.util.List;
@@ -79,12 +83,16 @@
private LinearLayout mEthernet;
private LinearLayout mMobileDataToggle;
private LinearLayout mWifiToggle;
+ private Switch mWifiToggleSwitch;
+ private TextView mWifiToggleSummary;
private LinearLayout mConnectedWifi;
private RecyclerView mWifiList;
private LinearLayout mSeeAll;
private LinearLayout mWifiScanNotify;
private TextView mAirplaneModeSummaryText;
+ private MockitoSession mMockitoSession;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -101,6 +109,15 @@
.thenReturn(MOBILE_NETWORK_SUMMARY);
when(mInternetDialogController.getWifiManager()).thenReturn(mWifiManager);
+ mMockitoSession = ExtendedMockito.mockitoSession()
+ .spyStatic(WifiEnterpriseRestrictionUtils.class)
+ .startMocking();
+ when(WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(mContext)).thenReturn(true);
+
+ createInternetDialog();
+ }
+
+ private void createInternetDialog() {
mInternetDialog = new InternetDialog(mContext, mock(InternetDialogFactory.class),
mInternetDialogController, true, true, true, mock(UiEventLogger.class), mHandler,
mBgExecutor, mKeyguard);
@@ -114,6 +131,8 @@
mEthernet = mDialogView.requireViewById(R.id.ethernet_layout);
mMobileDataToggle = mDialogView.requireViewById(R.id.mobile_network_layout);
mWifiToggle = mDialogView.requireViewById(R.id.turn_on_wifi_layout);
+ mWifiToggleSwitch = mDialogView.requireViewById(R.id.wifi_toggle);
+ mWifiToggleSummary = mDialogView.requireViewById(R.id.wifi_toggle_summary);
mConnectedWifi = mDialogView.requireViewById(R.id.wifi_connected_layout);
mWifiList = mDialogView.requireViewById(R.id.wifi_list_layout);
mSeeAll = mDialogView.requireViewById(R.id.see_all_layout);
@@ -124,6 +143,7 @@
@After
public void tearDown() {
mInternetDialog.dismissDialog();
+ mMockitoSession.finishMocking();
}
@Test
@@ -411,6 +431,33 @@
}
@Test
+ public void updateDialog_disallowChangeWifiState_disableWifiSwitch() {
+ mInternetDialog.dismissDialog();
+ when(WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(mContext)).thenReturn(false);
+ createInternetDialog();
+
+ mInternetDialog.updateDialog(false);
+
+ // Disable Wi-Fi switch and show restriction message in summary.
+ assertThat(mWifiToggleSwitch.isEnabled()).isFalse();
+ assertThat(mWifiToggleSummary.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mWifiToggleSummary.getText().length()).isNotEqualTo(0);
+ }
+
+ @Test
+ public void updateDialog_allowChangeWifiState_enableWifiSwitch() {
+ mInternetDialog.dismissDialog();
+ when(WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(mContext)).thenReturn(true);
+ createInternetDialog();
+
+ mInternetDialog.updateDialog(false);
+
+ // Enable Wi-Fi switch and hide restriction message in summary.
+ assertThat(mWifiToggleSwitch.isEnabled()).isTrue();
+ assertThat(mWifiToggleSummary.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
public void updateDialog_wifiOn_hideWifiScanNotify() {
// The preconditions WiFi ON and WiFi entries are already in setUp()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
index 5d16036..4270d72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
@@ -144,7 +144,7 @@
}
private fun setFractionToShade(fraction: Float) {
- shelf.setFractionToShade(fraction)
+ whenever(ambientState.fractionToShade).thenReturn(fraction)
}
private fun setOnLockscreen(isOnLockscreen: Boolean) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt
index 968e16a..c3658ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt
@@ -23,6 +23,8 @@
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.LockscreenShadeTransitionController
+import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
@@ -44,7 +46,7 @@
class NotificationStackSizeCalculatorTest : SysuiTestCase() {
@Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
-
+ @Mock private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController
@Mock private lateinit var stackLayout: NotificationStackScrollLayout
private val testableResources = mContext.getOrCreateTestableResources()
@@ -63,6 +65,7 @@
sizeCalculator =
NotificationStackSizeCalculator(
statusBarStateController = sysuiStatusBarStateController,
+ lockscreenShadeTransitionController = lockscreenShadeTransitionController,
testableResources.resources)
}
@@ -155,6 +158,55 @@
assertThat(height).isAtMost(availableSpace)
}
+ @Test
+ fun onLockscreen_onKeyguard_AndNotGoingToShade_returnsTrue() {
+ whenever(sysuiStatusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
+ whenever(lockscreenShadeTransitionController.fractionToShade).thenReturn(0f)
+ assertThat(sizeCalculator.onLockscreen()).isTrue()
+ }
+
+ @Test
+ fun onLockscreen_goingToShade_returnsFalse() {
+ whenever(sysuiStatusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
+ whenever(lockscreenShadeTransitionController.fractionToShade).thenReturn(0.5f)
+ assertThat(sizeCalculator.onLockscreen()).isFalse()
+ }
+
+ @Test
+ fun onLockscreen_notOnLockscreen_returnsFalse() {
+ whenever(sysuiStatusBarStateController.state).thenReturn(StatusBarState.SHADE)
+ whenever(lockscreenShadeTransitionController.fractionToShade).thenReturn(1f)
+ assertThat(sizeCalculator.onLockscreen()).isFalse()
+ }
+
+ @Test
+ fun spaceNeeded_onLockscreen_usesMinHeight() {
+ setGapHeight(0f)
+ // No divider height since we're testing one element where index = 0
+
+ val expandableView = createMockRow(rowHeight)
+ whenever(expandableView.getMinHeight(any())).thenReturn(5)
+ whenever(expandableView.intrinsicHeight).thenReturn(10)
+
+ val space = sizeCalculator.spaceNeeded(expandableView, visibleIndex = 0,
+ previousView = null, stack = stackLayout, onLockscreen = true)
+ assertThat(space).isEqualTo(5)
+ }
+
+ @Test
+ fun spaceNeeded_notOnLockscreen_usesIntrinsicHeight() {
+ setGapHeight(0f)
+ // No divider height since we're testing one element where index = 0
+
+ val expandableView = createMockRow(rowHeight)
+ whenever(expandableView.getMinHeight(any())).thenReturn(5)
+ whenever(expandableView.intrinsicHeight).thenReturn(10)
+
+ val space = sizeCalculator.spaceNeeded(expandableView, visibleIndex = 0,
+ previousView = null, stack = stackLayout, onLockscreen = false)
+ assertThat(space).isEqualTo(10)
+ }
+
private fun computeMaxKeyguardNotifications(
rows: List<ExpandableView>,
availableSpace: Float,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index 6b4dc58..1f90d0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -1,5 +1,6 @@
package com.android.systemui.statusbar.notification.stack
+import android.annotation.DimenRes
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
import com.android.systemui.R
@@ -31,6 +32,14 @@
mStatusBarKeyguardViewManager
)
+ private val testableResources = mContext.orCreateTestableResources
+
+ private fun px(@DimenRes id: Int): Float =
+ testableResources.resources.getDimensionPixelSize(id).toFloat()
+
+ private val bigGap = px(R.dimen.notification_section_divider_height)
+ private val smallGap = px(R.dimen.notification_section_divider_height_lockscreen)
+
@Before
fun setUp() {
whenever(notificationRow.viewState).thenReturn(expandableViewState)
@@ -80,4 +89,25 @@
val centeredY = ambientState.stackY + fullHeight / 2f - emptyShadeView.height / 2f
assertThat(emptyShadeView.viewState?.yTranslation).isEqualTo(centeredY)
}
+
+ @Test
+ fun getGapForLocation_onLockscreen_returnsSmallGap() {
+ val gap = stackScrollAlgorithm.getGapForLocation(
+ /* fractionToShade= */ 0f, /* onKeyguard= */ true)
+ assertThat(gap).isEqualTo(smallGap)
+ }
+
+ @Test
+ fun getGapForLocation_goingToShade_interpolatesGap() {
+ val gap = stackScrollAlgorithm.getGapForLocation(
+ /* fractionToShade= */ 0.5f, /* onKeyguard= */ true)
+ assertThat(gap).isEqualTo(smallGap * 0.5f + bigGap * 0.5f)
+ }
+
+ @Test
+ fun getGapForLocation_notOnLockscreen_returnsBigGap() {
+ val gap = stackScrollAlgorithm.getGapForLocation(
+ /* fractionToShade= */ 0f, /* onKeyguard= */ false)
+ assertThat(gap).isEqualTo(bigGap)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
index 01769e5..b1950ea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
@@ -20,6 +20,7 @@
import static android.view.View.VISIBLE;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -323,6 +324,7 @@
assertEquals(GONE, mWalletView.getCardCarousel().getVisibility());
assertEquals(VISIBLE, mWalletView.getEmptyStateView().getVisibility());
assertEquals(GONE, mWalletView.getErrorView().getVisibility());
+ assertTrue(mWalletView.getAppButton().hasOnClickListeners());
}
@Test
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 35f7e06..7cee203 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15093,7 +15093,7 @@
@GuardedBy("this")
final boolean canGcNowLocked() {
for (BroadcastQueue q : mBroadcastQueues) {
- if (!q.mParallelBroadcasts.isEmpty() || !q.mDispatcher.isEmpty()) {
+ if (!q.mParallelBroadcasts.isEmpty() || !q.mDispatcher.isIdle()) {
return false;
}
}
diff --git a/services/core/java/com/android/server/am/AppBatteryTracker.java b/services/core/java/com/android/server/am/AppBatteryTracker.java
index 90201a0..8c42d4d 100644
--- a/services/core/java/com/android/server/am/AppBatteryTracker.java
+++ b/services/core/java/com/android/server/am/AppBatteryTracker.java
@@ -266,22 +266,16 @@
}
FrameworkStatsLog.write(FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO,
uid,
- FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_UNKNOWN,
- FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__THRESHOLD__THRESHOLD_UNKNOWN,
- FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__UNKNOWN_TRACKER,
+ AppBackgroundRestrictionsInfo.LEVEL_UNKNOWN, // RestrictionLevel
+ AppBackgroundRestrictionsInfo.THRESHOLD_UNKNOWN,
+ AppBackgroundRestrictionsInfo.UNKNOWN_TRACKER,
null /*byte[] fgs_tracker_info*/,
getBatteryTrackerInfoProtoLocked(uid) /*byte[] battery_tracker_info*/,
null /*byte[] broadcast_events_tracker_info*/,
null /*byte[] bind_service_events_tracker_info*/,
- FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_UNKNOWN,
- FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__OPT_LEVEL__UNKNOWN,
- FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_UNKNOWN,
+ AppBackgroundRestrictionsInfo.REASON_UNKNOWN, // ExemptionReason
+ AppBackgroundRestrictionsInfo.UNKNOWN, // OptimizationLevel
+ AppBackgroundRestrictionsInfo.SDK_UNKNOWN, // TargetSdk
isLowRamDeviceStatic());
}
}
diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java
index bdda0b7..d70404f 100644
--- a/services/core/java/com/android/server/am/AppRestrictionController.java
+++ b/services/core/java/com/android/server/am/AppRestrictionController.java
@@ -116,6 +116,7 @@
import android.database.ContentObserver;
import android.graphics.drawable.Icon;
import android.net.Uri;
+import android.os.AppBackgroundRestrictionsInfo;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
@@ -123,7 +124,6 @@
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
-import android.os.PowerExemptionManager.ExemptionReason;
import android.os.PowerExemptionManager.ReasonCode;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -1095,6 +1095,14 @@
DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "restriction_exempted_packages";
/**
+ * Whether or not to show the notification for abusive apps, i.e. when the system
+ * detects it's draining significant amount of battery in the background.
+ * {@code true} - we'll show the prompt to user, {@code false} - we'll not show it.
+ */
+ static final String KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED =
+ DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "prompt_abusive_apps_to_bg_restricted";
+
+ /**
* Default value to {@link #mBgAutoRestrictedBucket}.
*/
static final boolean DEFAULT_BG_AUTO_RESTRICTED_BUCKET_ON_BG_RESTRICTION = false;
@@ -1119,6 +1127,11 @@
*/
final boolean mDefaultBgPromptFgsWithNotiToBgRestricted;
+ /**
+ * Default value to {@link #mBgPromptAbusiveAppsToBgRestricted}.
+ */
+ final boolean mDefaultBgPromptAbusiveAppToBgRestricted;
+
volatile boolean mBgAutoRestrictedBucket;
volatile boolean mRestrictedBucketEnabled;
@@ -1144,10 +1157,17 @@
*/
volatile boolean mBgPromptFgsWithNotiOnLongRunning;
+ /**
+ * @see #KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED.
+ */
+ volatile boolean mBgPromptAbusiveAppsToBgRestricted;
+
ConstantsObserver(Handler handler, Context context) {
super(handler);
mDefaultBgPromptFgsWithNotiToBgRestricted = context.getResources().getBoolean(
com.android.internal.R.bool.config_bg_prompt_fgs_with_noti_to_bg_restricted);
+ mDefaultBgPromptAbusiveAppToBgRestricted = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_bg_prompt_abusive_apps_to_bg_restricted);
}
@Override
@@ -1172,6 +1192,9 @@
case KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING:
updateBgPromptFgsWithNotiOnLongRunning();
break;
+ case KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED:
+ updateBgPromptAbusiveAppToBgRestricted();
+ break;
case KEY_BG_RESTRICTION_EXEMPTED_PACKAGES:
updateBgRestrictionExemptedPackages();
break;
@@ -1209,6 +1232,7 @@
updateBgLongFgsNotificationMinimalInterval();
updateBgPromptFgsWithNotiToBgRestricted();
updateBgPromptFgsWithNotiOnLongRunning();
+ updateBgPromptAbusiveAppToBgRestricted();
updateBgRestrictionExemptedPackages();
}
@@ -1251,6 +1275,13 @@
DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING);
}
+ private void updateBgPromptAbusiveAppToBgRestricted() {
+ mBgPromptAbusiveAppsToBgRestricted = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED,
+ mDefaultBgPromptAbusiveAppToBgRestricted);
+ }
+
private void updateBgRestrictionExemptedPackages() {
final String settings = DeviceConfig.getString(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -1290,6 +1321,10 @@
pw.print('=');
pw.println(mBgPromptFgsWithNotiToBgRestricted);
pw.print(prefix);
+ pw.print(KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED);
+ pw.print('=');
+ pw.println(mBgPromptAbusiveAppsToBgRestricted);
+ pw.print(prefix);
pw.print(KEY_BG_RESTRICTION_EXEMPTED_PACKAGES);
pw.print('=');
pw.println(mBgRestrictionExemptedPackages.toString());
@@ -1881,76 +1916,59 @@
private int getRestrictionLevelStatsd(@RestrictionLevel int level) {
switch (level) {
case RESTRICTION_LEVEL_UNKNOWN:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_UNKNOWN;
+ return AppBackgroundRestrictionsInfo.LEVEL_UNKNOWN;
case RESTRICTION_LEVEL_UNRESTRICTED:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_UNRESTRICTED;
+ return AppBackgroundRestrictionsInfo.LEVEL_UNRESTRICTED;
case RESTRICTION_LEVEL_EXEMPTED:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_EXEMPTED;
+ return AppBackgroundRestrictionsInfo.LEVEL_EXEMPTED;
case RESTRICTION_LEVEL_ADAPTIVE_BUCKET:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_ADAPTIVE_BUCKET;
+ return AppBackgroundRestrictionsInfo.LEVEL_ADAPTIVE_BUCKET;
case RESTRICTION_LEVEL_RESTRICTED_BUCKET:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_RESTRICTED_BUCKET;
+ return AppBackgroundRestrictionsInfo.LEVEL_RESTRICTED_BUCKET;
case RESTRICTION_LEVEL_BACKGROUND_RESTRICTED:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_BACKGROUND_RESTRICTED;
+ return AppBackgroundRestrictionsInfo.LEVEL_BACKGROUND_RESTRICTED;
case RESTRICTION_LEVEL_HIBERNATION:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_HIBERNATION;
+ return AppBackgroundRestrictionsInfo.LEVEL_HIBERNATION;
default:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__RESTRICTION_LEVEL__LEVEL_UNKNOWN;
+ return AppBackgroundRestrictionsInfo.LEVEL_UNKNOWN;
}
}
private int getThresholdStatsd(int reason) {
switch (reason) {
case REASON_MAIN_FORCED_BY_SYSTEM:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__THRESHOLD__THRESHOLD_RESTRICTED;
+ return AppBackgroundRestrictionsInfo.THRESHOLD_RESTRICTED;
case REASON_MAIN_FORCED_BY_USER:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__THRESHOLD__THRESHOLD_USER;
+ return AppBackgroundRestrictionsInfo.THRESHOLD_USER;
default:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__THRESHOLD__THRESHOLD_UNKNOWN;
+ return AppBackgroundRestrictionsInfo.THRESHOLD_UNKNOWN;
}
}
private int getTrackerTypeStatsd(@TrackerType int type) {
switch (type) {
case TRACKER_TYPE_BATTERY:
- return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__BATTERY_TRACKER;
+ return AppBackgroundRestrictionsInfo.BATTERY_TRACKER;
case TRACKER_TYPE_BATTERY_EXEMPTION:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__BATTERY_EXEMPTION_TRACKER;
+ return AppBackgroundRestrictionsInfo.BATTERY_EXEMPTION_TRACKER;
case TRACKER_TYPE_FGS:
- return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__FGS_TRACKER;
+ return AppBackgroundRestrictionsInfo.FGS_TRACKER;
case TRACKER_TYPE_MEDIA_SESSION:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__MEDIA_SESSION_TRACKER;
+ return AppBackgroundRestrictionsInfo.MEDIA_SESSION_TRACKER;
case TRACKER_TYPE_PERMISSION:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__PERMISSION_TRACKER;
+ return AppBackgroundRestrictionsInfo.PERMISSION_TRACKER;
case TRACKER_TYPE_BROADCAST_EVENTS:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__BROADCAST_EVENTS_TRACKER;
+ return AppBackgroundRestrictionsInfo.BROADCAST_EVENTS_TRACKER;
case TRACKER_TYPE_BIND_SERVICE_EVENTS:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__BIND_SERVICE_EVENTS_TRACKER;
+ return AppBackgroundRestrictionsInfo.BIND_SERVICE_EVENTS_TRACKER;
default:
- return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TRACKER__UNKNOWN_TRACKER;
+ return AppBackgroundRestrictionsInfo.UNKNOWN_TRACKER;
}
}
- private @ExemptionReason int getExemptionReasonStatsd(int uid, @RestrictionLevel int level) {
+ private int getExemptionReasonStatsd(int uid, @RestrictionLevel int level) {
if (level != RESTRICTION_LEVEL_EXEMPTED) {
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__EXEMPTION_REASON__REASON_DENIED;
+ return AppBackgroundRestrictionsInfo.REASON_DENIED;
}
@ReasonCode final int reasonCode = getBackgroundRestrictionExemptionReason(uid);
@@ -1960,16 +1978,15 @@
private int getOptimizationLevelStatsd(@RestrictionLevel int level) {
switch (level) {
case RESTRICTION_LEVEL_UNKNOWN:
- return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__OPT_LEVEL__UNKNOWN;
+ return AppBackgroundRestrictionsInfo.UNKNOWN;
case RESTRICTION_LEVEL_UNRESTRICTED:
- return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__OPT_LEVEL__NOT_OPTIMIZED;
+ return AppBackgroundRestrictionsInfo.NOT_OPTIMIZED;
case RESTRICTION_LEVEL_ADAPTIVE_BUCKET:
- return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__OPT_LEVEL__OPTIMIZED;
+ return AppBackgroundRestrictionsInfo.OPTIMIZED;
case RESTRICTION_LEVEL_BACKGROUND_RESTRICTED:
- return FrameworkStatsLog
- .APP_BACKGROUND_RESTRICTIONS_INFO__OPT_LEVEL__BACKGROUND_RESTRICTED;
+ return AppBackgroundRestrictionsInfo.BACKGROUND_RESTRICTED;
default:
- return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__OPT_LEVEL__UNKNOWN;
+ return AppBackgroundRestrictionsInfo.UNKNOWN;
}
}
@@ -1977,26 +1994,26 @@
private int getTargetSdkStatsd(String packageName) {
final PackageManager pm = mInjector.getPackageManager();
if (pm == null) {
- return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_UNKNOWN;
+ return AppBackgroundRestrictionsInfo.SDK_UNKNOWN;
}
try {
final PackageInfo pkg = pm.getPackageInfo(packageName, 0 /* flags */);
if (pkg == null || pkg.applicationInfo == null) {
- return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_UNKNOWN;
+ return AppBackgroundRestrictionsInfo.SDK_UNKNOWN;
}
final int targetSdk = pkg.applicationInfo.targetSdkVersion;
if (targetSdk < Build.VERSION_CODES.S) {
- return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_PRE_S;
+ return AppBackgroundRestrictionsInfo.SDK_PRE_S;
} else if (targetSdk < Build.VERSION_CODES.TIRAMISU) {
- return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_S;
+ return AppBackgroundRestrictionsInfo.SDK_S;
} else if (targetSdk == Build.VERSION_CODES.TIRAMISU) {
- return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_T;
+ return AppBackgroundRestrictionsInfo.SDK_T;
} else {
- return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_UNKNOWN;
+ return AppBackgroundRestrictionsInfo.SDK_UNKNOWN;
}
} catch (PackageManager.NameNotFoundException ignored) {
}
- return FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO__TARGET_SDK__SDK_UNKNOWN;
+ return AppBackgroundRestrictionsInfo.SDK_UNKNOWN;
}
private void applyRestrictionLevel(String pkgName, int uid,
@@ -2296,6 +2313,13 @@
}
void postRequestBgRestrictedIfNecessary(String packageName, int uid) {
+ if (!mBgController.mConstantsObserver.mBgPromptAbusiveAppsToBgRestricted) {
+ if (DEBUG_BG_RESTRICTION_CONTROLLER) {
+ Slog.i(TAG, "Not requesting bg-restriction due to config");
+ }
+ return;
+ }
+
final Intent intent = new Intent(Settings.ACTION_VIEW_ADVANCED_POWER_USAGE_DETAIL);
intent.setData(Uri.fromParts(PACKAGE_SCHEME, packageName, null));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
diff --git a/services/core/java/com/android/server/am/BroadcastDispatcher.java b/services/core/java/com/android/server/am/BroadcastDispatcher.java
index 872531a..49477ad 100644
--- a/services/core/java/com/android/server/am/BroadcastDispatcher.java
+++ b/services/core/java/com/android/server/am/BroadcastDispatcher.java
@@ -512,12 +512,24 @@
*/
public boolean isEmpty() {
synchronized (mLock) {
+ return isIdle()
+ && getBootCompletedBroadcastsUidsSize(Intent.ACTION_LOCKED_BOOT_COMPLETED) == 0
+ && getBootCompletedBroadcastsUidsSize(Intent.ACTION_BOOT_COMPLETED) == 0;
+ }
+ }
+
+ /**
+ * Have less check than {@link #isEmpty()}.
+ * The dispatcher is considered as idle even with deferred LOCKED_BOOT_COMPLETED/BOOT_COMPLETED
+ * broadcasts because those can be deferred until the first time the uid's process is started.
+ * @return
+ */
+ public boolean isIdle() {
+ synchronized (mLock) {
return mCurrentBroadcast == null
&& mOrderedBroadcasts.isEmpty()
&& isDeferralsListEmpty(mDeferredBroadcasts)
- && isDeferralsListEmpty(mAlarmBroadcasts)
- && getBootCompletedBroadcastsUidsSize(Intent.ACTION_LOCKED_BOOT_COMPLETED) == 0
- && getBootCompletedBroadcastsUidsSize(Intent.ACTION_BOOT_COMPLETED) == 0;
+ && isDeferralsListEmpty(mAlarmBroadcasts);
}
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 8a7fece..3ba99a8 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -2218,7 +2218,7 @@
}
boolean isIdle() {
- return mParallelBroadcasts.isEmpty() && mDispatcher.isEmpty()
+ return mParallelBroadcasts.isEmpty() && mDispatcher.isIdle()
&& (mPendingBroadcast == null);
}
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 849f530..349174d 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -207,6 +207,9 @@
STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
STORAGE_PERMISSIONS.add(Manifest.permission.ACCESS_MEDIA_LOCATION);
+ STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_AUDIO);
+ STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_VIDEO);
+ STORAGE_PERMISSIONS.add(Manifest.permission.READ_MEDIA_IMAGES);
}
private static final Set<String> NEARBY_DEVICES_PERMISSIONS = new ArraySet<>();
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
index 9aa53f1..7baec62 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
@@ -79,7 +79,8 @@
import java.util.function.Function;
/** Resolves all Android component types [activities, services, providers and receivers]. */
-public class ComponentResolver extends ComponentResolverLocked implements Snappable {
+public class ComponentResolver extends ComponentResolverLocked implements
+ Snappable<ComponentResolverApi> {
private static final boolean DEBUG = false;
private static final String TAG = "PackageManager";
private static final boolean DEBUG_FILTERS = false;
@@ -166,11 +167,13 @@
mProvidersByAuthority = new ArrayMap<>();
mDeferProtectedFilters = true;
- mSnapshot = new SnapshotCache<ComponentResolverApi>(this, this) {
+ mSnapshot = new SnapshotCache<>(this, this) {
@Override
public ComponentResolverApi createSnapshot() {
- return new ComponentResolverSnapshot(ComponentResolver.this,
- userNeedsBadgingCache);
+ synchronized (mLock) {
+ return new ComponentResolverSnapshot(ComponentResolver.this,
+ userNeedsBadgingCache);
+ }
}};
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index eaf82b6..2d7d705 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -138,8 +138,8 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.policy.ForceShowNavigationBarSettingsObserver;
import com.android.internal.policy.GestureNavigationSettingsObserver;
+import com.android.internal.policy.KidsModeSettingsObserver;
import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.policy.SystemBarUtils;
import com.android.internal.protolog.common.ProtoLog;
@@ -378,7 +378,7 @@
private final WindowManagerInternal.AppTransitionListener mAppTransitionListener;
- private final ForceShowNavigationBarSettingsObserver mForceShowNavigationBarSettingsObserver;
+ private final KidsModeSettingsObserver mKidsModeSettingsObserver;
private boolean mForceShowNavigationBarEnabled;
private class PolicyHandler extends Handler {
@@ -653,17 +653,17 @@
});
mHandler.post(mGestureNavigationSettingsObserver::register);
- mForceShowNavigationBarSettingsObserver = new ForceShowNavigationBarSettingsObserver(
+ mKidsModeSettingsObserver = new KidsModeSettingsObserver(
mHandler, mContext);
- mForceShowNavigationBarSettingsObserver.setOnChangeRunnable(() -> {
+ mKidsModeSettingsObserver.setOnChangeRunnable(() -> {
synchronized (mLock) {
mForceShowNavigationBarEnabled =
- mForceShowNavigationBarSettingsObserver.isEnabled();
+ mKidsModeSettingsObserver.isEnabled();
updateSystemBarAttributes();
}
});
- mForceShowNavigationBarEnabled = mForceShowNavigationBarSettingsObserver.isEnabled();
- mHandler.post(mForceShowNavigationBarSettingsObserver::register);
+ mForceShowNavigationBarEnabled = mKidsModeSettingsObserver.isEnabled();
+ mHandler.post(mKidsModeSettingsObserver::register);
}
/**
@@ -2861,7 +2861,7 @@
void release() {
mDisplayContent.mTransitionController.unregisterLegacyListener(mAppTransitionListener);
mHandler.post(mGestureNavigationSettingsObserver::unregister);
- mHandler.post(mForceShowNavigationBarSettingsObserver::unregister);
+ mHandler.post(mKidsModeSettingsObserver::unregister);
mImmersiveModeConfirmation.release();
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index fc407e6..efe617d 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -445,7 +445,7 @@
}
final int taskCount = visibleTasks.size();
- for (int i = 0; i < taskCount; i++) {
+ for (int i = taskCount - 1; i >= 0; i--) {
final Task task = visibleTasks.get(i);
if (skipAnimation(task)) {
continue;
@@ -746,7 +746,7 @@
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
"collectTaskRemoteAnimations, target: %s", target);
}
- }, true);
+ }, false /* traverseTopToBottom */);
}
void logRecentsAnimationStartTime(int durationMs) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 6f69e03..22714c6 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2007,8 +2007,7 @@
r.getDisplayContent().prepareAppTransition(TRANSIT_NONE);
final TaskFragment organizedTf = r.getOrganizedTaskFragment();
- // TODO: Does it make sense to only count non-finishing activities?
- final boolean singleActivity = task.getActivityCount() == 1;
+ final boolean singleActivity = task.getNonFinishingActivityCount() == 1;
final Task rootTask;
if (singleActivity) {
rootTask = task;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index bd078d8..9ea566e 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1380,14 +1380,6 @@
return getActivity(ActivityRecord::canBeTopRunning);
}
- int getActivityCount() {
- final int[] activityCount = new int[1];
- forAllActivities(ar -> {
- activityCount[0]++;
- });
- return activityCount[0];
- }
-
/**
* Return true if any activities in this task belongs to input uid.
*/
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 4e0d84c..e0346544 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1034,19 +1034,19 @@
// If the top activity is the resumed one, nothing to do.
if (mResumedActivity == next && next.isState(RESUMED)
&& taskDisplayArea.allResumedActivitiesComplete()) {
+ // Ensure the visibility gets updated before execute app transition.
+ taskDisplayArea.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
+ false /* preserveWindows */, true /* notifyClients */);
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
- // For devices that are not in fullscreen mode (e.g. freeform windows), it's possible
- // we still want to check if the visibility of other windows have changed (e.g. bringing
- // a fullscreen window forward to cover another freeform activity.)
- if (taskDisplayArea.inMultiWindowMode()) {
- if (taskDisplayArea.mDisplayContent != null
- && taskDisplayArea.mDisplayContent.mFocusedApp != next) {
- taskDisplayArea.mDisplayContent.setFocusedApp(next);
- }
- taskDisplayArea.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */, true /* notifyClients */);
+
+ // In a multi-resumed environment, like in a freeform device, the top
+ // activity can be resumed, but it might not be the focused app.
+ // Set focused app when top activity is resumed
+ if (taskDisplayArea.inMultiWindowMode() && taskDisplayArea.mDisplayContent != null
+ && taskDisplayArea.mDisplayContent.mFocusedApp != next) {
+ taskDisplayArea.mDisplayContent.setFocusedApp(next);
}
ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Top activity "
+ "resumed %s", next);
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
index c0b4f0f..ac54293 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
@@ -585,6 +585,7 @@
DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketThreshold = null;
DeviceConfigSession<Float> bgCurrentDrainBgRestrictedThreshold = null;
DeviceConfigSession<Boolean> bgPromptFgsWithNotiToBgRestricted = null;
+ DeviceConfigSession<Boolean> bgPromptAbusiveAppToBgRestricted = null;
DeviceConfigSession<Long> bgNotificationMinInterval = null;
DeviceConfigSession<Integer> bgBatteryExemptionTypes = null;
DeviceConfigSession<Boolean> bgCurrentDrainDecoupleThresholds = null;
@@ -642,6 +643,14 @@
R.bool.config_bg_prompt_fgs_with_noti_to_bg_restricted));
bgPromptFgsWithNotiToBgRestricted.set(true);
+ bgPromptAbusiveAppToBgRestricted = new DeviceConfigSession<>(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ ConstantsObserver.KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED,
+ DeviceConfig::getBoolean,
+ mContext.getResources().getBoolean(
+ R.bool.config_bg_prompt_abusive_apps_to_bg_restricted));
+ bgPromptAbusiveAppToBgRestricted.set(true);
+
bgNotificationMinInterval = new DeviceConfigSession<>(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
ConstantsObserver.KEY_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL,
@@ -1055,6 +1064,7 @@
closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold);
closeIfNotNull(bgCurrentDrainBgRestrictedThreshold);
closeIfNotNull(bgPromptFgsWithNotiToBgRestricted);
+ closeIfNotNull(bgPromptAbusiveAppToBgRestricted);
closeIfNotNull(bgNotificationMinInterval);
closeIfNotNull(bgBatteryExemptionTypes);
closeIfNotNull(bgCurrentDrainDecoupleThresholds);
@@ -1613,6 +1623,7 @@
DeviceConfigSession<String> bgPermissionsInMonitor = null;
DeviceConfigSession<Boolean> bgCurrentDrainHighThresholdByBgLocation = null;
DeviceConfigSession<Boolean> bgCurrentDrainDecoupleThresholds = null;
+ DeviceConfigSession<Boolean> bgPromptAbusiveAppToBgRestricted = null;
mBgRestrictionController.addAppBackgroundRestrictionListener(listener);
@@ -1751,6 +1762,14 @@
AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLD);
bgCurrentDrainDecoupleThresholds.set(true);
+ bgPromptAbusiveAppToBgRestricted = new DeviceConfigSession<>(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ ConstantsObserver.KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED,
+ DeviceConfig::getBoolean,
+ mContext.getResources().getBoolean(
+ R.bool.config_bg_prompt_abusive_apps_to_bg_restricted));
+ bgPromptAbusiveAppToBgRestricted.set(true);
+
mCurrentTimeMillis = 10_000L;
doReturn(mCurrentTimeMillis - windowMs).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis).when(stats).getStatsEndTimestamp();
@@ -2168,6 +2187,7 @@
closeIfNotNull(bgBatteryExemptionTypes);
closeIfNotNull(bgPermissionMonitorEnabled);
closeIfNotNull(bgPermissionsInMonitor);
+ closeIfNotNull(bgPromptAbusiveAppToBgRestricted);
closeIfNotNull(bgCurrentDrainHighThresholdByBgLocation);
closeIfNotNull(bgCurrentDrainDecoupleThresholds);
}