Skip to content

Commit

Permalink
SystemUI: Implement burn-in protection for status/navbar
Browse files Browse the repository at this point in the history
Devices with OLED display suffer from
status-bar's notification items and nagivation bar's software keys
causing permanent burn-ins when used long-term.

Moving all items in the area
both horizontally and vertically workarounds this problem.

This new feature can be enabled by setting
config_statusBarBurnInProtection to true.

The shifting interval can be configured with config_shift_interval.
The default shifting interval is 60 seconds.

Forward-ported to oreo-mr1.

Change-Id: I8df1ebc8bc0f359fe5a6a1fe11aa6201237a7359

SystemUI: rework statusbar burn-in protection controller

* Turns out that this controller was instantiated twice resulting in two timers running simultaneously which resulted in views to shift abruptly.
  Since the shift amount was too low it was not noticeable at all. So now we instantiate it once with all final dependencies and inject PhoneStatusBarView in fragment transaction.
* Finalized many instance variables and a reference to the main handler is kept instead of creating new ones in each cycle
* simplified / generalised the shift algorithm a bit so that it's easily configurable
* added a callback to reload shift vars on screen density changes
* additional changes:
* use the same controller for navigation handle, saves some cpu time

Signed-off-by: jhonboy121 <[email protected]>

SystemUI: inject BurnInProtectionController

Signed-off-by: jhonboy121 <[email protected]>

[jhonboy121]: use the scoped SysUISingleton annotation

SystemUI: BurnInProtectionController: rewrite in kotlin and improvements
* ditched TimerTask in favor of coroutines

Signed-off-by: jhonboy121 <[email protected]>

[jhonboy121]:
* adapted to A13
* use BurnInHelper util functions for calculating offset

[ghostrider-reborn]:
* use NavigationBarView directly instead of CentralSurfaces
* rework timer and offset calculation logic

SystemUI: Enable statusbar burn-in protection by default

 * AOSP already provides a config for burn-in protection
   so enable statusbar burn-in protection based on that

 * To forcefully disable it, set
   config_statusBarBurnInProtection to false

Change-Id: I1a0b5c06ed6092153a35cb1cdc12b3b5e865ce8f

SystemUI: BurnInProtectionController: offset less aggressively

Change-Id: Ib37b0fde6edfc34cad8876d2e01ba4f37f323036
Signed-off-by: jhonboy121 <[email protected]>

SystemUI: Make setNavigationBarView and setPhoneStatusBarView nullable

 * this fixes a potential npe on devices without navbar or statusbar

Change-Id: Ia8e0ff844e24f67685ba20ac61a88d3256c9c648

Co-authored-by: jhonboy121 <[email protected]>
Co-authored-by: Adithya R <[email protected]>
Co-authored-by: Fabian Leutenegger <[email protected]>
Change-Id: I067022d43d20f43760a192b43569c31316a5337a
Signed-off-by: Adithya R <[email protected]>
  • Loading branch information
4 people authored and markakash committed Oct 4, 2024
1 parent d80a925 commit 4f6df87
Show file tree
Hide file tree
Showing 7 changed files with 291 additions and 4 deletions.
5 changes: 5 additions & 0 deletions packages/SystemUI/res/values/lineage_config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,9 @@
Possible values: 3, 3.1, 3.2, 4, 4.1, 4.2
-->
<string name="config_screenRecorderAVCProfileLevel" translatable="false">4.2</string>

<!-- Whether to enable burn-in protection for statusbar and navbar -->
<bool name="config_statusBarBurnInProtection">@*android:bool/config_enableBurnInProtection</bool>
<!-- Interval between subsequent shifting of statusbar and navbar contents, in seconds -->
<integer name="config_statusBarBurnInProtectionShiftInterval">60</integer>
</resources>
5 changes: 5 additions & 0 deletions packages/SystemUI/res/values/lineage_dimens.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,9 @@

<!-- Screen Record -->
<dimen name="screenrecord_dot_size">48dp</dimen>

<!-- Maximum horizontal offset of statusbar for burn-in protection -->
<dimen name="status_bar_offset_max_x">4dp</dimen>
<!-- Maximum vertical offset of statusbar for burn-in protection -->
<dimen name="status_bar_offset_max_y">4dp</dimen>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ fun getBurnInScale(): Float {
* @param amplitude maximum value of the function
* @return a value between 0 and amplitude
*/
private fun zigzag(x: Float, amplitude: Float, period: Float): Float {
fun zigzag(x: Float, amplitude: Float, period: Float): Float {
val xprime = x % period / (period / 2)
val interpolationAmount = if (xprime <= 1) xprime else 2 - xprime
return MathUtils.lerp(0f, amplitude, interpolationAmount)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import com.android.systemui.navigationbar.buttons.NearestTouchFrame;
import com.android.systemui.navigationbar.buttons.RotationContextButton;
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import com.android.systemui.navigationbar.gestural.NavigationHandle;
import com.android.systemui.recents.Recents;
import com.android.systemui.res.R;
import com.android.systemui.settings.DisplayTracker;
Expand All @@ -83,6 +84,7 @@
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
import com.android.systemui.statusbar.policy.Offset;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.pip.Pip;

Expand Down Expand Up @@ -186,6 +188,9 @@ public class NavigationBarView extends FrameLayout {
private boolean mShowCursorKeys;
private boolean mImeVisible;

@Nullable
private ViewGroup mNavigationBarContents = null;

private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
private boolean mHomeAppearing;
Expand Down Expand Up @@ -889,12 +894,31 @@ public void setAccessibilityButtonState(final boolean visible, final boolean lon
mContextualButtonGroup.setButtonVisibility(R.id.accessibility_button, visible);
}

public void offsetNavBar(Offset offset) {
if (isGesturalMode(mNavBarMode)) {
final NavigationHandle handle = (NavigationHandle) getHomeHandle().getCurrentView();
if (handle != null) {
handle.setTranslationY(offset.getY());
handle.invalidate();
}
return;
}
if (mNavigationBarContents == null) {
return;
}
mNavigationBarContents.setTranslationX(offset.getX());
mNavigationBarContents.setTranslationY(offset.getY());
invalidate();
}

@Override
public void onFinishInflate() {
super.onFinishInflate();
mNavigationInflaterView = findViewById(R.id.navigation_inflater);
mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);

mNavigationBarContents = (ViewGroup) findViewById(R.id.nav_buttons);

updateOrientationViews();
reloadNavIcons();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@
import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.statusbar.policy.BurnInProtectionController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
Expand Down Expand Up @@ -598,6 +599,8 @@ public int getId() {

private final SceneContainerFlags mSceneContainerFlags;

private final BurnInProtectionController mBurnInProtectionController;

/**
* Public constructor for CentralSurfaces.
*
Expand Down Expand Up @@ -709,7 +712,8 @@ public CentralSurfacesImpl(
UserTracker userTracker,
Provider<FingerprintManager> fingerprintManager,
ActivityStarter activityStarter,
SceneContainerFlags sceneContainerFlags
SceneContainerFlags sceneContainerFlags,
BurnInProtectionController burnInProtectionController
) {
mContext = context;
mNotificationsController = notificationsController;
Expand Down Expand Up @@ -805,6 +809,7 @@ public CentralSurfacesImpl(
mFingerprintManager = fingerprintManager;
mActivityStarter = activityStarter;
mSceneContainerFlags = sceneContainerFlags;
mBurnInProtectionController = burnInProtectionController;

mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
mStartingSurfaceOptional = startingSurfaceOptional;
Expand Down Expand Up @@ -1228,6 +1233,7 @@ protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
mShadeSurface.updateExpansionAndVisibility();
setBouncerShowingForStatusBarComponents(mBouncerShowing);
checkBarModes();
mBurnInProtectionController.setPhoneStatusBarView(mStatusBarView);
});
mStatusBarInitializer.initializeStatusBar();

Expand Down Expand Up @@ -1498,6 +1504,7 @@ protected void setUpDisableFlags(int state1, int state2) {
// Try to remove this.
protected void createNavigationBar(@Nullable RegisterStatusBarResult result) {
mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */, result);
mBurnInProtectionController.setNavigationBarView(getNavigationBarView());
}

/**
Expand Down Expand Up @@ -2503,6 +2510,8 @@ public void onFinishedGoingToSleep() {

updateNotificationPanelTouchState();
getNotificationShadeWindowViewController().cancelCurrentTouch();
mBurnInProtectionController.stopShiftTimer();

if (mLaunchCameraOnFinishedGoingToSleep) {
mLaunchCameraOnFinishedGoingToSleep = false;

Expand Down Expand Up @@ -2668,6 +2677,7 @@ public void onFinishedWakingUp() {
}
}
updateScrimController();
mBurnInProtectionController.startShiftTimer();
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.Rect;
import android.inputmethodservice.InputMethodService;
Expand Down Expand Up @@ -56,6 +57,7 @@
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
import com.android.systemui.statusbar.policy.Clock;
import com.android.systemui.statusbar.policy.Offset;
import com.android.systemui.statusbar.window.StatusBarWindowController;
import com.android.systemui.user.ui.binder.StatusBarUserChipViewBinder;
import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel;
Expand Down Expand Up @@ -84,6 +86,8 @@ public class PhoneStatusBarView extends FrameLayout implements Callbacks {
private Gefingerpoken mTouchEventHandler;
private int mDensity;
private float mFontScale;
@Nullable
private ViewGroup mStatusBarContents = null;

/**
* Draw this many pixels into the left/right side of the cutout to optimally use the space
Expand Down Expand Up @@ -156,6 +160,7 @@ public void onFinishInflate() {
mBattery = findViewById(R.id.battery);
mClockController = new ClockController(getContext(), this);
mCutoutSpace = findViewById(R.id.cutout_space_view);
mStatusBarContents = (ViewGroup) findViewById(R.id.status_bar_contents);

updateResources();
}
Expand Down Expand Up @@ -221,6 +226,15 @@ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
return super.onApplyWindowInsets(insets);
}

public void offsetStatusBar(Offset offset) {
if (mStatusBarContents == null) {
return;
}
mStatusBarContents.setTranslationX(offset.getX());
mStatusBarContents.setTranslationY(offset.getY());
invalidate();
}

/**
* @return boolean indicating if we need to update the cutout location / margins
*/
Expand Down Expand Up @@ -336,7 +350,7 @@ private void updatePaddings() {
int statusBarPaddingStart = getResources().getDimensionPixelSize(
R.dimen.status_bar_padding_start);

findViewById(R.id.status_bar_contents).setPaddingRelative(
mStatusBarContents.setPaddingRelative(
statusBarPaddingStart,
getResources().getDimensionPixelSize(R.dimen.status_bar_padding_top),
getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end),
Expand Down
Loading

0 comments on commit 4f6df87

Please sign in to comment.