Merge "Remove all GHBM logic" into tm-dev

This commit is contained in:
Grace Cheng
2022-04-04 16:07:33 +00:00
committed by Android (Google) Code Review
9 changed files with 21 additions and 307 deletions

View File

@@ -24,31 +24,20 @@ package android.hardware.fingerprint;
* @hide * @hide
*/ */
oneway interface IUdfpsHbmListener { oneway interface IUdfpsHbmListener {
/** HBM that applies to the whole screen. */
const int GLOBAL_HBM = 0;
/** HBM that only applies to a portion of the screen. */
const int LOCAL_HBM = 1;
/** /**
* UdfpsController will call this method when the HBM is enabled. * UdfpsController will call this method when the HBM is enabled.
* *
* @param hbmType The type of HBM that was enabled. See
* {@link com.android.systemui.biometrics.UdfpsHbmTypes}.
* @param displayId The displayId for which the HBM is enabled. See * @param displayId The displayId for which the HBM is enabled. See
* {@link android.view.Display#getDisplayId()}. * {@link android.view.Display#getDisplayId()}.
*/ */
void onHbmEnabled(int hbmType, int displayId); void onHbmEnabled(int displayId);
/** /**
* UdfpsController will call this method when the HBM is disabled. * UdfpsController will call this method when the HBM is disabled.
* *
* @param hbmType The type of HBM that was disabled. See
* {@link com.android.systemui.biometrics.UdfpsHbmTypes}.
* @param displayId The displayId for which the HBM is disabled. See * @param displayId The displayId for which the HBM is disabled. See
* {@link android.view.Display#getDisplayId()}. * {@link android.view.Display#getDisplayId()}.
*/ */
void onHbmDisabled(int hbmType, int displayId); void onHbmDisabled(int displayId);
} }

View File

@@ -28,10 +28,4 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"/> android:layout_height="match_parent"/>
<com.android.systemui.biometrics.UdfpsSurfaceView
android:id="@+id/hbm_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"/>
</com.android.systemui.biometrics.UdfpsView> </com.android.systemui.biometrics.UdfpsView>

View File

@@ -17,9 +17,6 @@
package com.android.systemui.biometrics; package com.android.systemui.biometrics;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.view.Surface;
import com.android.systemui.biometrics.UdfpsHbmTypes.HbmType;
/** /**
* Interface for controlling the high-brightness mode (HBM). UdfpsView can use this callback to * Interface for controlling the high-brightness mode (HBM). UdfpsView can use this callback to
@@ -36,24 +33,21 @@ public interface UdfpsHbmProvider {
* This method must be called from the UI thread. The callback, if provided, will also be * This method must be called from the UI thread. The callback, if provided, will also be
* invoked from the UI thread. * invoked from the UI thread.
* *
* @param hbmType The type of HBM that should be enabled. See {@link UdfpsHbmTypes}.
* @param surface The surface for which the HBM is requested, in case the HBM implementation
* needs to set special surface flags to enable the HBM. Can be null.
* @param onHbmEnabled A runnable that will be executed once HBM is enabled. * @param onHbmEnabled A runnable that will be executed once HBM is enabled.
*/ */
void enableHbm(@HbmType int hbmType, @Nullable Surface surface, void enableHbm(@Nullable Runnable onHbmEnabled);
@Nullable Runnable onHbmEnabled);
/** /**
* UdfpsView will call this to disable the HBM when the illumination is not longer needed. * UdfpsView will call this to disable HBM when illumination is no longer needed.
* *
* This method is a no-op when HBM is already disabled. If HBM is enabled, this method will * This method will disable HBM if HBM is enabled. Otherwise, if HBM is already disabled,
* disable HBM for the {@code hbmType} and {@code surface} that were provided to the * this method is a no-op.
* corresponding {@link #enableHbm(int, Surface, Runnable)}.
* *
* The call must be made from the UI thread. The callback, if provided, will also be invoked * The call must be made from the UI thread. The callback, if provided, will also be invoked
* from the UI thread. * from the UI thread.
* *
*
*
* @param onHbmDisabled A runnable that will be executed once HBM is disabled. * @param onHbmDisabled A runnable that will be executed once HBM is disabled.
*/ */
void disableHbm(@Nullable Runnable onHbmDisabled); void disableHbm(@Nullable Runnable onHbmDisabled);

View File

@@ -1,39 +0,0 @@
/*
* Copyright (C) 2021 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;
import android.annotation.IntDef;
import android.hardware.fingerprint.IUdfpsHbmListener;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Different high-brightness mode (HBM) types that are relevant to this package.
*/
public final class UdfpsHbmTypes {
/** HBM that applies to the whole screen. */
public static final int GLOBAL_HBM = IUdfpsHbmListener.GLOBAL_HBM;
/** HBM that only applies to a portion of the screen. */
public static final int LOCAL_HBM = IUdfpsHbmListener.LOCAL_HBM;
@Retention(RetentionPolicy.SOURCE)
@IntDef({GLOBAL_HBM, LOCAL_HBM})
public @interface HbmType {
}
}

View File

@@ -1,145 +0,0 @@
/*
* Copyright (C) 2021 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;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* Surface View for providing the Global High-Brightness Mode (GHBM) illumination for UDFPS.
*/
public class UdfpsSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "UdfpsSurfaceView";
/**
* Notifies {@link UdfpsView} when to enable GHBM illumination.
*/
interface GhbmIlluminationListener {
/**
* @param surface the surface for which GHBM should be enabled.
* @param onIlluminatedRunnable a runnable that should be run after GHBM is enabled.
*/
void enableGhbm(@NonNull Surface surface, @Nullable Runnable onIlluminatedRunnable);
}
@NonNull private final SurfaceHolder mHolder;
@NonNull private final Paint mSensorPaint;
@Nullable private GhbmIlluminationListener mGhbmIlluminationListener;
@Nullable private Runnable mOnIlluminatedRunnable;
boolean mAwaitingSurfaceToStartIllumination;
boolean mHasValidSurface;
public UdfpsSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
// Make this SurfaceView draw on top of everything else in this window. This allows us to
// 1) Always show the HBM circle on top of everything else, and
// 2) Properly composite this view with any other animations in the same window no matter
// what contents are added in which order to this view hierarchy.
setZOrderOnTop(true);
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setFormat(PixelFormat.RGBA_8888);
mSensorPaint = new Paint(0 /* flags */);
mSensorPaint.setAntiAlias(true);
mSensorPaint.setARGB(255, 255, 255, 255);
mSensorPaint.setStyle(Paint.Style.FILL);
}
@Override public void surfaceCreated(SurfaceHolder holder) {
mHasValidSurface = true;
if (mAwaitingSurfaceToStartIllumination) {
doIlluminate(mOnIlluminatedRunnable);
mOnIlluminatedRunnable = null;
mAwaitingSurfaceToStartIllumination = false;
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// Unused.
}
@Override public void surfaceDestroyed(SurfaceHolder holder) {
mHasValidSurface = false;
}
void setGhbmIlluminationListener(@Nullable GhbmIlluminationListener listener) {
mGhbmIlluminationListener = listener;
}
/**
* Note: there is no corresponding method to stop GHBM illumination. It is expected that
* {@link UdfpsView} will hide this view, which would destroy the surface and remove the
* illumination dot.
*/
void startGhbmIllumination(@Nullable Runnable onIlluminatedRunnable) {
if (mGhbmIlluminationListener == null) {
Log.e(TAG, "startIllumination | mGhbmIlluminationListener is null");
return;
}
if (mHasValidSurface) {
doIlluminate(onIlluminatedRunnable);
} else {
mAwaitingSurfaceToStartIllumination = true;
mOnIlluminatedRunnable = onIlluminatedRunnable;
}
}
private void doIlluminate(@Nullable Runnable onIlluminatedRunnable) {
if (mGhbmIlluminationListener == null) {
Log.e(TAG, "doIlluminate | mGhbmIlluminationListener is null");
return;
}
mGhbmIlluminationListener.enableGhbm(mHolder.getSurface(), onIlluminatedRunnable);
}
/**
* Immediately draws the illumination dot on this SurfaceView's surface.
*/
void drawIlluminationDot(@NonNull RectF sensorRect) {
if (!mHasValidSurface) {
Log.e(TAG, "drawIlluminationDot | the surface is destroyed or was never created.");
return;
}
Canvas canvas = null;
try {
canvas = mHolder.lockCanvas();
canvas.drawOval(sensorRect, mSensorPaint);
} finally {
// Make sure the surface is never left in a bad state.
if (canvas != null) {
mHolder.unlockCanvasAndPost(canvas);
}
}
}
}

View File

@@ -22,26 +22,17 @@ import android.graphics.Paint
import android.graphics.PointF import android.graphics.PointF
import android.graphics.RectF import android.graphics.RectF
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.os.Build
import android.os.UserHandle
import android.provider.Settings
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Log import android.util.Log
import android.view.MotionEvent import android.view.MotionEvent
import android.view.Surface
import android.widget.FrameLayout import android.widget.FrameLayout
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.doze.DozeReceiver import com.android.systemui.doze.DozeReceiver
import com.android.systemui.biometrics.UdfpsHbmTypes.HbmType
private const val TAG = "UdfpsView" private const val TAG = "UdfpsView"
private const val SETTING_HBM_TYPE = "com.android.systemui.biometrics.UdfpsSurfaceView.hbmType"
@HbmType
private const val DEFAULT_HBM_TYPE = UdfpsHbmTypes.LOCAL_HBM
/** /**
* A view containing 1) A SurfaceView for HBM, and 2) A normal drawable view for all other * The main view group containing all UDFPS animations.
* animations.
*/ */
class UdfpsView( class UdfpsView(
context: Context, context: Context,
@@ -68,21 +59,6 @@ class UdfpsView(
com.android.internal.R.integer.config_udfps_illumination_transition_ms com.android.internal.R.integer.config_udfps_illumination_transition_ms
).toLong() ).toLong()
@HbmType
private val hbmType = if (Build.IS_ENG || Build.IS_USERDEBUG) {
Settings.Secure.getIntForUser(
context.contentResolver,
SETTING_HBM_TYPE,
DEFAULT_HBM_TYPE,
UserHandle.USER_CURRENT
)
} else {
DEFAULT_HBM_TYPE
}
// Only used for UdfpsHbmTypes.GLOBAL_HBM.
private var ghbmView: UdfpsSurfaceView? = null
/** View controller (can be different for enrollment, BiometricPrompt, Keyguard, etc.). */ /** View controller (can be different for enrollment, BiometricPrompt, Keyguard, etc.). */
var animationViewController: UdfpsAnimationViewController<*>? = null var animationViewController: UdfpsAnimationViewController<*>? = null
@@ -109,12 +85,6 @@ class UdfpsView(
return (animationViewController == null || !animationViewController!!.shouldPauseAuth()) return (animationViewController == null || !animationViewController!!.shouldPauseAuth())
} }
override fun onFinishInflate() {
if (hbmType == UdfpsHbmTypes.GLOBAL_HBM) {
ghbmView = findViewById(R.id.hbm_view)
}
}
override fun dozeTimeTick() { override fun dozeTimeTick() {
animationViewController?.dozeTimeTick() animationViewController?.dozeTimeTick()
} }
@@ -180,24 +150,11 @@ class UdfpsView(
override fun startIllumination(onIlluminatedRunnable: Runnable?) { override fun startIllumination(onIlluminatedRunnable: Runnable?) {
isIlluminationRequested = true isIlluminationRequested = true
animationViewController?.onIlluminationStarting() animationViewController?.onIlluminationStarting()
doIlluminate(onIlluminatedRunnable)
val gView = ghbmView
if (gView != null) {
gView.setGhbmIlluminationListener(this::doIlluminate)
gView.visibility = VISIBLE
gView.startGhbmIllumination(onIlluminatedRunnable)
} else {
doIlluminate(null /* surface */, onIlluminatedRunnable)
}
} }
private fun doIlluminate(surface: Surface?, onIlluminatedRunnable: Runnable?) { private fun doIlluminate(onIlluminatedRunnable: Runnable?) {
if (ghbmView != null && surface == null) { hbmProvider?.enableHbm() {
Log.e(TAG, "doIlluminate | surface must be non-null for GHBM")
}
hbmProvider?.enableHbm(hbmType, surface) {
ghbmView?.drawIlluminationDot(sensorRect)
if (onIlluminatedRunnable != null) { if (onIlluminatedRunnable != null) {
// No framework API can reliably tell when a frame reaches the panel. A timeout // No framework API can reliably tell when a frame reaches the panel. A timeout
// is the safest solution. // is the safest solution.
@@ -211,10 +168,6 @@ class UdfpsView(
override fun stopIllumination() { override fun stopIllumination() {
isIlluminationRequested = false isIlluminationRequested = false
animationViewController?.onIlluminationStopped() animationViewController?.onIlluminationStopped()
ghbmView?.let { view ->
view.setGhbmIlluminationListener(null)
view.visibility = INVISIBLE
}
hbmProvider?.disableHbm(null /* onHbmDisabled */) hbmProvider?.disableHbm(null /* onHbmDisabled */)
} }
} }

View File

@@ -23,7 +23,6 @@ import android.testing.AndroidTestingRunner
import android.testing.TestableLooper import android.testing.TestableLooper
import android.testing.ViewUtils import android.testing.ViewUtils
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Surface
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
@@ -37,7 +36,6 @@ import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.never import org.mockito.Mockito.never
import org.mockito.Mockito.nullable import org.mockito.Mockito.nullable
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
@@ -148,7 +146,7 @@ class UdfpsViewTest : SysuiTestCase() {
view.startIllumination(onDone) view.startIllumination(onDone)
val illuminator = withArgCaptor<Runnable> { val illuminator = withArgCaptor<Runnable> {
verify(hbmProvider).enableHbm(anyInt(), nullable(Surface::class.java), capture()) verify(hbmProvider).enableHbm(capture())
} }
assertThat(view.isIlluminationRequested).isTrue() assertThat(view.isIlluminationRequested).isTrue()

View File

@@ -2098,7 +2098,6 @@ public class DisplayModeDirector {
private class UdfpsObserver extends IUdfpsHbmListener.Stub { private class UdfpsObserver extends IUdfpsHbmListener.Stub {
private final SparseBooleanArray mLocalHbmEnabled = new SparseBooleanArray(); private final SparseBooleanArray mLocalHbmEnabled = new SparseBooleanArray();
private final SparseBooleanArray mGlobalHbmEnabled = new SparseBooleanArray();
public void observe() { public void observe() {
StatusBarManagerInternal statusBar = StatusBarManagerInternal statusBar =
@@ -2109,39 +2108,27 @@ public class DisplayModeDirector {
} }
@Override @Override
public void onHbmEnabled(int hbmType, int displayId) { public void onHbmEnabled(int displayId) {
synchronized (mLock) { synchronized (mLock) {
updateHbmStateLocked(hbmType, displayId, true /*enabled*/); updateHbmStateLocked(displayId, true /*enabled*/);
} }
} }
@Override @Override
public void onHbmDisabled(int hbmType, int displayId) { public void onHbmDisabled(int displayId) {
synchronized (mLock) { synchronized (mLock) {
updateHbmStateLocked(hbmType, displayId, false /*enabled*/); updateHbmStateLocked(displayId, false /*enabled*/);
} }
} }
private void updateHbmStateLocked(int hbmType, int displayId, boolean enabled) { private void updateHbmStateLocked(int displayId, boolean enabled) {
switch (hbmType) {
case UdfpsObserver.LOCAL_HBM:
mLocalHbmEnabled.put(displayId, enabled); mLocalHbmEnabled.put(displayId, enabled);
break;
case UdfpsObserver.GLOBAL_HBM:
mGlobalHbmEnabled.put(displayId, enabled);
break;
default:
Slog.w(TAG, "Unknown HBM type reported. Ignoring.");
return;
}
updateVoteLocked(displayId); updateVoteLocked(displayId);
} }
private void updateVoteLocked(int displayId) { private void updateVoteLocked(int displayId) {
final Vote vote; final Vote vote;
if (mGlobalHbmEnabled.get(displayId)) { if (mLocalHbmEnabled.get(displayId)) {
vote = Vote.forRefreshRates(60f, 60f);
} else if (mLocalHbmEnabled.get(displayId)) {
Display.Mode[] modes = mSupportedModesByDisplay.get(displayId); Display.Mode[] modes = mSupportedModesByDisplay.get(displayId);
float maxRefreshRate = 0f; float maxRefreshRate = 0f;
for (Display.Mode mode : modes) { for (Display.Mode mode : modes) {
@@ -2165,13 +2152,6 @@ public class DisplayModeDirector {
final String enabled = mLocalHbmEnabled.valueAt(i) ? "enabled" : "disabled"; final String enabled = mLocalHbmEnabled.valueAt(i) ? "enabled" : "disabled";
pw.println(" Display " + displayId + ": " + enabled); pw.println(" Display " + displayId + ": " + enabled);
} }
pw.println(" mGlobalHbmEnabled: ");
for (int i = 0; i < mGlobalHbmEnabled.size(); i++) {
final int displayId = mGlobalHbmEnabled.keyAt(i);
final String enabled = mGlobalHbmEnabled.valueAt(i) ? "enabled" : "disabled";
pw.println(" Display " + displayId + ": " + enabled);
}
} }
} }

View File

@@ -20,8 +20,8 @@ import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REF
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS; import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS; import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS; import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_SUNLIGHT;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_HDR; import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_HDR;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_SUNLIGHT;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE; import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE; import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE;
@@ -919,16 +919,6 @@ public class DisplayModeDirectorTest {
// Should be no vote initially // Should be no vote initially
Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_UDFPS); Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_UDFPS);
assertNull(vote); assertNull(vote);
// Enabling GHBM votes for 60hz
hbmListener.onHbmEnabled(IUdfpsHbmListener.GLOBAL_HBM, DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_UDFPS);
assertVoteForRefreshRate(vote, 60.f);
// Disabling GHBM removes the vote
hbmListener.onHbmDisabled(IUdfpsHbmListener.GLOBAL_HBM, DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_UDFPS);
assertNull(vote);
} }
@Test @Test