diff options
Diffstat (limited to 'packages/SystemUI/src/com/android')
48 files changed, 819 insertions, 312 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java index 3f3d8a5bfa4..e7b4bd831e4 100644 --- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java +++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java @@ -19,16 +19,12 @@ package com.android.keyguard; import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE; import static android.telephony.PhoneStateListener.LISTEN_NONE; -import static com.android.internal.telephony.PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM; - import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.wifi.WifiManager; import android.os.Handler; -import android.os.SystemProperties; -import android.telephony.CarrierConfigManager; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; @@ -37,20 +33,18 @@ import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; -import androidx.annotation.VisibleForTesting; - import com.android.internal.telephony.IccCardConstants; import com.android.internal.telephony.TelephonyIntents; -import com.android.internal.telephony.TelephonyProperties; import com.android.settingslib.WirelessUtils; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.keyguard.WakefulnessLifecycle; -import java.util.ArrayList; import java.util.List; import java.util.Objects; +import androidx.annotation.VisibleForTesting; + /** * Controller that generates text including the carrier names and/or the status of all the SIM * interfaces in the device. Through a callback, the updates can be retrieved either as a list or @@ -73,8 +67,6 @@ public class CarrierTextController { private Context mContext; private CharSequence mSeparator; private WakefulnessLifecycle mWakefulnessLifecycle; - @VisibleForTesting - protected boolean mDisplayOpportunisticSubscriptionCarrierText; private final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { @Override @@ -175,9 +167,6 @@ public class CarrierTextController { mSimSlotsNumber = ((TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE)).getPhoneCount(); mSimErrorState = new boolean[mSimSlotsNumber]; - updateDisplayOpportunisticSubscriptionCarrierText(SystemProperties.getBoolean( - TelephonyProperties.DISPLAY_OPPORTUNISTIC_SUBSCRIPTION_CARRIER_TEXT_PROPERTY_NAME, - false)); } /** @@ -254,63 +243,8 @@ public class CarrierTextController { } } - /** - * @param subscriptions - */ - private void filterMobileSubscriptionInSameGroup(List<SubscriptionInfo> subscriptions) { - if (subscriptions.size() == MAX_PHONE_COUNT_DUAL_SIM) { - SubscriptionInfo info1 = subscriptions.get(0); - SubscriptionInfo info2 = subscriptions.get(1); - if (info1.getGroupUuid() != null && info1.getGroupUuid().equals(info2.getGroupUuid())) { - // If both subscriptions are primary, show both. - if (!info1.isOpportunistic() && !info2.isOpportunistic()) return; - - // If carrier required, always show signal bar of primary subscription. - // Otherwise, show whichever subscription is currently active for Internet. - boolean alwaysShowPrimary = CarrierConfigManager.getDefaultConfig() - .getBoolean(CarrierConfigManager - .KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN); - if (alwaysShowPrimary) { - subscriptions.remove(info1.isOpportunistic() ? info1 : info2); - } else { - subscriptions.remove(info1.getSubscriptionId() == mActiveMobileDataSubscription - ? info2 : info1); - } - - } - } - } - - /** - * updates if opportunistic sub carrier text should be displayed or not - * - */ - @VisibleForTesting - public void updateDisplayOpportunisticSubscriptionCarrierText(boolean isEnable) { - mDisplayOpportunisticSubscriptionCarrierText = isEnable; - } - protected List<SubscriptionInfo> getSubscriptionInfo() { - List<SubscriptionInfo> subs; - if (mDisplayOpportunisticSubscriptionCarrierText) { - SubscriptionManager subscriptionManager = ((SubscriptionManager) mContext - .getSystemService( - Context.TELEPHONY_SUBSCRIPTION_SERVICE)); - subs = subscriptionManager.getActiveSubscriptionInfoList(false); - if (subs == null) { - subs = new ArrayList<>(); - } else { - filterMobileSubscriptionInSameGroup(subs); - } - } else { - subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false); - if (subs == null) { - subs = new ArrayList<>(); - } else { - filterMobileSubscriptionInSameGroup(subs); - } - } - return subs; + return mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(false); } protected void updateCarrierText() { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 7f1ea563b4d..98323908c8d 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -30,6 +30,7 @@ import static android.os.BatteryManager.EXTRA_PLUGGED; import static android.os.BatteryManager.EXTRA_STATUS; import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE; +import static com.android.internal.telephony.PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; @@ -77,6 +78,7 @@ import android.os.UserManager; import android.provider.Settings; import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; +import android.telephony.CarrierConfigManager; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; @@ -257,6 +259,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { private boolean mLogoutEnabled; // If the user long pressed the lock icon, disabling face auth for the current session. private boolean mLockIconPressed; + private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID; private final boolean mFingerprintWakeAndUnlock; @@ -394,9 +397,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } }; - private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { + @VisibleForTesting + public PhoneStateListener mPhoneStateListener = new PhoneStateListener() { @Override public void onActiveDataSubscriptionIdChanged(int subId) { + mActiveMobileDataSubscription = subId; mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED); } }; @@ -498,7 +503,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } - /** @return List of SubscriptionInfo records, maybe empty but never null */ + /** + * @return List of SubscriptionInfo records, maybe empty but never null. + */ public List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) { List<SubscriptionInfo> sil = mSubscriptionInfo; if (sil == null || forceReload) { @@ -510,7 +517,42 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } else { mSubscriptionInfo = sil; } - return mSubscriptionInfo; + return new ArrayList<>(mSubscriptionInfo); + } + + /** + * This method returns filtered list of SubscriptionInfo from {@link #getSubscriptionInfo}. + * above. Maybe empty but never null. + * + * In DSDS mode if both subscriptions are grouped and one is opportunistic, we filter out one + * of them based on carrier config. e.g. In this case we should only show one carrier name + * on the status bar and quick settings. + */ + public List<SubscriptionInfo> getFilteredSubscriptionInfo(boolean forceReload) { + List<SubscriptionInfo> subscriptions = getSubscriptionInfo(false); + if (subscriptions.size() == MAX_PHONE_COUNT_DUAL_SIM) { + SubscriptionInfo info1 = subscriptions.get(0); + SubscriptionInfo info2 = subscriptions.get(1); + if (info1.getGroupUuid() != null && info1.getGroupUuid().equals(info2.getGroupUuid())) { + // If both subscriptions are primary, show both. + if (!info1.isOpportunistic() && !info2.isOpportunistic()) return subscriptions; + + // If carrier required, always show signal bar of primary subscription. + // Otherwise, show whichever subscription is currently active for Internet. + boolean alwaysShowPrimary = CarrierConfigManager.getDefaultConfig() + .getBoolean(CarrierConfigManager + .KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN); + if (alwaysShowPrimary) { + subscriptions.remove(info1.isOpportunistic() ? info1 : info2); + } else { + subscriptions.remove(info1.getSubscriptionId() == mActiveMobileDataSubscription + ? info2 : info1); + } + + } + } + + return subscriptions; } @Override @@ -2647,6 +2689,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { pw.println(" " + mSubscriptionInfo.get(i)); } } + pw.println(" Current active data subId=" + mActiveMobileDataSubscription); pw.println(" Service states:"); for (int subId : mServiceStates.keySet()) { pw.println(" " + subId + "=" + mServiceStates.get(subId)); diff --git a/packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt b/packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt new file mode 100644 index 00000000000..3015710e8a9 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2020 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 + +import android.content.Context +import android.graphics.Path +import android.graphics.Rect +import android.graphics.RectF +import android.hardware.camera2.CameraManager +import android.util.PathParser +import java.util.concurrent.Executor + +import kotlin.math.roundToInt + +const val TAG = "CameraAvailabilityListener" + +/** + * Listens for usage of the Camera and controls the ScreenDecorations transition to show extra + * protection around a display cutout based on config_frontBuiltInDisplayCutoutProtection and + * config_enableDisplayCutoutProtection + */ +class CameraAvailabilityListener( + private val cameraManager: CameraManager, + private val cutoutProtectionPath: Path, + private val targetCameraId: String, + excludedPackages: String, + private val executor: Executor +) { + private var cutoutBounds = Rect() + private val excludedPackageIds: Set<String> + private val listeners = mutableListOf<CameraTransitionCallback>() + private val availabilityCallback: CameraManager.AvailabilityCallback = + object : CameraManager.AvailabilityCallback() { + override fun onCameraClosed(cameraId: String) { + if (targetCameraId == cameraId) { + notifyCameraInactive() + } + } + + override fun onCameraOpened(cameraId: String, packageId: String) { + if (targetCameraId == cameraId && !isExcluded(packageId)) { + notifyCameraActive() + } + } + } + + init { + val computed = RectF() + cutoutProtectionPath.computeBounds(computed, false /* unused */) + cutoutBounds.set( + computed.left.roundToInt(), + computed.top.roundToInt(), + computed.right.roundToInt(), + computed.bottom.roundToInt()) + excludedPackageIds = excludedPackages.split(",").toSet() + } + + /** + * Start listening for availability events, and maybe notify listeners + * + * @return true if we started listening + */ + fun startListening() { + registerCameraListener() + } + + fun stop() { + unregisterCameraListener() + } + + fun addTransitionCallback(callback: CameraTransitionCallback) { + listeners.add(callback) + } + + fun removeTransitionCallback(callback: CameraTransitionCallback) { + listeners.remove(callback) + } + + private fun isExcluded(packageId: String): Boolean { + return excludedPackageIds.contains(packageId) + } + + private fun registerCameraListener() { + cameraManager.registerAvailabilityCallback(executor, availabilityCallback) + } + + private fun unregisterCameraListener() { + cameraManager.unregisterAvailabilityCallback(availabilityCallback) + } + + private fun notifyCameraActive() { + listeners.forEach { it.onApplyCameraProtection(cutoutProtectionPath, cutoutBounds) } + } + + private fun notifyCameraInactive() { + listeners.forEach { it.onHideCameraProtection() } + } + + /** + * Callbacks to tell a listener that a relevant camera turned on and off. + */ + interface CameraTransitionCallback { + fun onApplyCameraProtection(protectionPath: Path, bounds: Rect) + fun onHideCameraProtection() + } + + companion object Factory { + fun build(context: Context, executor: Executor): CameraAvailabilityListener { + val manager = context + .getSystemService(Context.CAMERA_SERVICE) as CameraManager + val res = context.resources + val pathString = res.getString(R.string.config_frontBuiltInDisplayCutoutProtection) + val cameraId = res.getString(R.string.config_protectedCameraId) + val excluded = res.getString(R.string.config_cameraProtectionExcludedPackages) + + return CameraAvailabilityListener( + manager, pathFromString(pathString), cameraId, excluded, executor) + } + + private fun pathFromString(pathString: String): Path { + val spec = pathString.trim() + val p: Path + try { + p = PathParser.createPathFromPathData(spec) + } catch (e: Throwable) { + throw IllegalArgumentException("Invalid protection path", e) + } + + return p + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/ConfigurationChangedReceiver.java b/packages/SystemUI/src/com/android/systemui/ConfigurationChangedReceiver.java deleted file mode 100644 index 4fba6404f37..00000000000 --- a/packages/SystemUI/src/com/android/systemui/ConfigurationChangedReceiver.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package com.android.systemui; - -import android.content.res.Configuration; - -public interface ConfigurationChangedReceiver { - void onConfigurationChanged(Configuration newConfiguration); -} diff --git a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java index a94952c5bc1..6606c8235de 100644 --- a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java +++ b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java @@ -152,14 +152,14 @@ public class CornerHandleView extends View { // Attempt to get the bottom corner radius, otherwise fall back on the generic or top // values. If none are available, use the FALLBACK_RADIUS_DP. int radius = getResources().getDimensionPixelSize( - com.android.internal.R.dimen.rounded_corner_radius_bottom); + com.android.systemui.R.dimen.config_rounded_mask_size_bottom); if (radius == 0) { radius = getResources().getDimensionPixelSize( - com.android.internal.R.dimen.rounded_corner_radius); + com.android.systemui.R.dimen.config_rounded_mask_size); } if (radius == 0) { radius = getResources().getDimensionPixelSize( - com.android.internal.R.dimen.rounded_corner_radius_top); + com.android.systemui.R.dimen.config_rounded_mask_size_top); } if (radius == 0) { radius = (int) convertDpToPixel(FALLBACK_RADIUS_DP, mContext); diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index ec2111d502c..7abb5ece6ab 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -16,7 +16,6 @@ package com.android.systemui; import android.annotation.Nullable; import android.app.INotificationManager; -import android.content.res.Configuration; import android.hardware.SensorPrivacyManager; import android.hardware.display.NightDisplayListener; import android.os.Handler; @@ -524,15 +523,6 @@ public class Dependency { .forEach(o -> ((Dumpable) o).dump(fd, pw, args)); } - protected static void staticOnConfigurationChanged(Configuration newConfig) { - sDependency.onConfigurationChanged(newConfig); - } - - protected synchronized void onConfigurationChanged(Configuration newConfig) { - mDependencies.values().stream().filter(obj -> obj instanceof ConfigurationChangedReceiver) - .forEach(o -> ((ConfigurationChangedReceiver) o).onConfigurationChanged(newConfig)); - } - protected final <T> T getDependency(Class<T> cls) { return getDependencyInner(cls); } diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index c0c14fb0122..fa3405fab8d 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -18,12 +18,14 @@ package com.android.systemui; import android.app.ActivityManager; import android.content.Context; +import android.content.res.Configuration; import android.graphics.Rect; import android.os.HandlerThread; import android.os.Trace; import android.service.wallpaper.WallpaperService; import android.util.Log; import android.util.Size; +import android.view.DisplayInfo; import android.view.SurfaceHolder; import com.android.internal.annotations.VisibleForTesting; @@ -84,14 +86,19 @@ public class ImageWallpaper extends WallpaperService { private StatusBarStateController mController; private final Runnable mFinishRenderingTask = this::finishRendering; private final boolean mNeedTransition; + private boolean mShouldStopTransition; + private final boolean mIsHighEndGfx; + private final boolean mDisplayNeedsBlanking; + private final DisplayInfo mDisplayInfo = new DisplayInfo(); private final Object mMonitor = new Object(); private boolean mNeedRedraw; // This variable can only be accessed in synchronized block. private boolean mWaitingForRendering; GLEngine(Context context) { - mNeedTransition = ActivityManager.isHighEndGfx() - && !DozeParameters.getInstance(context).getDisplayNeedsBlanking(); + mIsHighEndGfx = ActivityManager.isHighEndGfx(); + mDisplayNeedsBlanking = DozeParameters.getInstance(context).getDisplayNeedsBlanking(); + mNeedTransition = mIsHighEndGfx && !mDisplayNeedsBlanking; // We will preserve EGL context when we are in lock screen or aod // to avoid janking in following transition, we need to release when back to home. @@ -99,12 +106,14 @@ public class ImageWallpaper extends WallpaperService { if (mController != null) { mController.addCallback(this /* StateListener */); } - mEglHelper = new EglHelper(); - mRenderer = new ImageWallpaperRenderer(context, this /* SurfaceProxy */); } @Override public void onCreate(SurfaceHolder surfaceHolder) { + mEglHelper = new EglHelper(); + // Deferred init renderer because we need to get wallpaper by display context. + mRenderer = new ImageWallpaperRenderer(getDisplayContext(), this /* SurfaceProxy */); + getDisplayContext().getDisplay().getDisplayInfo(mDisplayInfo); setFixedSizeAllowed(true); setOffsetNotificationsEnabled(true); updateSurfaceSize(); @@ -118,21 +127,44 @@ public class ImageWallpaper extends WallpaperService { holder.setFixedSize(width, height); } + /** + * Check if necessary to stop transition with current wallpaper on this device. <br/> + * This should only be invoked after {@link #onSurfaceCreated(SurfaceHolder)}} + * is invoked since it needs display context and surface frame size. + * + * @return true if need to stop transition + */ + @VisibleForTesting + boolean checkIfShouldStopTransition() { + int orientation = getDisplayContext().getResources().getConfiguration().orientation; + boolean portrait = orientation == Configuration.ORIENTATION_PORTRAIT; + Rect frame = getSurfaceHolder().getSurfaceFrame(); + int frameWidth = frame.width(); + int frameHeight = frame.height(); + int displayWidth = portrait ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight; + int displayHeight = portrait ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth; + return mNeedTransition + && (frameWidth < displayWidth || frameHeight < displayHeight); + } + @Override public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) { + if (mWorker == null) return; mWorker.getThreadHandler().post(() -> mRenderer.updateOffsets(xOffset, yOffset)); } @Override public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) { - if (!mNeedTransition) return; + if (mWorker == null || !mNeedTransition) return; + final long duration = mShouldStopTransition ? 0 : animationDuration; if (DEBUG) { Log.d(TAG, "onAmbientModeChanged: inAmbient=" + inAmbientMode - + ", duration=" + animationDuration); + + ", duration=" + duration + + ", mShouldStopTransition=" + mShouldStopTransition); } mWorker.getThreadHandler().post( - () -> mRenderer.updateAmbientMode(inAmbientMode, animationDuration)); + () -> mRenderer.updateAmbientMode(inAmbientMode, duration)); if (inAmbientMode && animationDuration == 0) { // This means that we are transiting from home to aod, to avoid // race condition between window visibility and transition, @@ -168,12 +200,13 @@ public class ImageWallpaper extends WallpaperService { mRenderer = null; mEglHelper.finish(); mEglHelper = null; - getSurfaceHolder().getSurface().hwuiDestroy(); }); } @Override public void onSurfaceCreated(SurfaceHolder holder) { + if (mWorker == null) return; + mShouldStopTransition = checkIfShouldStopTransition(); mWorker.getThreadHandler().post(() -> { mEglHelper.init(holder); mRenderer.onSurfaceCreated(); @@ -182,6 +215,7 @@ public class ImageWallpaper extends WallpaperService { @Override public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { + if (mWorker == null) return; mWorker.getThreadHandler().post(() -> { if (DEBUG) { Log.d(TAG, "onSurfaceChanged: w=" + width + ", h=" + height); @@ -194,6 +228,7 @@ public class ImageWallpaper extends WallpaperService { @Override public void onSurfaceRedrawNeeded(SurfaceHolder holder) { + if (mWorker == null) return; mWorker.getThreadHandler().post(() -> { if (DEBUG) { Log.d(TAG, "onSurfaceRedrawNeeded: mNeedRedraw=" + mNeedRedraw); @@ -222,7 +257,7 @@ public class ImageWallpaper extends WallpaperService { @Override public void onStatePostChange() { // When back to home, we try to release EGL, which is preserved in lock screen or aod. - if (mController.getState() == StatusBarState.SHADE) { + if (mWorker != null && mController.getState() == StatusBarState.SHADE) { mWorker.getThreadHandler().post(this::scheduleFinishRendering); } } @@ -327,10 +362,12 @@ public class ImageWallpaper extends WallpaperService { } private void cancelFinishRenderingTask() { + if (mWorker == null) return; mWorker.getThreadHandler().removeCallbacks(mFinishRenderingTask); } private void scheduleFinishRendering() { + if (mWorker == null) return; cancelFinishRenderingTask(); mWorker.getThreadHandler().postDelayed(mFinishRenderingTask, DELAY_FINISH_RENDERING); } @@ -359,15 +396,13 @@ public class ImageWallpaper extends WallpaperService { protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) { super.dump(prefix, fd, out, args); out.print(prefix); out.print("Engine="); out.println(this); - - boolean isHighEndGfx = ActivityManager.isHighEndGfx(); - out.print(prefix); out.print("isHighEndGfx="); out.println(isHighEndGfx); - - DozeParameters dozeParameters = DozeParameters.getInstance(getApplicationContext()); + out.print(prefix); out.print("isHighEndGfx="); out.println(mIsHighEndGfx); out.print(prefix); out.print("displayNeedsBlanking="); - out.println(dozeParameters != null ? dozeParameters.getDisplayNeedsBlanking() : "null"); - + out.println(mDisplayNeedsBlanking); + out.print(prefix); out.print("displayInfo="); out.print(mDisplayInfo); out.print(prefix); out.print("mNeedTransition="); out.println(mNeedTransition); + out.print(prefix); out.print("mShouldStopTransition="); + out.println(mShouldStopTransition); out.print(prefix); out.print("StatusBarState="); out.println(mController != null ? mController.getState() : "null"); diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index f38b4f259c8..8e5d5a83750 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -26,9 +26,12 @@ import static com.android.systemui.tuner.TunablePadding.FLAG_END; import static com.android.systemui.tuner.TunablePadding.FLAG_START; import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.annotation.Dimension; +import android.annotation.NonNull; import android.app.ActivityManager; import android.app.Fragment; import android.content.BroadcastReceiver; @@ -37,6 +40,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.ColorStateList; import android.content.res.Configuration; +import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; @@ -44,7 +48,9 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.Region; +import android.graphics.drawable.VectorDrawable; import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.HandlerThread; @@ -105,9 +111,11 @@ public class ScreenDecorations extends SystemUI implements Tunable, private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS = SystemProperties.getBoolean("debug.screenshot_rounded_corners", false); private static final boolean VERBOSE = false; + private static final boolean DEBUG_COLOR = DEBUG_SCREENSHOT_ROUNDED_CORNERS; private DisplayManager mDisplayManager; private DisplayManager.DisplayListener mDisplayListener; + private CameraAvailabilityListener mCameraListener; @VisibleForTesting protected int mRoundedDefault; @@ -129,6 +137,26 @@ public class ScreenDecorations extends SystemUI implements Tunable, private boolean mAssistHintBlocked = false; private boolean mIsReceivingNavBarColor = false; private boolean mInGesturalMode; + private boolean mIsRoundedCornerMultipleRadius; + + private CameraAvailabilityListener.CameraTransitionCallback mCameraTransitionCallback = + new CameraAvailabilityListener.CameraTransitionCallback() { + @Override + public void onApplyCameraProtection(@NonNull Path protectionPath, @NonNull Rect bounds) { + // Show the extra protection around the front facing camera if necessary + mCutoutTop.setProtection(protectionPath, bounds); + mCutoutTop.setShowProtection(true); + mCutoutBottom.setProtection(protectionPath, bounds); + mCutoutBottom.setShowProtection(true); + } + + @Override + public void onHideCameraProtection() { + // Go back to the regular anti-aliasing + mCutoutTop.setShowProtection(false); + mCutoutBottom.setShowProtection(false); + } + }; /** * Converts a set of {@link Rect}s into a {@link Region} @@ -323,9 +351,12 @@ public class ScreenDecorations extends SystemUI implements Tunable, private void startOnScreenDecorationsThread() { mRotation = RotationUtils.getExactRotation(mContext); mWindowManager = mContext.getSystemService(WindowManager.class); + mIsRoundedCornerMultipleRadius = mContext.getResources().getBoolean( + R.bool.config_roundedCornerMultipleRadius); updateRoundedCornerRadii(); if (hasRoundedCorners() || shouldDrawCutout() || shouldHostHandles()) { setupDecorations(); + setupCameraListener(); } mDisplayListener = new DisplayManager.DisplayListener() { @@ -441,6 +472,16 @@ public class ScreenDecorations extends SystemUI implements Tunable, new ValidatingPreDrawListener(mBottomOverlay)); } + private void setupCameraListener() { + Resources res = mContext.getResources(); + boolean enabled = res.getBoolean(R.bool.config_enableDisplayCutoutProtection); + if (enabled) { + mCameraListener = CameraAvailabilityListener.Factory.build(mContext, mHandler::post); + mCameraListener.addTransitionCallback(mCameraTransitionCallback); + mCameraListener.startListening(); + } + } + private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -457,6 +498,9 @@ public class ScreenDecorations extends SystemUI implements Tunable, private void updateColorInversion(int colorsInvertedValue) { int tint = colorsInvertedValue != 0 ? Color.WHITE : Color.BLACK; + if (DEBUG_COLOR) { + tint = Color.RED; + } ColorStateList tintList = ColorStateList.valueOf(tint); ((ImageView) mOverlay.findViewById(R.id.left)).setImageTintList(tintList); ((ImageView) mOverlay.findViewById(R.id.right)).setImageTintList(tintList); @@ -528,15 +572,22 @@ public class ScreenDecorations extends SystemUI implements Tunable, com.android.internal.R.dimen.rounded_corner_radius_top); final int newRoundedDefaultBottom = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.rounded_corner_radius_bottom); - final boolean roundedCornersChanged = mRoundedDefault != newRoundedDefault || mRoundedDefaultBottom != newRoundedDefaultBottom || mRoundedDefaultTop != newRoundedDefaultTop; if (roundedCornersChanged) { - mRoundedDefault = newRoundedDefault; - mRoundedDefaultTop = newRoundedDefaultTop; - mRoundedDefaultBottom = newRoundedDefaultBottom; + // If config_roundedCornerMultipleRadius set as true, ScreenDecorations respect the + // max(width, height) size of drawable/rounded.xml instead of rounded_corner_radius + if (mIsRoundedCornerMultipleRadius) { + final VectorDrawable d = (VectorDrawable) mContext.getDrawable(R.drawable.rounded); + mRoundedDefault = Math.max(d.getIntrinsicWidth(), d.getIntrinsicHeight()); + mRoundedDefaultTop = mRoundedDefaultBottom = mRoundedDefault; + } else { + mRoundedDefault = newRoundedDefault; + mRoundedDefaultTop = newRoundedDefaultTop; + mRoundedDefaultBottom = newRoundedDefaultBottom; + } onTuningChanged(SIZE, null); } } @@ -637,7 +688,8 @@ public class ScreenDecorations extends SystemUI implements Tunable, } private boolean hasRoundedCorners() { - return mRoundedDefault > 0 || mRoundedDefaultBottom > 0 || mRoundedDefaultTop > 0; + return mRoundedDefault > 0 || mRoundedDefaultBottom > 0 || mRoundedDefaultTop > 0 + || mIsRoundedCornerMultipleRadius; } private boolean shouldDrawCutout() { @@ -820,11 +872,22 @@ public class ScreenDecorations extends SystemUI implements Tunable, public static class DisplayCutoutView extends View implements DisplayManager.DisplayListener, RegionInterceptableView { + private static final float HIDDEN_CAMERA_PROTECTION_SCALE = 0.5f; + private final DisplayInfo mInfo = new DisplayInfo(); private final Paint mPaint = new Paint(); private final List<Rect> mBounds = new ArrayList(); private final Rect mBoundingRect = new Rect(); private final Path mBoundingPath = new Path(); + // Don't initialize these yet because they may never exist + private RectF mProtectionRect; + private RectF mProtectionRectOrig; + private Path mProtectionPath; + private Path mProtectionPathOrig; + private Rect mTotalBounds = new Rect(); + // Whether or not to show the cutout protection path + private boolean mShowProtection = false; + private final int[] mLocation = new int[2]; private final boolean mInitialStart; private final Runnable mVisibilityChangedListener; @@ -832,6 +895,8 @@ public class ScreenDecorations extends SystemUI implements Tunable, private int mColor = Color.BLACK; private boolean mStart; private int mRotation; + private float mCameraProtectionProgress = HIDDEN_CAMERA_PROTECTION_SCALE; + private ValueAnimator mCameraProtectionAnimator; public DisplayCutoutView(Context context, boolean start, Runnable visibilityChangedListener, ScreenDecorations decorations) { @@ -871,12 +936,19 @@ public class ScreenDecorations extends SystemUI implements Tunable, super.onDraw(canvas); getLocationOnScreen(mLocation); canvas.translate(-mLocation[0], -mLocation[1]); + if (!mBoundingPath.isEmpty()) { mPaint.setColor(mColor); mPaint.setStyle(Paint.Style.FILL); mPaint.setAntiAlias(true); canvas.drawPath(mBoundingPath, mPaint); } + if (mCameraProtectionProgress > HIDDEN_CAMERA_PROTECTION_SCALE + && !mProtectionRect.isEmpty()) { + canvas.scale(mCameraProtectionProgress, mCameraProtectionProgress, + mProtectionRect.centerX(), mProtectionRect.centerY()); + canvas.drawPath(mProtectionPath, mPaint); + } } @Override @@ -899,6 +971,53 @@ public class ScreenDecorations extends SystemUI implements Tunable, update(); } + void setProtection(Path protectionPath, Rect pathBounds) { + if (mProtectionPathOrig == null) { + mProtectionPathOrig = new Path(); + mProtectionPath = new Path(); + } + mProtectionPathOrig.set(protectionPath); + if (mProtectionRectOrig == null) { + mProtectionRectOrig = new RectF(); + mProtectionRect = new RectF(); + } + mProtectionRectOrig.set(pathBounds); + } + + void setShowProtection(boolean shouldShow) { + if (mShowProtection == shouldShow) { + return; + } + + mShowProtection = shouldShow; + updateBoundingPath(); + // Delay the relayout until the end of the animation when hiding the cutout, + // otherwise we'd clip it. + if (mShowProtection) { + requestLayout(); + } + if (mCameraProtectionAnimator != null) { + mCameraProtectionAnimator.cancel(); + } + mCameraProtectionAnimator = ValueAnimator.ofFloat(mCameraProtectionProgress, + mShowProtection ? 1.0f : HIDDEN_CAMERA_PROTECTION_SCALE).setDuration(750); + mCameraProtectionAnimator.setInterpolator(Interpolators.DECELERATE_QUINT); + mCameraProtectionAnimator.addUpdateListener(animation -> { + mCameraProtectionProgress = (float) animation.getAnimatedValue(); + invalidate(); + }); + mCameraProtectionAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mCameraProtectionAnimator = null; + if (!mShowProtection) { + requestLayout(); + } + } + }); + mCameraProtectionAnimator.start(); + } + private boolean isStart() { final boolean flipped = (mRotation == RotationUtils.ROTATION_SEASCAPE || mRotation == RotationUtils.ROTATION_UPSIDE_DOWN); @@ -945,6 +1064,12 @@ public class ScreenDecorations extends SystemUI implements Tunable, Matrix m = new Matrix(); transformPhysicalToLogicalCoordinates(mInfo.rotation, dw, dh, m); mBoundingPath.transform(m); + if (mProtectionPathOrig != null) { + // Reset the protection path so we don't aggregate rotations + mProtectionPath.set(mProtectionPathOrig); + mProtectionPath.transform(m); + m.mapRect(mProtectionRect, mProtectionRectOrig); + } } private static void transformPhysicalToLogicalCoordinates(@Surface.Rotation int rotation, @@ -1002,9 +1127,20 @@ public class ScreenDecorations extends SystemUI implements Tunable, super.onMeasure(widthMeasureSpec, heightMeasureSpec); return; } - setMeasuredDimension( - resolveSizeAndState(mBoundingRect.width(), widthMeasureSpec, 0), - resolveSizeAndState(mBoundingRect.height(), heightMeasureSpec, 0)); + + if (mShowProtection) { + // Make sure that our measured height encompases the protection + mTotalBounds.union(mBoundingRect); + mTotalBounds.union((int) mProtectionRect.left, (int) mProtectionRect.top, + (int) mProtectionRect.right, (int) mProtectionRect.bottom); + setMeasuredDimension( + resolveSizeAndState(mTotalBounds.width(), widthMeasureSpec, 0), + resolveSizeAndState(mTotalBounds.height(), heightMeasureSpec, 0)); + } else { + setMeasuredDimension( + resolveSizeAndState(mBoundingRect.width(), widthMeasureSpec, 0), + resolveSizeAndState(mBoundingRect.height(), heightMeasureSpec, 0)); + } } public static void boundsFromDirection(DisplayCutout displayCutout, int gravity, diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index 9252e576799..0d1bd6bae2b 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -286,7 +286,11 @@ public class SystemUIApplication extends Application implements SysUiServiceProv @Override public void onConfigurationChanged(Configuration newConfig) { if (mServicesStarted) { - Dependency.staticOnConfigurationChanged(newConfig); + SystemUIFactory + .getInstance() + .getRootComponent() + .getConfigurationController() + .onConfigurationChanged(newConfig); int len = mServices.length; for (int i = 0; i < len; i++) { if (mServices[i] != null) { diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java index f18c8b2c3da..a5b386eddd3 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java @@ -20,6 +20,7 @@ import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME import com.android.systemui.fragments.FragmentService; import com.android.systemui.statusbar.phone.StatusBar; +import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.util.InjectionInflationController; import com.android.systemui.util.leak.GarbageMonitor; @@ -40,12 +41,20 @@ import dagger.Component; SystemUIModule.class, SystemUIDefaultModule.class}) public interface SystemUIRootComponent { + /** * Main dependency providing module. */ @Singleton Dependency.DependencyInjector createDependency(); + + /** + * Creates a ConfigurationController. + */ + @Singleton + ConfigurationController getConfigurationController(); + /** * Injects the StatusBar. */ diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java index 1a2d062f1b8..d2c5f1e91ea 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java @@ -1,5 +1,9 @@ package com.android.systemui.assist; +import static android.view.Display.DEFAULT_DISPLAY; + +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; @@ -39,13 +43,12 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.settingslib.applications.InterestingConfigChanges; -import com.android.systemui.ConfigurationChangedReceiver; -import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SysUiServiceProvider; import com.android.systemui.assist.ui.DefaultUiController; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import javax.inject.Inject; @@ -55,7 +58,7 @@ import javax.inject.Singleton; * Class to manage everything related to assist in SystemUI. */ @Singleton -public class AssistManager implements ConfigurationChangedReceiver { +public class AssistManager { /** * Controls the UI for showing Assistant invocation progress. @@ -103,6 +106,9 @@ public class AssistManager implements ConfigurationChangedReceiver { public static final String INVOCATION_TYPE_KEY = "invocation_type"; protected static final String ACTION_KEY = "action"; protected static final String SHOW_ASSIST_HANDLES_ACTION = "show_assist_handles"; + protected static final String SET_ASSIST_GESTURE_CONSTRAINED_ACTION = + "set_assist_gesture_constrained"; + protected static final String CONSTRAINED_KEY = "should_constrain"; public static final int INVOCATION_TYPE_GESTURE = 1; public static final int INVOCATION_TYPE_ACTIVE_EDGE = 2; @@ -125,6 +131,7 @@ public class AssistManager implements ConfigurationChangedReceiver { private final PhoneStateMonitor mPhoneStateMonitor; private final AssistHandleBehaviorController mHandleController; private final UiController mUiController; + protected final OverviewProxyService mOverviewProxyService; private AssistOrbContainer mView; private final DeviceProvisionedController mDeviceProvisionedController; @@ -153,12 +160,41 @@ public class AssistManager implements ConfigurationChangedReceiver { } }; + private ConfigurationController.ConfigurationListener mConfigurationListener = + new ConfigurationController.ConfigurationListener() { + @Override + public void onConfigChanged(Configuration newConfig) { + if (!mInterestingConfigChanges.applyNewConfig(mContext.getResources())) { + return; + } + boolean visible = false; + if (mView != null) { + visible = mView.isShowing(); + mWindowManager.removeView(mView); + } + + mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate( + R.layout.assist_orb, null); + mView.setVisibility(View.GONE); + mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); + WindowManager.LayoutParams lp = getLayoutParams(); + mWindowManager.addView(mView, lp); + if (visible) { + mView.show(true /* show */, false /* animate */); + } + } + }; + @Inject public AssistManager( DeviceProvisionedController controller, Context context, AssistUtils assistUtils, - AssistHandleBehaviorController handleController) { + AssistHandleBehaviorController handleController, + ConfigurationController configurationController, + OverviewProxyService overviewProxyService) { mContext = context; mDeviceProvisionedController = controller; mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); @@ -167,17 +203,19 @@ public class AssistManager implements ConfigurationChangedReceiver { mPhoneStateMonitor = new PhoneStateMonitor(context); mHandleController = handleController; + configurationController.addCallback(mConfigurationListener); + registerVoiceInteractionSessionListener(); mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS); - onConfigurationChanged(context.getResources().getConfiguration()); + mConfigurationListener.onConfigChanged(context.getResources().getConfiguration()); mShouldEnableOrb = !ActivityManager.isLowRamDeviceStatic(); mUiController = new DefaultUiController(mContext); - OverviewProxyService overviewProxy = Dependency.get(OverviewProxyService.class); - overviewProxy.addCallback(new OverviewProxyService.OverviewProxyListener() { + mOverviewProxyService = overviewProxyService; + mOverviewProxyService.addCallback(new OverviewProxyService.OverviewProxyListener() { @Override public void onAssistantProgress(float progress) { // Progress goes from 0 to 1 to indicate how close the assist gesture is to @@ -214,36 +252,20 @@ public class AssistManager implements ConfigurationChangedReceiver { if (VERBOSE) { Log.v(TAG, "UI hints received"); } - if (SHOW_ASSIST_HANDLES_ACTION.equals(hints.getString(ACTION_KEY))) { + + String action = hints.getString(ACTION_KEY); + if (SHOW_ASSIST_HANDLES_ACTION.equals(action)) { requestAssistHandles(); + } else if (SET_ASSIST_GESTURE_CONSTRAINED_ACTION.equals(action)) { + mOverviewProxyService.setSystemUiStateFlag( + SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED, + hints.getBoolean(CONSTRAINED_KEY, false), + DEFAULT_DISPLAY); } } }); } - public void onConfigurationChanged(Configuration newConfiguration) { - if (!mInterestingConfigChanges.applyNewConfig(mContext.getResources())) { - return; - } - boolean visible = false; - if (mView != null) { - visible = mView.isShowing(); - mWindowManager.removeView(mView); - } - - mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate( - R.layout.assist_orb, null); - mView.setVisibility(View.GONE); - mView.setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); - WindowManager.LayoutParams lp = getLayoutParams(); - mWindowManager.addView(mView, lp); - if (visible) { - mView.show(true /* show */, false /* animate */); - } - } - protected boolean shouldShowOrb() { return false; } diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DisplayUtils.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DisplayUtils.java index 251229f42da..33e6ca49ddd 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/ui/DisplayUtils.java +++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DisplayUtils.java @@ -84,8 +84,8 @@ public class DisplayUtils { public static int getCornerRadiusBottom(Context context) { int radius = 0; - int resourceId = context.getResources().getIdentifier("rounded_corner_radius_bottom", - "dimen", "android"); + int resourceId = context.getResources().getIdentifier("config_rounded_mask_size_bottom", + "dimen", "com.android.systemui"); if (resourceId > 0) { radius = context.getResources().getDimensionPixelSize(resourceId); } @@ -103,8 +103,8 @@ public class DisplayUtils { public static int getCornerRadiusTop(Context context) { int radius = 0; - int resourceId = context.getResources().getIdentifier("rounded_corner_radius_top", - "dimen", "android"); + int resourceId = context.getResources().getIdentifier("config_rounded_mask_size_top", + "dimen", "com.android.systemui"); if (resourceId > 0) { radius = context.getResources().getDimensionPixelSize(resourceId); } @@ -118,8 +118,8 @@ public class DisplayUtils { private static int getCornerRadiusDefault(Context context) { int radius = 0; - int resourceId = context.getResources().getIdentifier("rounded_corner_radius", "dimen", - "android"); + int resourceId = context.getResources().getIdentifier("config_rounded_mask_size", + "dimen", "com.android.systemui"); if (resourceId > 0) { radius = context.getResources().getDimensionPixelSize(resourceId); } diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/PathSpecCornerPathRenderer.java b/packages/SystemUI/src/com/android/systemui/assist/ui/PathSpecCornerPathRenderer.java index 2bad7fc9583..523378e97c9 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/ui/PathSpecCornerPathRenderer.java +++ b/packages/SystemUI/src/com/android/systemui/assist/ui/PathSpecCornerPathRenderer.java @@ -45,8 +45,8 @@ public final class PathSpecCornerPathRenderer extends CornerPathRenderer { mWidth = DisplayUtils.getWidth(context); mHeight = DisplayUtils.getHeight(context); - mBottomCornerRadius = DisplayUtils.getCornerRadiusBottom(context); - mTopCornerRadius = DisplayUtils.getCornerRadiusTop(context); + mBottomCornerRadius = DisplayUtils.getCornerRadiusBottom(context); + mTopCornerRadius = DisplayUtils.getCornerRadiusTop(context); String pathData = context.getResources().getString(R.string.config_rounded_mask); Path path = PathParser.createPathFromPathData(pathData); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/PointerCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/PointerCountClassifier.java index 40e141fbf98..6f9e1206197 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/PointerCountClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/PointerCountClassifier.java @@ -16,6 +16,9 @@ package com.android.systemui.classifier.brightline; +import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN; +import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS; + import android.view.MotionEvent; /** @@ -27,6 +30,7 @@ import android.view.MotionEvent; class PointerCountClassifier extends FalsingClassifier { private static final int MAX_ALLOWED_POINTERS = 1; + private static final int MAX_ALLOWED_POINTERS_SWIPE_DOWN = 2; private int mMaxPointerCount; PointerCountClassifier(FalsingDataProvider dataProvider) { @@ -48,6 +52,10 @@ class PointerCountClassifier extends FalsingClassifier { @Override public boolean isFalseTouch() { + int interactionType = getInteractionType(); + if (interactionType == QUICK_SETTINGS || interactionType == NOTIFICATION_DRAG_DOWN) { + return mMaxPointerCount > MAX_ALLOWED_POINTERS_SWIPE_DOWN; + } return mMaxPointerCount > MAX_ALLOWED_POINTERS; } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java index c27e633f2a9..1145501f4c5 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java @@ -155,15 +155,8 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi } int scrimOpacity = -1; - if (mPaused || mScreenOff) { - // If AOD is paused, force the screen black until the - // sensor reports a new brightness. This ensures that when the screen comes on - // again, it will only show after the brightness sensor has stabilized, - // avoiding a potential flicker. - scrimOpacity = 255; - } else if (!mScreenOff && mLightSensor == null) { - // No light sensor but previous state turned the screen black. Make the scrim - // transparent and below views visible. + if (mLightSensor == null) { + // No light sensor, scrims are always transparent. scrimOpacity = 0; } else if (brightnessReady) { // Only unblank scrim once brightness is ready. diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index 026a62528c8..e6cbab26c65 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -43,11 +43,11 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; -import com.android.systemui.R; import com.android.systemui.plugins.SensorManagerPlugin; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.util.AlarmTimeout; import com.android.systemui.util.AsyncSensorManager; +import com.android.systemui.util.ProximitySensor; import com.android.systemui.util.wakelock.WakeLock; import java.io.PrintWriter; @@ -288,6 +288,7 @@ public class DozeSensors { final AlarmTimeout mCooldownTimer; final AlwaysOnDisplayPolicy mPolicy; final Sensor mSensor; + private final float mSensorThreshold; final boolean mUsingBrightnessSensor; public ProxSensor(AlwaysOnDisplayPolicy policy) { @@ -297,11 +298,14 @@ public class DozeSensors { // The default prox sensor can be noisy, so let's use a prox gated brightness sensor // if available. - Sensor sensor = DozeSensors.findSensorWithType(mSensorManager, - mContext.getString(R.string.doze_brightness_sensor_type)); + Sensor sensor = ProximitySensor.findCustomProxSensor(mContext, mSensorManager); mUsingBrightnessSensor = sensor != null; - if (sensor == null) { + if (mUsingBrightnessSensor) { + mSensorThreshold = ProximitySensor.getBrightnessSensorThreshold( + mContext.getResources()); + } else { sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); + mSensorThreshold = sensor == null ? 0 : sensor.getMaximumRange(); } mSensor = sensor; } @@ -343,11 +347,9 @@ public class DozeSensors { if (DEBUG) Log.d(TAG, "onSensorChanged " + event); if (mUsingBrightnessSensor) { - // The custom brightness sensor is gated by the proximity sensor and will return 0 - // whenever prox is covered. - mCurrentlyFar = event.values[0] > 0; + mCurrentlyFar = event.values[0] > mSensorThreshold; } else { - mCurrentlyFar = event.values[0] >= event.sensor.getMaximumRange(); + mCurrentlyFar = event.values[0] >= mSensorThreshold; } mProxCallback.accept(mCurrentlyFar); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 6199a0deb31..c7a133dc530 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -41,10 +41,10 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.Preconditions; import com.android.systemui.Dependency; -import com.android.systemui.R; import com.android.systemui.dock.DockManager; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.util.Assert; +import com.android.systemui.util.ProximitySensor; import com.android.systemui.util.wakelock.WakeLock; import java.io.PrintWriter; @@ -431,15 +431,18 @@ public class DozeTriggers implements DozeMachine.Part { private boolean mFinished; private float mMaxRange; private boolean mUsingBrightnessSensor; + private float mSensorThreshold; protected abstract void onProximityResult(int result); public void check() { Preconditions.checkState(!mFinished && !mRegistered); - Sensor sensor = DozeSensors.findSensorWithType(mSensorManager, - mContext.getString(R.string.doze_brightness_sensor_type)); + Sensor sensor = ProximitySensor.findCustomProxSensor(mContext, mSensorManager); mUsingBrightnessSensor = sensor != null; - if (sensor == null) { + if (mUsingBrightnessSensor) { + mSensorThreshold = ProximitySensor.getBrightnessSensorThreshold( + mContext.getResources()); + } else { sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); } if (sensor == null) { @@ -473,7 +476,7 @@ public class DozeTriggers implements DozeMachine.Part { if (mUsingBrightnessSensor) { // The custom brightness sensor is gated by the proximity sensor and will // return 0 whenever prox is covered. - isNear = event.values[0] == 0; + isNear = event.values[0] <= mSensorThreshold; } else { isNear = event.values[0] < mMaxRange; } diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java index b4cc571be06..bbf49e3d13d 100644 --- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java +++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java @@ -20,11 +20,11 @@ import android.os.Handler; import android.util.ArrayMap; import android.view.View; -import com.android.systemui.ConfigurationChangedReceiver; import com.android.systemui.Dumpable; import com.android.systemui.SystemUIRootComponent; import com.android.systemui.qs.QSFragment; import com.android.systemui.statusbar.phone.NavigationBarFragment; +import com.android.systemui.statusbar.policy.ConfigurationController; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -41,7 +41,7 @@ import dagger.Subcomponent; * Also dispatches the configuration changes to all current FragmentHostStates. */ @Singleton -public class FragmentService implements ConfigurationChangedReceiver, Dumpable { +public class FragmentService implements Dumpable { private static final String TAG = "FragmentService"; @@ -50,10 +50,22 @@ public class FragmentService implements ConfigurationChangedReceiver, Dumpable { private final Handler mHandler = new Handler(); private final FragmentCreator mFragmentCreator; + private ConfigurationController.ConfigurationListener mConfigurationListener = + new ConfigurationController.ConfigurationListener() { + @Override + public void onConfigChanged(Configuration newConfig) { + for (FragmentHostState state : mHosts.values()) { + state.sendConfigurationChange(newConfig); + } + } + }; + @Inject - public FragmentService(SystemUIRootComponent rootComponent) { + public FragmentService(SystemUIRootComponent rootComponent, + ConfigurationController configurationController) { mFragmentCreator = rootComponent.createFragmentCreator(); initInjectionMap(); + configurationController.addCallback(mConfigurationListener); } ArrayMap<String, Method> getInjectionMap() { @@ -97,13 +109,6 @@ public class FragmentService implements ConfigurationChangedReceiver, Dumpable { } @Override - public void onConfigurationChanged(Configuration newConfig) { - for (FragmentHostState state : mHosts.values()) { - state.sendConfigurationChange(newConfig); - } - } - - @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("Dumping fragments:"); for (FragmentHostState state : mHosts.values()) { diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java index be6f7bfe258..5f6588f9fca 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java @@ -31,7 +31,6 @@ import android.util.Log; import android.util.MathUtils; import android.util.Size; import android.view.DisplayInfo; -import android.view.WindowManager; import com.android.systemui.R; @@ -70,8 +69,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer, } DisplayInfo displayInfo = new DisplayInfo(); - WindowManager wm = context.getSystemService(WindowManager.class); - wm.getDefaultDisplay().getDisplayInfo(displayInfo); + context.getDisplay().getDisplayInfo(displayInfo); // We only do transition in portrait currently, b/137962047. int orientation = context.getResources().getConfiguration().orientation; @@ -115,12 +113,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer, mBitmap = mWallpaperManager.getBitmap(); mWallpaperManager.forgetLoadedWallpaper(); if (mBitmap != null) { - float scale = (float) mScissor.height() / mBitmap.getHeight(); - int surfaceHeight = Math.max(mScissor.height(), mBitmap.getHeight()); - int surfaceWidth = scale > 1f - ? Math.round(mBitmap.getWidth() * scale) - : mBitmap.getWidth(); - mSurfaceSize.set(0, 0, surfaceWidth, surfaceHeight); + mSurfaceSize.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight()); } } if (DEBUG) { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java index e408745699e..50c50065915 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java @@ -319,7 +319,8 @@ public class KeyguardSliceProvider extends SliceProvider implements mZenModeController = new ZenModeControllerImpl(getContext(), mHandler); mZenModeController.addCallback(this); mDatePattern = getContext().getString(R.string.system_ui_aod_date_pattern); - mPendingIntent = PendingIntent.getActivity(getContext(), 0, new Intent(), 0); + mPendingIntent = PendingIntent.getActivity(getContext(), 0, + new Intent(getContext(), KeyguardSliceProvider.class), 0); mMediaWakeLock = new SettableWakeLock(WakeLock.createPartial(getContext(), "media"), "media"); KeyguardSliceProvider.sInstance = this; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java index a9dadecf88a..b9084667653 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java @@ -25,9 +25,12 @@ import android.content.Intent; import android.content.res.Configuration; import android.graphics.drawable.Animatable; import android.util.AttributeSet; +import android.util.Pair; import android.util.SparseArray; +import android.view.DisplayCutout; import android.view.View; import android.view.ViewGroup; +import android.view.WindowInsets; import android.view.accessibility.AccessibilityEvent; import android.widget.ImageView; import android.widget.LinearLayout; @@ -42,6 +45,7 @@ import com.android.systemui.SysUiServiceProvider; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.statusbar.phone.PhoneStatusBarView; public class QSDetail extends LinearLayout { @@ -150,6 +154,25 @@ public class QSDetail extends LinearLayout { } } + @Override + public WindowInsets onApplyWindowInsets(WindowInsets insets) { + DisplayCutout cutout = insets.getDisplayCutout(); + Pair<Integer, Integer> padding = PhoneStatusBarView.cornerCutoutMargins( + cutout, getDisplay()); + if (padding == null) { + mQsDetailHeader.setPaddingRelative( + getResources().getDimensionPixelSize(R.dimen.qs_detail_header_padding), + getPaddingTop(), + getResources().getDimensionPixelSize(R.dimen.qs_detail_header_padding), + getPaddingBottom() + ); + } else { + mQsDetailHeader.setPadding(padding.first, getPaddingTop(), + padding.second, getPaddingBottom()); + } + return super.onApplyWindowInsets(insets); + } + private void updateDetailText() { mDetailDoneButton.setText(R.string.quick_settings_done); mDetailSettingsButton.setText(R.string.quick_settings_more_settings); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index b09adf90e67..d4a1f1877b2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -546,10 +546,15 @@ public class QuickStatusBarHeader extends RelativeLayout implements cutout, getDisplay()); if (padding == null) { mSystemIconsView.setPaddingRelative( - getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), 0, - getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end), 0); + getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), + getResources().getDimensionPixelSize(R.dimen.status_bar_padding_top), + getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end), + 0); } else { - mSystemIconsView.setPadding(padding.first, 0, padding.second, 0); + mSystemIconsView.setPadding( + padding.first, + getResources().getDimensionPixelSize(R.dimen.status_bar_padding_top), + padding.second, 0); } LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSpace.getLayoutParams(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java index 70062492c16..7a8f497041c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java @@ -103,7 +103,9 @@ public class TileQueryHelper { final ArrayList<QSTile> tilesToAdd = new ArrayList<>(); for (String spec : possibleTiles) { - // Only add current and stock tiles that can be created from QSFactoryImpl + // Only add current and stock tiles that can be created from QSFactoryImpl. + // Do not include CustomTile. Those will be created by `addPackageTiles`. + if (spec.startsWith(CustomTile.PREFIX)) continue; final QSTile tile = host.createTile(spec); if (tile == null) { continue; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 0644a0ff737..3bab5ac9056 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -166,7 +166,8 @@ public class KeyguardIndicationController implements StateListener, mStatusBarStateController = statusBarStateController; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mDockManager = dockManager; - mDockManager.addAlignmentStateListener(this::handleAlignStateChanged); + mDockManager.addAlignmentStateListener( + alignState -> mHandler.post(() -> handleAlignStateChanged(alignState))); // lock icon is not used on all form factors. if (mLockIcon != null) { mLockIcon.setOnLongClickListener(this::handleLockLongClick); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java index d1b3c3cb12d..2a5ccdb0c0a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java @@ -134,7 +134,7 @@ public class OperatorNameView extends TextView implements DemoMode, DarkReceiver private void updateText() { CharSequence displayText = null; - List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false); + List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(false); final int N = subs.size(); for (int i = 0; i < N; i++) { int subId = subs.get(i).getSubscriptionId(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java index 04f1c3248a6..1524b079908 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar; +import static java.lang.Float.isNaN; + import android.annotation.NonNull; import android.content.Context; import android.graphics.Canvas; @@ -179,6 +181,9 @@ public class ScrimView extends View { * @param alpha Gradient alpha from 0 to 1. */ public void setViewAlpha(float alpha) { + if (isNaN(alpha)) { + throw new IllegalArgumentException("alpha cannot be NaN"); + } if (alpha != mViewAlpha) { mViewAlpha = alpha; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java index 247c31fc80a..240d567b78c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java @@ -137,6 +137,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { entry.updateIcons(mContext, sbn); entry.reset(); updateNotification(entry, pmUser, sbn, entry.getRow()); + entry.getRow().setOnDismissRunnable(onDismissRunnable); } else { entry.createIcons(mContext, sbn); new RowInflaterTask().inflate(mContext, parent, entry, 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 8079fbb8115..389033f6657 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 @@ -3780,9 +3780,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); - final int action = ev.getAction(); + final int action = ev.getActionMasked(); + if (ev.findPointerIndex(mActivePointerId) == -1 && action != MotionEvent.ACTION_DOWN) { + // Incomplete gesture, possibly due to window swap mid-gesture. Ignore until a new + // one starts. + Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent " + + MotionEvent.actionToString(ev.getActionMasked())); + return true; + } - switch (action & MotionEvent.ACTION_MASK) { + switch (action) { case MotionEvent.ACTION_DOWN: { if (getChildCount() == 0 || !isInContentBounds(ev)) { return false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java index 5912cd7b643..1042b61ab4f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java @@ -47,7 +47,7 @@ public class AutoHideController implements CommandQueue.Callbacks { private final NotificationRemoteInputManager mRemoteInputManager; private final CommandQueue mCommandQueue; private StatusBar mStatusBar; - private NavigationBarFragment mNavigationBar; + private AutoHideElement mNavigationBar; @VisibleForTesting int mDisplayId; @@ -85,11 +85,11 @@ public class AutoHideController implements CommandQueue.Callbacks { } } - void setStatusBar(StatusBar statusBar) { + public void setStatusBar(StatusBar statusBar) { mStatusBar = statusBar; } - void setNavigationBar(NavigationBarFragment navigationBar) { + public void setNavigationBar(AutoHideElement navigationBar) { mNavigationBar = navigationBar; } @@ -158,7 +158,8 @@ public class AutoHideController implements CommandQueue.Callbacks { mAutoHideSuspended = (mSystemUiVisibility & getTransientMask()) != 0; } - void touchAutoHide() { + /** Schedule auto hide if necessary otherwise cancel any pending runnables. */ + public void touchAutoHide() { // update transient bar auto hide if ((hasStatusBar() && mStatusBar.getStatusBarMode() == MODE_SEMI_TRANSPARENT) || hasNavigationBar() && mNavigationBar.isSemiTransparent()) { @@ -172,13 +173,14 @@ public class AutoHideController implements CommandQueue.Callbacks { if (hasStatusBar()) { return () -> mStatusBar.checkBarModes(); } else if (hasNavigationBar()) { - return () -> mNavigationBar.checkNavBarModes(); + return () -> mNavigationBar.synchronizeState(); } else { return null; } } - private void cancelAutoHide() { + /** Remove any scheduled auto hide runnables. */ + public void cancelAutoHide() { mAutoHideSuspended = false; mHandler.removeCallbacks(mAutoHide); } @@ -202,7 +204,8 @@ public class AutoHideController implements CommandQueue.Callbacks { } } - private void userAutoHide() { + /** Schedule auto hide. */ + public void userAutoHide() { cancelAutoHide(); mHandler.postDelayed(mAutoHide, 350); // longer than app gesture -> flag clear } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideElement.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideElement.java new file mode 100644 index 00000000000..8849519ba47 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideElement.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 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.statusbar.phone; + +/** An interface for a UI element controlled by the {@link AutoHideController}. */ +public interface AutoHideElement { + /** + * Synchronizes the UI State of this {@link AutoHideElement}. This method is posted as a + * {@link Runnable} on the main thread. + */ + void synchronizeState(); + + /** + * Returns {@code true} if the {@link AutoHideElement} is in a + * {@link BarTransitions#MODE_SEMI_TRANSPARENT} state. + */ + boolean isSemiTransparent(); +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt index 424acfd9916..54ef623e95a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt @@ -18,14 +18,11 @@ import android.content.Context import android.content.pm.ActivityInfo import android.content.res.Configuration import android.os.LocaleList - -import com.android.systemui.ConfigurationChangedReceiver import com.android.systemui.statusbar.policy.ConfigurationController import java.util.ArrayList -class ConfigurationControllerImpl(context: Context) - : ConfigurationController, ConfigurationChangedReceiver { +class ConfigurationControllerImpl(context: Context) : ConfigurationController { private val listeners: MutableList<ConfigurationController.ConfigurationListener> = ArrayList() private val lastConfig = Configuration() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java index dd200da56d2..b26cb25981f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java @@ -111,8 +111,9 @@ public class HeadsUpTouchHelper implements Gefingerpoken { mInitialTouchY = y; int startHeight = (int) (mPickedChild.getActualHeight() + mPickedChild.getTranslationY()); - mPanel.setPanelScrimMinFraction((float) startHeight - / mPanel.getMaxPanelHeight()); + float maxPanelHeight = mPanel.getMaxPanelHeight(); + mPanel.setPanelScrimMinFraction(maxPanelHeight > 0f + ? (float) startHeight / maxPanelHeight : 0f); mPanel.startExpandMotion(x, y, true /* startTracking */, startHeight); mPanel.startExpandingFromPeek(); // This call needs to be after the expansion start otherwise we will get a diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 80d36a1a4e5..c3244a4431d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -641,9 +641,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL if (previewBefore != null) { mPreviewContainer.removeView(previewBefore); } - if (mLeftIsVoiceAssist) { - mLeftPreview = mPreviewInflater.inflatePreviewFromService( - mAssistManager.getVoiceInteractorComponentName()); + ComponentName voiceInteractorComponentName = + mAssistManager.getVoiceInteractorComponentName(); + if (mLeftIsVoiceAssist && voiceInteractorComponentName != null) { + mLeftPreview = mPreviewInflater.inflatePreviewFromService(voiceInteractorComponentName); } else { mLeftPreview = mPreviewInflater.inflatePreview(mLeftButton.getIntent()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java index 1253c9a0a85..b51088f66af 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java @@ -120,7 +120,7 @@ import javax.inject.Inject; * on clicks and view states of the nav bar. */ public class NavigationBarFragment extends LifecycleFragment implements Callbacks, - NavigationModeController.ModeChangedListener { + NavigationModeController.ModeChangedListener, AutoHideElement { public static final String TAG = "NavigationBar"; private static final boolean DEBUG = false; @@ -968,10 +968,18 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback mAutoHideController.setNavigationBar(this); } + // AutoHideElement + @Override public boolean isSemiTransparent() { return mNavigationBarMode == MODE_SEMI_TRANSPARENT; } + // AutoHideElement + @Override + public void synchronizeState() { + checkNavBarModes(); + } + private void checkBarModes() { // We only have status bar on default display now. if (mIsOnDefaultDisplay) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 3f1a4e6f880..d2a092cfcd4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -2133,7 +2133,7 @@ public class NotificationPanelView extends PanelView implements } else { maxHeight = calculatePanelHeightShade(); } - maxHeight = Math.max(maxHeight, min); + maxHeight = Math.max(min, maxHeight); return maxHeight; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java index 063d00b806c..21a96675943 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.phone; +import static java.lang.Float.isNaN; + import android.content.Context; import android.os.Bundle; import android.os.Parcelable; @@ -160,6 +162,9 @@ public abstract class PanelBar extends FrameLayout { * fraction as the panel also might be expanded if the fraction is 0 */ public void panelExpansionChanged(float frac, boolean expanded) { + if (isNaN(frac)) { + throw new IllegalArgumentException("frac cannot be NaN"); + } boolean fullyClosed = true; boolean fullyOpened = false; if (SPEW) LOG("panelExpansionChanged: start state=%d", mState); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java index 08d92864d35..afd8644e223 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java @@ -29,24 +29,22 @@ public final class PhoneStatusBarTransitions extends BarTransitions { private static final float ICON_ALPHA_WHEN_LIGHTS_OUT_BATTERY_CLOCK = 0.5f; private static final float ICON_ALPHA_WHEN_LIGHTS_OUT_NON_BATTERY_CLOCK = 0; - private final PhoneStatusBarView mView; private final float mIconAlphaWhenOpaque; - private View mLeftSide, mStatusIcons, mNetworkTraffic, mBattery, mClock; + private View mLeftSide, mStatusIcons, mNetworkTraffic, mBattery; private Animator mCurrentAnimation; - public PhoneStatusBarTransitions(PhoneStatusBarView view) { - super(view, R.drawable.status_background); - mView = view; - final Resources res = mView.getContext().getResources(); + /** + * @param backgroundView view to apply the background drawable + */ + public PhoneStatusBarTransitions(PhoneStatusBarView statusBarView, View backgroundView) { + super(backgroundView, R.drawable.status_background); + final Resources res = statusBarView.getContext().getResources(); mIconAlphaWhenOpaque = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1); - } - - public void init() { - mLeftSide = mView.findViewById(R.id.status_bar_left_side); - mStatusIcons = mView.findViewById(R.id.statusIcons); - mNetworkTraffic = mView.findViewById(R.id.network_traffic); - mBattery = mView.findViewById(R.id.battery); + mLeftSide = statusBarView.findViewById(R.id.status_bar_left_side); + mStatusIcons = statusBarView.findViewById(R.id.statusIcons); + mNetworkTraffic = statusBarView.findViewById(R.id.network_traffic); + mBattery = statusBarView.findViewById(R.id.battery); applyModeBackground(-1, getMode(), false /*animate*/); applyMode(getMode(), false /*animate*/); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 8efd952e67c..3d705da65f2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -21,6 +21,8 @@ import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFromDirection; import static com.android.systemui.SysUiServiceProvider.getComponent; +import static java.lang.Float.isNaN; + import android.annotation.Nullable; import android.content.Context; import android.content.res.Configuration; @@ -46,6 +48,7 @@ import com.android.systemui.R; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.util.leak.RotationUtils; import java.util.Objects; @@ -59,7 +62,6 @@ public class PhoneStatusBarView extends PanelBar { StatusBar mBar; boolean mIsFullyOpenedPanel = false; - private final PhoneStatusBarTransitions mBarTransitions; private ScrimController mScrimController; private float mMinFraction; private Runnable mHideExpandedRunnable = new Runnable() { @@ -72,6 +74,7 @@ public class PhoneStatusBarView extends PanelBar { }; private DarkReceiver mBattery; private int mLastOrientation; + private int mRotationOrientation; @Nullable private View mCenterIconSpace; @Nullable @@ -82,19 +85,15 @@ public class PhoneStatusBarView extends PanelBar { * Draw this many pixels into the left/right side of the cutout to optimally use the space */ private int mCutoutSideNudge = 0; + private int mStatusBarHeight; private boolean mHeadsUpVisible; public PhoneStatusBarView(Context context, AttributeSet attrs) { super(context, attrs); - mBarTransitions = new PhoneStatusBarTransitions(this); mCommandQueue = getComponent(context, CommandQueue.class); } - public BarTransitions getBarTransitions() { - return mBarTransitions; - } - public void setBar(StatusBar bar) { mBar = bar; } @@ -105,7 +104,6 @@ public class PhoneStatusBarView extends PanelBar { @Override public void onFinishInflate() { - mBarTransitions.init(); mBattery = findViewById(R.id.battery); mCutoutSpace = findViewById(R.id.cutout_space_view); mCenterIconSpace = findViewById(R.id.centered_icon_area); @@ -133,6 +131,7 @@ public class PhoneStatusBarView extends PanelBar { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); + updateResources(); // May trigger cutout space layout-ing if (updateOrientationAndCutout(newConfig.orientation)) { @@ -162,6 +161,7 @@ public class PhoneStatusBarView extends PanelBar { changed = true; mLastOrientation = newOrientation; } + mRotationOrientation = RotationUtils.getExactRotation(mContext); } if (!Objects.equals(getRootWindowInsets().getDisplayCutout(), mDisplayCutout)) { @@ -267,6 +267,9 @@ public class PhoneStatusBarView extends PanelBar { @Override public void panelScrimMinFractionChanged(float minFraction) { + if (isNaN(minFraction)) { + throw new IllegalArgumentException("minFraction cannot be NaN"); + } if (mMinFraction != minFraction) { mMinFraction = minFraction; updateScrimFraction(); @@ -295,15 +298,34 @@ public class PhoneStatusBarView extends PanelBar { mCutoutSideNudge = getResources().getDimensionPixelSize( R.dimen.display_cutout_margin_consumption); + boolean isRtl = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; + + int statusBarPaddingTop = getResources().getDimensionPixelSize( + R.dimen.status_bar_padding_top); + int statusBarPaddingStart = getResources().getDimensionPixelSize( + R.dimen.status_bar_padding_start); + int statusBarPaddingEnd = getResources().getDimensionPixelSize( + R.dimen.status_bar_padding_end); + ViewGroup.LayoutParams layoutParams = getLayoutParams(); - layoutParams.height = getResources().getDimensionPixelSize( - R.dimen.status_bar_height); + mStatusBarHeight = getResources().getDimensionPixelSize(R.dimen.status_bar_height); + layoutParams.height = mStatusBarHeight; + + View sbContents = findViewById(R.id.status_bar_contents); + sbContents.setPadding( + isRtl ? statusBarPaddingEnd : statusBarPaddingStart, + statusBarPaddingTop, + isRtl ? statusBarPaddingStart : statusBarPaddingEnd, + 0); + + findViewById(R.id.notification_lights_out).setPadding(0, statusBarPaddingStart, 0, 0); + setLayoutParams(layoutParams); } private void updateLayoutForCutout() { Pair<Integer, Integer> cornerCutoutMargins = cornerCutoutMargins(mDisplayCutout, - getDisplay()); + getDisplay(), mRotationOrientation, mStatusBarHeight); updateCutoutLocation(cornerCutoutMargins); updateSafeInsets(cornerCutoutMargins); } @@ -339,15 +361,13 @@ public class PhoneStatusBarView extends PanelBar { // or letterboxing from the right or left sides. FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); - if (mDisplayCutout == null || mDisplayCutout.isEmpty() - || mLastOrientation != ORIENTATION_PORTRAIT || cornerCutoutMargins == null) { + if (mDisplayCutout == null || mDisplayCutout.isEmpty() || cornerCutoutMargins == null) { lp.leftMargin = 0; lp.rightMargin = 0; return; } - - lp.leftMargin = Math.max(lp.leftMargin, cornerCutoutMargins.first); - lp.rightMargin = Math.max(lp.rightMargin, cornerCutoutMargins.second); + lp.leftMargin = cornerCutoutMargins.first; + lp.rightMargin = cornerCutoutMargins.second; // If we're already inset enough (e.g. on the status bar side), we can have 0 margin WindowInsets insets = getRootWindowInsets(); @@ -361,23 +381,43 @@ public class PhoneStatusBarView extends PanelBar { } } + /** + * Returns a Pair of integers where + * - Pair.first is the left margin inset + * - Pair.second is the right margin inset + */ public static Pair<Integer, Integer> cornerCutoutMargins(DisplayCutout cutout, Display display) { + return cornerCutoutMargins(cutout, display, RotationUtils.ROTATION_NONE, -1); + } + + private static Pair<Integer, Integer> cornerCutoutMargins(DisplayCutout cutout, + Display display, int rotationOrientation, int statusBarHeight) { if (cutout == null) { return null; } Point size = new Point(); display.getRealSize(size); + if (rotationOrientation != RotationUtils.ROTATION_NONE) { + return new Pair<>(cutout.getSafeInsetLeft(), cutout.getSafeInsetRight()); + } + Rect bounds = new Rect(); boundsFromDirection(cutout, Gravity.TOP, bounds); + if (statusBarHeight >= 0 && bounds.top > statusBarHeight) { + return null; + } + if (bounds.left <= 0) { return new Pair<>(bounds.right, 0); } + if (bounds.right >= size.x) { return new Pair<>(0, size.x - bounds.left); } + return null; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 9019e9a3f44..08ba50857fa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.phone; +import static java.lang.Float.isNaN; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; @@ -261,6 +263,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo mCurrentBehindTint = state.getBehindTint(); mCurrentInFrontAlpha = state.getFrontAlpha(); mCurrentBehindAlpha = state.getBehindAlpha(); + if (isNaN(mCurrentBehindAlpha) || isNaN(mCurrentInFrontAlpha)) { + throw new IllegalStateException("Scrim opacity is NaN for state: " + state + ", front: " + + mCurrentInFrontAlpha + ", back: " + mCurrentBehindAlpha); + } applyExpansionToAlpha(); // Scrim might acquire focus when user is navigating with a D-pad or a keyboard. @@ -390,6 +396,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo * @param fraction From 0 to 1 where 0 means collapsed and 1 expanded. */ public void setPanelExpansion(float fraction) { + if (isNaN(fraction)) { + throw new IllegalArgumentException("Fraction should not be NaN"); + } if (mExpansionFraction != fraction) { mExpansionFraction = fraction; @@ -464,6 +473,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo mCurrentBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(), mState.getBehindTint(), interpolatedFract); } + if (isNaN(mCurrentBehindAlpha) || isNaN(mCurrentInFrontAlpha)) { + throw new IllegalStateException("Scrim opacity is NaN for state: " + mState + + ", front: " + mCurrentInFrontAlpha + ", back: " + mCurrentBehindAlpha); + } } /** @@ -523,6 +536,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo float newBehindAlpha = mState.getBehindAlpha(); if (mCurrentBehindAlpha != newBehindAlpha) { mCurrentBehindAlpha = newBehindAlpha; + if (isNaN(mCurrentBehindAlpha)) { + throw new IllegalStateException("Scrim opacity is NaN for state: " + mState + + ", back: " + mCurrentBehindAlpha); + } updateScrims(); } } @@ -903,7 +920,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo pw.print(" alpha="); pw.print(mCurrentBehindAlpha); pw.print(" tint=0x"); pw.println(Integer.toHexString(mScrimBehind.getTint())); - pw.print(" mTracking="); pw.println(mTracking); + pw.print(" mTracking="); pw.println(mTracking); + + pw.print(" mExpansionFraction="); pw.println(mExpansionFraction); } public void setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode) { @@ -950,6 +969,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo // in this case, back-scrim needs to be re-evaluated if (mState == ScrimState.AOD || mState == ScrimState.PULSING) { float newBehindAlpha = mState.getBehindAlpha(); + if (isNaN(newBehindAlpha)) { + throw new IllegalStateException("Scrim opacity is NaN for state: " + mState + + ", back: " + mCurrentBehindAlpha); + } if (mCurrentBehindAlpha != newBehindAlpha) { mCurrentBehindAlpha = newBehindAlpha; updateScrims(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 32bcd2b3c83..22e6b11f55c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -2392,6 +2392,14 @@ public class StatusBar extends SystemUI implements DemoMode, navbarColorManagedByIme); } + protected final int getSystemUiVisibility() { + return mSystemUiVisibility; + } + + protected final int getDisplayId() { + return mDisplayId; + } + @Override public void showWirelessChargingAnimation(int batteryLevel) { if (mDozing || mKeyguardManager.isKeyguardLocked()) { @@ -2425,7 +2433,7 @@ public class StatusBar extends SystemUI implements DemoMode, } protected BarTransitions getStatusBarTransitions() { - return mStatusBarView.getBarTransitions(); + return mStatusBarWindow.getBarTransitions(); } protected @TransitionMode int computeBarMode(int oldVis, int newVis) { @@ -2456,8 +2464,10 @@ public class StatusBar extends SystemUI implements DemoMode, void checkBarModes() { if (mDemoMode) return; - if (mStatusBarView != null) checkBarMode(mStatusBarMode, mStatusBarWindowState, - getStatusBarTransitions()); + if (mStatusBarView != null && getStatusBarTransitions() != null) { + checkBarMode(mStatusBarMode, mStatusBarWindowState, + getStatusBarTransitions()); + } mNavigationBarController.checkNavBarModes(mDisplayId); mNoAnimationOnNextBarModeChange = false; } @@ -2475,8 +2485,8 @@ public class StatusBar extends SystemUI implements DemoMode, } private void finishBarAnimations() { - if (mStatusBarView != null) { - mStatusBarView.getBarTransitions().finishAnimations(); + if (mStatusBarWindow != null && mStatusBarWindow.getBarTransitions() != null) { + mStatusBarWindow.getBarTransitions().finishAnimations(); } mNavigationBarController.finishBarAnimations(mDisplayId); } @@ -2554,8 +2564,8 @@ public class StatusBar extends SystemUI implements DemoMode, Settings.Global.ZEN_MODE_OFF))); pw.print(" mWallpaperSupported= "); pw.println(mWallpaperSupported); - if (mStatusBarView != null) { - dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions()); + if (mStatusBarWindow != null) { + dumpBarTransitions(pw, "mStatusBarWindow", mStatusBarWindow.getBarTransitions()); } pw.println(" StatusBarWindowView: "); if (mStatusBarWindow != null) { @@ -3214,8 +3224,8 @@ public class StatusBar extends SystemUI implements DemoMode, -1; if (barMode != -1) { boolean animate = true; - if (mStatusBarView != null) { - mStatusBarView.getBarTransitions().transitionTo(barMode, animate); + if (mStatusBarWindow != null && mStatusBarWindow.getBarTransitions() != null) { + mStatusBarWindow.getBarTransitions().transitionTo(barMode, animate); } mNavigationBarController.transitionTo(mDisplayId, barMode, animate); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java index 53cfcdae426..b460ddcb480 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -66,8 +66,6 @@ import com.android.systemui.R; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.DragDownHelper; -import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.phone.ScrimController.ScrimVisibility; import com.android.systemui.tuner.TunerService; @@ -97,6 +95,7 @@ public class StatusBarWindowView extends FrameLayout { private View mBrightnessMirror; private LockIcon mLockIcon; private PhoneStatusBarView mStatusBarView; + private PhoneStatusBarTransitions mBarTransitions; private int mRightInset = 0; private int mLeftInset = 0; @@ -205,7 +204,8 @@ public class StatusBarWindowView extends FrameLayout { int targetLeft = Math.max(insets.left, leftCutout); int targetRight = Math.max(insets.right, rightCutout); - // Super-special right inset handling, because scrims and backdrop need to ignore it. + // Super-special right inset handling, because scrims, backdrop and status bar + // container need to ignore it. if (targetRight != mRightInset || targetLeft != mLeftInset) { mRightInset = targetRight; mLeftInset = targetLeft; @@ -306,6 +306,12 @@ public class StatusBarWindowView extends FrameLayout { public void setStatusBarView(PhoneStatusBarView statusBarView) { mStatusBarView = statusBarView; + mBarTransitions = new PhoneStatusBarTransitions(statusBarView, + findViewById(R.id.status_bar_container)); + } + + public PhoneStatusBarTransitions getBarTransitions() { + return mBarTransitions; } public void setService(StatusBar service) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java index 351579a9571..7d562fbdfe6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java @@ -277,7 +277,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa boolean otherProfileConnected = false; for (CachedBluetoothDevice device : getDevices()) { - for (LocalBluetoothProfile profile : device.getProfiles()) { + for (LocalBluetoothProfile profile : device.getProfileListCopy()) { int profileId = profile.getProfileId(); boolean isConnected = device.isConnectedProfile(profile); if (profileId == BluetoothProfile.HEADSET diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java index b89f27d5b5d..972e03998f3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java @@ -34,6 +34,7 @@ import android.text.format.DateFormat; import android.text.style.CharacterStyle; import android.text.style.RelativeSizeSpan; import android.util.AttributeSet; +import android.util.Log; import android.view.Display; import android.view.View; import android.widget.TextView; @@ -66,6 +67,7 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C DarkReceiver, ConfigurationListener { public static final String CLOCK_SECONDS = "clock_seconds"; + private static final String TAG = "StatusBarClock"; private static final String CLOCK_STYLE = "lineagesystem:status_bar_am_pm"; private static final String CLOCK_SUPER_PARCELABLE = "clock_super_parcelable"; @@ -228,9 +230,18 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); + Handler handler = getHandler(); + if (handler == null) { + Log.e(TAG, + "Received intent, but handler is null - still attached to window? Window " + + "token: " + + getWindowToken()); + return; + } + if (action.equals(Intent.ACTION_TIMEZONE_CHANGED)) { String tz = intent.getStringExtra("time-zone"); - getHandler().post(() -> { + handler.post(() -> { mCalendar = Calendar.getInstance(TimeZone.getTimeZone(tz)); if (mClockFormat != null) { mClockFormat.setTimeZone(mCalendar.getTimeZone()); @@ -238,14 +249,14 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C }); } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { final Locale newLocale = getResources().getConfiguration().locale; - getHandler().post(() -> { + handler.post(() -> { if (!newLocale.equals(mLocale)) { mLocale = newLocale; mClockFormatString = ""; // force refresh } }); } - getHandler().post(() -> updateClock()); + handler.post(() -> updateClock()); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java index 0e5c8c105df..0a6cf7be736 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java @@ -24,7 +24,11 @@ import com.android.systemui.statusbar.policy.ConfigurationController.Configurati */ public interface ConfigurationController extends CallbackController<ConfigurationListener> { - public void notifyThemeChanged(); + /** Alert controller of a change in the configuration. */ + void onConfigurationChanged(Configuration newConfiguration); + + /** Alert controller of a change in between light and dark themes. */ + void notifyThemeChanged(); interface ConfigurationListener { default void onConfigChanged(Configuration newConfig) {} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java index 0d6178b1176..f2c0434a1a9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java @@ -97,7 +97,7 @@ public class EmergencyCryptkeeperText extends TextView { boolean allSimsMissing = true; CharSequence displayText = null; - List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false); + List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(false); final int N = subs.size(); for (int i = 0; i < N; i++) { int subId = subs.get(i).getSubscriptionId(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 7a09455017d..2ad5a8aa7fe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -61,7 +61,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyIntents; import com.android.settingslib.net.DataUsageController; -import com.android.systemui.ConfigurationChangedReceiver; import com.android.systemui.DemoMode; import com.android.systemui.Dumpable; import com.android.systemui.R; @@ -87,8 +86,7 @@ import javax.inject.Singleton; /** Platform implementation of the network controller. **/ @Singleton public class NetworkControllerImpl extends BroadcastReceiver - implements NetworkController, DemoMode, DataUsageController.NetworkNameProvider, - ConfigurationChangedReceiver, Dumpable { + implements NetworkController, DemoMode, DataUsageController.NetworkNameProvider, Dumpable { // debug static final String TAG = "NetworkController"; static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @@ -166,6 +164,14 @@ public class NetworkControllerImpl extends BroadcastReceiver private boolean mUserSetup; private boolean mSimDetected; + private ConfigurationController.ConfigurationListener mConfigurationListener = + new ConfigurationController.ConfigurationListener() { + @Override + public void onConfigChanged(Configuration newConfig) { + mConfig = Config.readConfig(mContext); + mReceiverHandler.post(() -> handleConfigurationChanged()); + } + }; /** * Construct this controller object and register for updates. */ @@ -553,16 +559,6 @@ public class NetworkControllerImpl extends BroadcastReceiver } } - public void onConfigurationChanged(Configuration newConfig) { - mConfig = Config.readConfig(mContext); - mReceiverHandler.post(new Runnable() { - @Override - public void run() { - handleConfigurationChanged(); - } - }); - } - @VisibleForTesting void handleConfigurationChanged() { updateMobileControllers(); diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java index a686cd77d94..88e49f6c307 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java @@ -15,7 +15,7 @@ */ package com.android.systemui.tuner; -import static com.android.systemui.Dependency.BG_HANDLER_NAME; +import static com.android.systemui.Dependency.MAIN_HANDLER_NAME; import android.app.ActivityManager; import android.content.ContentResolver; @@ -96,7 +96,7 @@ public class TunerServiceImpl extends TunerService { /** */ @Inject - public TunerServiceImpl(Context context, @Named(BG_HANDLER_NAME) Handler bgHandler, + public TunerServiceImpl(Context context, @Named(MAIN_HANDLER_NAME) Handler mainHandler, LeakDetector leakDetector) { mContext = context; mContentResolver = mContext.getContentResolver(); @@ -105,7 +105,7 @@ public class TunerServiceImpl extends TunerService { for (UserInfo user : UserManager.get(mContext).getUsers()) { mCurrentUser = user.getUserHandle().getIdentifier(); if (getValue(TUNER_VERSION, 0) != CURRENT_TUNER_VERSION) { - upgradeTuner(getValue(TUNER_VERSION, 0), CURRENT_TUNER_VERSION, bgHandler); + upgradeTuner(getValue(TUNER_VERSION, 0), CURRENT_TUNER_VERSION, mainHandler); } } @@ -126,7 +126,7 @@ public class TunerServiceImpl extends TunerService { mUserTracker.stopTracking(); } - private void upgradeTuner(int oldVersion, int newVersion, Handler bgHandler) { + private void upgradeTuner(int oldVersion, int newVersion, Handler mainHandler) { if (oldVersion < 1) { String blacklistStr = getValue(StatusBarIconController.ICON_BLACKLIST); if (blacklistStr != null) { @@ -148,7 +148,7 @@ public class TunerServiceImpl extends TunerService { if (oldVersion < 4) { // Delay this so that we can wait for everything to be registered first. final int user = mCurrentUser; - bgHandler.postDelayed( + mainHandler.postDelayed( () -> clearAllFromUser(user), 5000); } setValue(TUNER_VERSION, newVersion); diff --git a/packages/SystemUI/src/com/android/systemui/util/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/ProximitySensor.java index a905eba1f0e..4cd38febc5d 100644 --- a/packages/SystemUI/src/com/android/systemui/util/ProximitySensor.java +++ b/packages/SystemUI/src/com/android/systemui/util/ProximitySensor.java @@ -17,6 +17,7 @@ package com.android.systemui.util; import android.content.Context; +import android.content.res.Resources; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; @@ -40,7 +41,7 @@ public class ProximitySensor { private final Sensor mSensor; private final AsyncSensorManager mSensorManager; private final boolean mUsingBrightnessSensor; - private final float mMaxRange; + private final float mThreshold; private SensorEventListener mSensorEventListener = new SensorEventListener() { @Override @@ -59,7 +60,7 @@ public class ProximitySensor { @Inject public ProximitySensor(Context context, AsyncSensorManager sensorManager) { mSensorManager = sensorManager; - Sensor sensor = findBrightnessSensor(context, sensorManager); + Sensor sensor = findCustomProxSensor(context, sensorManager); if (sensor == null) { mUsingBrightnessSensor = false; @@ -69,9 +70,13 @@ public class ProximitySensor { } mSensor = sensor; if (mSensor != null) { - mMaxRange = mSensor.getMaximumRange(); + if (mUsingBrightnessSensor) { + mThreshold = getBrightnessSensorThreshold(context.getResources()); + } else { + mThreshold = mSensor.getMaximumRange(); + } } else { - mMaxRange = 0; + mThreshold = 0; } } @@ -79,8 +84,18 @@ public class ProximitySensor { mTag = tag; } - private Sensor findBrightnessSensor(Context context, SensorManager sensorManager) { - String sensorType = context.getString(R.string.doze_brightness_sensor_type); + /** + * Returns a brightness sensor that can be used for proximity purposes. + * + * @deprecated This method exists for legacy purposes. Use the containing class directly. + */ + @Deprecated + public static Sensor findCustomProxSensor(Context context, SensorManager sensorManager) { + String sensorType = context.getString(R.string.proximity_sensor_type); + if (sensorType.isEmpty()) { + return null; + } + List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL); Sensor sensor = null; for (Sensor s : sensorList) { @@ -94,6 +109,16 @@ public class ProximitySensor { } /** + * Returns a threshold value that can be used along with {@link #findCustomProxSensor} + * + * @deprecated This method exists for legacy purposes. Use the containing class directly. + */ + @Deprecated + public static float getBrightnessSensorThreshold(Resources resources) { + return resources.getFloat(R.dimen.proximity_sensor_threshold); + } + + /** * Returns {@code false} if a Proximity sensor is not available. */ public boolean getSensorAvailable() { @@ -141,11 +166,11 @@ public class ProximitySensor { } private void onSensorEvent(SensorEvent event) { - boolean near = event.values[0] < mMaxRange; if (mUsingBrightnessSensor) { - near = event.values[0] == 0; + mNear = event.values[0] <= mThreshold; + } else { + mNear = event.values[0] < mThreshold; } - mNear = near; mListeners.forEach(proximitySensorListener -> proximitySensorListener.onProximitySensorEvent( new ProximityEvent(mNear, event.timestamp))); |