diff options
Diffstat (limited to 'packages/SystemUI/src')
96 files changed, 1416 insertions, 846 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index 6ae2b4523c2a..fd92e9e72d2e 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -1,5 +1,7 @@ package com.android.keyguard; +import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -24,8 +26,8 @@ import android.widget.TextClock; import androidx.annotation.VisibleForTesting; import com.android.internal.colorextraction.ColorExtractor; +import com.android.internal.colorextraction.ColorExtractor.OnColorsChangedListener; import com.android.keyguard.clock.ClockManager; -import com.android.systemui.Dependency; import com.android.systemui.Interpolators; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.plugins.ClockPlugin; @@ -37,37 +39,65 @@ import java.io.PrintWriter; import java.util.Arrays; import java.util.TimeZone; +import javax.inject.Inject; +import javax.inject.Named; + /** * Switch to show plugin clock when plugin is connected, otherwise it will show default clock. */ public class KeyguardClockSwitch extends RelativeLayout { + /** + * Controller used to track StatusBar state to know when to show the big_clock_container. + */ + private final StatusBarStateController mStatusBarStateController; + + /** + * Color extractor used to apply colors from wallpaper to custom clock faces. + */ + private final SysuiColorExtractor mSysuiColorExtractor; + + /** + * Manager used to know when to show a custom clock face. + */ + private final ClockManager mClockManager; + + /** + * Layout transition that scales the default clock face. + */ private final Transition mTransition; + /** * Optional/alternative clock injected via plugin. */ private ClockPlugin mClockPlugin; + /** * Default clock. */ private TextClock mClockView; + /** * Frame for default and custom clock. */ private FrameLayout mSmallClockFrame; + /** * Container for big custom clock. */ private ViewGroup mBigClockContainer; + /** * Status area (date and other stuff) shown below the clock. Plugin can decide whether or not to * show it below the alternate clock. */ private View mKeyguardStatusArea; + /** * Maintain state so that a newly connected plugin can be initialized. */ private float mDarkAmount; + /** * If the Keyguard Slice has a header (big center-aligned text.) */ @@ -96,22 +126,20 @@ public class KeyguardClockSwitch extends RelativeLayout { * * The color palette changes when the wallpaper is changed. */ - private SysuiColorExtractor.OnColorsChangedListener mColorsListener = (extractor, which) -> { + private final OnColorsChangedListener mColorsListener = (extractor, which) -> { if ((which & WallpaperManager.FLAG_LOCK) != 0) { - if (extractor instanceof SysuiColorExtractor) { - updateColors((SysuiColorExtractor) extractor); - } else { - updateColors(Dependency.get(SysuiColorExtractor.class)); - } + updateColors(); } }; - public KeyguardClockSwitch(Context context) { - this(context, null); - } - - public KeyguardClockSwitch(Context context, AttributeSet attrs) { + @Inject + public KeyguardClockSwitch(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs, + StatusBarStateController statusBarStateController, SysuiColorExtractor colorExtractor, + ClockManager clockManager) { super(context, attrs); + mStatusBarStateController = statusBarStateController; + mSysuiColorExtractor = colorExtractor; + mClockManager = clockManager; mTransition = new ClockBoundsTransition(); } @@ -133,22 +161,18 @@ public class KeyguardClockSwitch extends RelativeLayout { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - Dependency.get(ClockManager.class).addOnClockChangedListener(mClockChangedListener); - StatusBarStateController stateController = Dependency.get(StatusBarStateController.class); - stateController.addCallback(mStateListener); - mStateListener.onStateChanged(stateController.getState()); - SysuiColorExtractor colorExtractor = Dependency.get(SysuiColorExtractor.class); - colorExtractor.addOnColorsChangedListener(mColorsListener); - updateColors(colorExtractor); + mClockManager.addOnClockChangedListener(mClockChangedListener); + mStatusBarStateController.addCallback(mStateListener); + mSysuiColorExtractor.addOnColorsChangedListener(mColorsListener); + updateColors(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - Dependency.get(ClockManager.class).removeOnClockChangedListener(mClockChangedListener); - Dependency.get(StatusBarStateController.class).removeCallback(mStateListener); - Dependency.get(SysuiColorExtractor.class) - .removeOnColorsChangedListener(mColorsListener); + mClockManager.removeOnClockChangedListener(mClockChangedListener); + mStatusBarStateController.removeCallback(mStateListener); + mSysuiColorExtractor.removeOnColorsChangedListener(mColorsListener); setClockPlugin(null); } @@ -290,9 +314,9 @@ public class KeyguardClockSwitch extends RelativeLayout { } } - private void updateColors(SysuiColorExtractor colorExtractor) { - ColorExtractor.GradientColors colors = colorExtractor.getColors(WallpaperManager.FLAG_LOCK, - true); + private void updateColors() { + ColorExtractor.GradientColors colors = mSysuiColorExtractor.getColors( + WallpaperManager.FLAG_LOCK, true); mSupportsDarkText = colors.supportsDarkText(); mColorPalette = colors.getColorPalette(); if (mClockPlugin != null) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java index 9dd97170437d..ae8bc528ab6a 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java @@ -28,9 +28,12 @@ import android.util.Log; import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; +import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; +import com.android.systemui.util.InjectionInflationController; + // TODO(multi-display): Support multiple external displays public class KeyguardDisplayManager { protected static final String TAG = "KeyguardDisplayManager"; @@ -38,6 +41,7 @@ public class KeyguardDisplayManager { private final MediaRouter mMediaRouter; private final DisplayManager mDisplayService; + private final InjectionInflationController mInjectableInflater; private final Context mContext; private boolean mShowing; @@ -75,8 +79,10 @@ public class KeyguardDisplayManager { } }; - public KeyguardDisplayManager(Context context) { + public KeyguardDisplayManager(Context context, + InjectionInflationController injectableInflater) { mContext = context; + mInjectableInflater = injectableInflater; mMediaRouter = mContext.getSystemService(MediaRouter.class); mDisplayService = mContext.getSystemService(DisplayManager.class); mDisplayService.registerDisplayListener(mDisplayListener, null /* handler */); @@ -110,7 +116,7 @@ public class KeyguardDisplayManager { final int displayId = display.getDisplayId(); Presentation presentation = mPresentations.get(displayId); if (presentation == null) { - presentation = new KeyguardPresentation(mContext, display); + presentation = new KeyguardPresentation(mContext, display, mInjectableInflater); presentation.setOnDismissListener(dialog -> { if (null != mPresentations.get(displayId)) { mPresentations.remove(displayId); @@ -201,6 +207,7 @@ public class KeyguardDisplayManager { private final static class KeyguardPresentation extends Presentation { private static final int VIDEO_SAFE_REGION = 80; // Percentage of display width & height private static final int MOVE_CLOCK_TIMEOUT = 10000; // 10s + private final InjectionInflationController mInjectableInflater; private View mClock; private int mUsableWidth; private int mUsableHeight; @@ -217,8 +224,10 @@ public class KeyguardDisplayManager { } }; - KeyguardPresentation(Context context, Display display) { + KeyguardPresentation(Context context, Display display, + InjectionInflationController injectionInflater) { super(context, display, R.style.keyguard_presentation_theme); + mInjectableInflater = injectionInflater; getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); setCancelable(false); } @@ -239,7 +248,9 @@ public class KeyguardDisplayManager { mMarginLeft = (100 - VIDEO_SAFE_REGION) * p.x / 200; mMarginTop = (100 - VIDEO_SAFE_REGION) * p.y / 200; - setContentView(R.layout.keyguard_presentation); + LayoutInflater inflater = mInjectableInflater.injectable( + LayoutInflater.from(getContext())); + setContentView(inflater.inflate(R.layout.keyguard_presentation, null)); mClock = findViewById(R.id.clock); // Avoid screen burn in diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java index c0ec405e7dc1..fb4fe814601f 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java @@ -99,13 +99,7 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView { esimButton.setVisibility(isEsimLocked ? View.VISIBLE : View.GONE); } - private void showDefaultMessage() { - if (mRemainingAttempts >= 0) { - mSecurityMessageDisplay.setMessage(getPinPasswordErrorMessage( - mRemainingAttempts, true)); - return; - } - + private void setLockedSimMessage() { boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId); int count = TelephonyManager.getDefault().getSimCount(); Resources rez = getResources(); @@ -122,13 +116,20 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView { color = info.getIconTint(); } } - if (isEsimLocked) { msg = rez.getString(R.string.kg_sim_lock_esim_instructions, msg); } mSecurityMessageDisplay.setMessage(msg); mSimImageView.setImageTintList(ColorStateList.valueOf(color)); + } + + private void showDefaultMessage() { + setLockedSimMessage(); + if (mRemainingAttempts >= 0) { + return; + } + // Sending empty PIN here to query the number of remaining PIN attempts new CheckSimPin("", mSubId) { @@ -137,8 +138,7 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView { " attemptsRemaining=" + attemptsRemaining); if (attemptsRemaining >= 0) { mRemainingAttempts = attemptsRemaining; - mSecurityMessageDisplay.setMessage( - getPinPasswordErrorMessage(attemptsRemaining, true)); + setLockedSimMessage(); } } }.start(); diff --git a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java index 870ac8778f76..147def392594 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java @@ -15,15 +15,19 @@ */ package com.android.keyguard.clock; +import android.app.WallpaperManager; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Color; import android.graphics.Paint.Style; import android.view.LayoutInflater; import android.view.View; import android.widget.TextClock; +import com.android.internal.colorextraction.ColorExtractor; import com.android.keyguard.R; +import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.plugins.ClockPlugin; import java.util.TimeZone; @@ -44,6 +48,16 @@ public class BubbleClockController implements ClockPlugin { private final LayoutInflater mLayoutInflater; /** + * Extracts accent color from wallpaper. + */ + private final SysuiColorExtractor mColorExtractor; + + /** + * Renders preview from clock view. + */ + private final ViewPreviewer mRenderer = new ViewPreviewer(); + + /** * Custom clock shown on AOD screen and behind stack scroller on lock. */ private View mView; @@ -64,11 +78,15 @@ public class BubbleClockController implements ClockPlugin { /** * Create a BubbleClockController instance. * - * @param layoutInflater Inflater used to inflate custom clock views. + * @param res Resources contains title and thumbnail. + * @param inflater Inflater used to inflate custom clock views. + * @param colorExtractor Extracts accent color from wallpaper. */ - public BubbleClockController(Resources res, LayoutInflater inflater) { + public BubbleClockController(Resources res, LayoutInflater inflater, + SysuiColorExtractor colorExtractor) { mResources = res; mLayoutInflater = inflater; + mColorExtractor = colorExtractor; } private void createViews() { @@ -99,6 +117,23 @@ public class BubbleClockController implements ClockPlugin { } @Override + public Bitmap getPreview(int width, int height) { + + // Use the big clock view for the preview + View view = getBigClockView(); + + // Initialize state of plugin before generating preview. + setDarkAmount(1f); + setTextColor(Color.WHITE); + ColorExtractor.GradientColors colors = mColorExtractor.getColors( + WallpaperManager.FLAG_LOCK, true); + setColorPalette(colors.supportsDarkText(), colors.getColorPalette()); + onTimeTick(); + + return mRenderer.createPreview(view, width, height); + } + + @Override public View getView() { if (mLockClockContainer == null) { createViews(); @@ -141,6 +176,8 @@ public class BubbleClockController implements ClockPlugin { @Override public void onTimeTick() { mAnalogClock.onTimeChanged(); + mDigitalClock.refresh(); + mLockClock.refresh(); } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java index 294c725af481..d0fff749972d 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java @@ -16,29 +16,20 @@ package com.android.keyguard.clock; import android.annotation.Nullable; -import android.app.WallpaperManager; import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; import android.database.ContentObserver; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.Canvas; -import android.graphics.Color; import android.os.Handler; import android.os.Looper; import android.provider.Settings; import android.util.ArrayMap; import android.util.DisplayMetrics; -import android.util.Log; import android.view.LayoutInflater; -import android.view.View; -import android.view.View.MeasureSpec; -import android.view.ViewGroup; import androidx.annotation.VisibleForTesting; -import com.android.internal.colorextraction.ColorExtractor; +import com.android.systemui.SysUiServiceProvider; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManager.DockEventListener; @@ -50,8 +41,6 @@ import com.android.systemui.util.InjectionInflationController; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.FutureTask; import javax.inject.Inject; import javax.inject.Singleton; @@ -72,6 +61,7 @@ public final class ClockManager { private final Map<String, ClockPlugin> mClocks = new ArrayMap<>(); @Nullable private ClockPlugin mCurrentClock; + private final Context mContext; private final ContentResolver mContentResolver; private final SettingsWrapper mSettingsWrapper; private final Handler mMainHandler = new Handler(Looper.getMainLooper()); @@ -117,7 +107,7 @@ public final class ClockManager { reload(); } }; - @Nullable private final DockManager mDockManager; + @Nullable private DockManager mDockManager; /** * When docked, the DOCKED_CLOCK_FACE setting will be checked for the custom clock face * to show. @@ -126,35 +116,31 @@ public final class ClockManager { private final List<ClockChangedListener> mListeners = new ArrayList<>(); - private final SysuiColorExtractor mColorExtractor; private final int mWidth; private final int mHeight; @Inject public ClockManager(Context context, InjectionInflationController injectionInflater, - PluginManager pluginManager, @Nullable DockManager dockManager, - SysuiColorExtractor colorExtractor) { - this(context, injectionInflater, pluginManager, dockManager, colorExtractor, + PluginManager pluginManager, SysuiColorExtractor colorExtractor) { + this(context, injectionInflater, pluginManager, colorExtractor, context.getContentResolver(), new SettingsWrapper(context.getContentResolver())); } ClockManager(Context context, InjectionInflationController injectionInflater, - PluginManager pluginManager, @Nullable DockManager dockManager, - SysuiColorExtractor colorExtractor, ContentResolver contentResolver, - SettingsWrapper settingsWrapper) { + PluginManager pluginManager, SysuiColorExtractor colorExtractor, + ContentResolver contentResolver, SettingsWrapper settingsWrapper) { + mContext = context; mPluginManager = pluginManager; - mDockManager = dockManager; - mColorExtractor = colorExtractor; mContentResolver = contentResolver; mSettingsWrapper = settingsWrapper; Resources res = context.getResources(); LayoutInflater layoutInflater = injectionInflater.injectable(LayoutInflater.from(context)); - addClockPlugin(new DefaultClockController(res, layoutInflater)); - addClockPlugin(new BubbleClockController(res, layoutInflater)); - addClockPlugin(new StretchAnalogClockController(res, layoutInflater)); - addClockPlugin(new TypeClockController(res, layoutInflater)); + addClockPlugin(new DefaultClockController(res, layoutInflater, colorExtractor)); + addClockPlugin(new BubbleClockController(res, layoutInflater, colorExtractor)); + addClockPlugin(new StretchAnalogClockController(res, layoutInflater, colorExtractor)); + addClockPlugin(new TypeClockController(res, layoutInflater, colorExtractor)); // Store the size of the display for generation of clock preview. DisplayMetrics dm = res.getDisplayMetrics(); @@ -217,7 +203,7 @@ public final class ClockManager { .setTitle(plugin.getTitle()) .setId(id) .setThumbnail(() -> plugin.getThumbnail()) - .setPreview(() -> getClockPreview(id)) + .setPreview(() -> plugin.getPreview(mWidth, mHeight)) .build()); } @@ -232,81 +218,6 @@ public final class ClockManager { } } - /** - * Generate a realistic preview of a clock face. - * @param clockId ID of clock to use for preview, should be obtained from {@link getClockInfos}. - * Returns null if clockId is not found. - */ - @Nullable - private Bitmap getClockPreview(String clockId) { - FutureTask<Bitmap> task = new FutureTask<>(new Callable<Bitmap>() { - @Override - public Bitmap call() { - Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888); - ClockPlugin plugin = mClocks.get(clockId); - if (plugin == null) { - return null; - } - - // Use the big clock view for the preview - View clockView = plugin.getBigClockView(); - if (clockView == null) { - return null; - } - - // Initialize state of plugin before generating preview. - plugin.setDarkAmount(1f); - plugin.setTextColor(Color.WHITE); - - ColorExtractor.GradientColors colors = mColorExtractor.getColors( - WallpaperManager.FLAG_LOCK, true); - plugin.setColorPalette(colors.supportsDarkText(), colors.getColorPalette()); - plugin.onTimeTick(); - - // Draw clock view hierarchy to canvas. - Canvas canvas = new Canvas(bitmap); - canvas.drawColor(Color.BLACK); - dispatchVisibilityAggregated(clockView, true); - clockView.measure(MeasureSpec.makeMeasureSpec(mWidth, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(mHeight, MeasureSpec.EXACTLY)); - clockView.layout(0, 0, mWidth, mHeight); - clockView.draw(canvas); - return bitmap; - } - }); - - if (Looper.myLooper() == Looper.getMainLooper()) { - task.run(); - } else { - mMainHandler.post(task); - } - - try { - return task.get(); - } catch (Exception e) { - Log.e(TAG, "Error completing task", e); - return null; - } - } - - private void dispatchVisibilityAggregated(View view, boolean isVisible) { - // Similar to View.dispatchVisibilityAggregated implementation. - final boolean thisVisible = view.getVisibility() == View.VISIBLE; - if (thisVisible || !isVisible) { - view.onVisibilityAggregated(isVisible); - } - - if (view instanceof ViewGroup) { - isVisible = thisVisible && isVisible; - ViewGroup vg = (ViewGroup) view; - int count = vg.getChildCount(); - - for (int i = 0; i < count; i++) { - dispatchVisibilityAggregated(vg.getChildAt(i), isVisible); - } - } - } - private void notifyClockChanged(ClockPlugin plugin) { for (int i = 0; i < mListeners.size(); i++) { // It probably doesn't make sense to supply the same plugin instances to multiple @@ -323,6 +234,9 @@ public final class ClockManager { mContentResolver.registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.DOCKED_CLOCK_FACE), false, mContentObserver); + if (mDockManager == null) { + mDockManager = SysUiServiceProvider.getComponent(mContext, DockManager.class); + } if (mDockManager != null) { mDockManager.addListener(mDockEventListener); } diff --git a/packages/SystemUI/src/com/android/keyguard/clock/DefaultClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/DefaultClockController.java index 8a6a4cd95991..73414b30432f 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/DefaultClockController.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/DefaultClockController.java @@ -15,15 +15,19 @@ */ package com.android.keyguard.clock; +import android.app.WallpaperManager; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Color; import android.graphics.Paint.Style; import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; +import com.android.internal.colorextraction.ColorExtractor; import com.android.keyguard.R; +import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.plugins.ClockPlugin; import java.util.TimeZone; @@ -44,6 +48,16 @@ public class DefaultClockController implements ClockPlugin { private final LayoutInflater mLayoutInflater; /** + * Extracts accent color from wallpaper. + */ + private final SysuiColorExtractor mColorExtractor; + + /** + * Renders preview from clock view. + */ + private final ViewPreviewer mRenderer = new ViewPreviewer(); + + /** * Root view of preview. */ private View mView; @@ -61,11 +75,15 @@ public class DefaultClockController implements ClockPlugin { /** * Create a DefaultClockController instance. * + * @param res Resources contains title and thumbnail. * @param inflater Inflater used to inflate custom clock views. + * @param colorExtractor Extracts accent color from wallpaper. */ - public DefaultClockController(Resources res, LayoutInflater inflater) { + public DefaultClockController(Resources res, LayoutInflater inflater, + SysuiColorExtractor colorExtractor) { mResources = res; mLayoutInflater = inflater; + mColorExtractor = colorExtractor; } private void createViews() { @@ -90,6 +108,23 @@ public class DefaultClockController implements ClockPlugin { } @Override + public Bitmap getPreview(int width, int height) { + + // Use the big clock view for the preview + View view = getBigClockView(); + + // Initialize state of plugin before generating preview. + setDarkAmount(1f); + setTextColor(Color.WHITE); + ColorExtractor.GradientColors colors = mColorExtractor.getColors( + WallpaperManager.FLAG_LOCK, true); + setColorPalette(colors.supportsDarkText(), colors.getColorPalette()); + onTimeTick(); + + return mRenderer.createPreview(view, width, height); + } + + @Override public View getView() { return null; } diff --git a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java index 7401819fde4d..ea9f0cd3c17d 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java @@ -15,15 +15,19 @@ */ package com.android.keyguard.clock; +import android.app.WallpaperManager; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Color; import android.graphics.Paint.Style; import android.view.LayoutInflater; import android.view.View; import android.widget.TextClock; +import com.android.internal.colorextraction.ColorExtractor; import com.android.keyguard.R; +import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.plugins.ClockPlugin; import java.util.TimeZone; @@ -44,6 +48,16 @@ public class StretchAnalogClockController implements ClockPlugin { private final LayoutInflater mLayoutInflater; /** + * Extracts accent color from wallpaper. + */ + private final SysuiColorExtractor mColorExtractor; + + /** + * Renders preview from clock view. + */ + private final ViewPreviewer mRenderer = new ViewPreviewer(); + + /** * Custom clock shown on AOD screen and behind stack scroller on lock. */ private View mBigClockView; @@ -64,11 +78,15 @@ public class StretchAnalogClockController implements ClockPlugin { /** * Create a BubbleClockController instance. * - * @param layoutInflater Inflater used to inflate custom clock views. + * @param res Resources contains title and thumbnail. + * @param inflater Inflater used to inflate custom clock views. + * @param colorExtractor Extracts accent color from wallpaper. */ - public StretchAnalogClockController(Resources res, LayoutInflater inflater) { + public StretchAnalogClockController(Resources res, LayoutInflater inflater, + SysuiColorExtractor colorExtractor) { mResources = res; mLayoutInflater = inflater; + mColorExtractor = colorExtractor; } private void createViews() { @@ -99,6 +117,23 @@ public class StretchAnalogClockController implements ClockPlugin { } @Override + public Bitmap getPreview(int width, int height) { + + // Use the big clock view for the preview + View view = getBigClockView(); + + // Initialize state of plugin before generating preview. + setDarkAmount(1f); + setTextColor(Color.WHITE); + ColorExtractor.GradientColors colors = mColorExtractor.getColors( + WallpaperManager.FLAG_LOCK, true); + setColorPalette(colors.supportsDarkText(), colors.getColorPalette()); + onTimeTick(); + + return mRenderer.createPreview(view, width, height); + } + + @Override public View getView() { if (mView == null) { createViews(); @@ -136,6 +171,8 @@ public class StretchAnalogClockController implements ClockPlugin { @Override public void onTimeTick() { mAnalogClock.onTimeChanged(); + mDigitalClock.refresh(); + mLockClock.refresh(); } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java index 387f2656c6f8..67c0989b49c4 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java @@ -15,14 +15,18 @@ */ package com.android.keyguard.clock; +import android.app.WallpaperManager; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Color; import android.graphics.Paint.Style; import android.view.LayoutInflater; import android.view.View; +import com.android.internal.colorextraction.ColorExtractor; import com.android.keyguard.R; +import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.plugins.ClockPlugin; import java.util.TimeZone; @@ -43,6 +47,16 @@ public class TypeClockController implements ClockPlugin { private final LayoutInflater mLayoutInflater; /** + * Extracts accent color from wallpaper. + */ + private final SysuiColorExtractor mColorExtractor; + + /** + * Renders preview from clock view. + */ + private final ViewPreviewer mRenderer = new ViewPreviewer(); + + /** * Custom clock shown on AOD screen and behind stack scroller on lock. */ private View mView; @@ -61,11 +75,15 @@ public class TypeClockController implements ClockPlugin { /** * Create a TypeClockController instance. * + * @param res Resources contains title and thumbnail. * @param inflater Inflater used to inflate custom clock views. + * @param colorExtractor Extracts accent color from wallpaper. */ - TypeClockController(Resources res, LayoutInflater inflater) { + TypeClockController(Resources res, LayoutInflater inflater, + SysuiColorExtractor colorExtractor) { mResources = res; mLayoutInflater = inflater; + mColorExtractor = colorExtractor; } private void createViews() { @@ -96,6 +114,23 @@ public class TypeClockController implements ClockPlugin { } @Override + public Bitmap getPreview(int width, int height) { + + // Use the big clock view for the preview + View view = getBigClockView(); + + // Initialize state of plugin before generating preview. + setDarkAmount(1f); + setTextColor(Color.WHITE); + ColorExtractor.GradientColors colors = mColorExtractor.getColors( + WallpaperManager.FLAG_LOCK, true); + setColorPalette(colors.supportsDarkText(), colors.getColorPalette()); + onTimeTick(); + + return mRenderer.createPreview(view, width, height); + } + + @Override public View getView() { if (mLockClock == null) { createViews(); diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ViewPreviewer.java b/packages/SystemUI/src/com/android/keyguard/clock/ViewPreviewer.java new file mode 100644 index 000000000000..abd0dd28dabc --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/clock/ViewPreviewer.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2019 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.keyguard.clock; + +import android.annotation.Nullable; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; + +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; + +/** + * Creates a preview image ({@link Bitmap}) of a {@link View} for a custom clock face. + */ +final class ViewPreviewer { + + private static final String TAG = "ViewPreviewer"; + + /** + * Handler used to run {@link View#draw(Canvas)} on the main thread. + */ + private final Handler mMainHandler = new Handler(Looper.getMainLooper()); + + /** + * Generate a realistic preview of a clock face. + * + * @param view view is used to generate preview image. + * @param width width of the preview image, should be the same as device width in pixels. + * @param height height of the preview image, should be the same as device height in pixels. + * @return bitmap of view. + */ + @Nullable + Bitmap createPreview(View view, int width, int height) { + if (view == null) { + return null; + } + FutureTask<Bitmap> task = new FutureTask<>(new Callable<Bitmap>() { + @Override + public Bitmap call() { + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + + // Draw clock view hierarchy to canvas. + Canvas canvas = new Canvas(bitmap); + canvas.drawColor(Color.BLACK); + dispatchVisibilityAggregated(view, true); + view.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)); + view.layout(0, 0, width, height); + view.draw(canvas); + + return bitmap; + } + }); + + if (Looper.myLooper() == Looper.getMainLooper()) { + task.run(); + } else { + mMainHandler.post(task); + } + + try { + return task.get(); + } catch (Exception e) { + Log.e(TAG, "Error completing task", e); + return null; + } + } + + private void dispatchVisibilityAggregated(View view, boolean isVisible) { + // Similar to View.dispatchVisibilityAggregated implementation. + final boolean thisVisible = view.getVisibility() == View.VISIBLE; + if (thisVisible || !isVisible) { + view.onVisibilityAggregated(isVisible); + } + + if (view instanceof ViewGroup) { + isVisible = thisVisible && isVisible; + ViewGroup vg = (ViewGroup) view; + int count = vg.getChildCount(); + + for (int i = 0; i < count; i++) { + dispatchVisibilityAggregated(vg.getChildAt(i), isVisible); + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/ActivityIntentHelper.java b/packages/SystemUI/src/com/android/systemui/ActivityIntentHelper.java new file mode 100644 index 000000000000..2b62e040b1fd --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/ActivityIntentHelper.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2019 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.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; + +import java.util.List; + +/** + * Contains useful methods for querying properties of an Activity Intent. + */ +public class ActivityIntentHelper { + + private final Context mContext; + + public ActivityIntentHelper(Context context) { + mContext = context; + } + + /** + * Determines if sending the given intent would result in starting an Intent resolver activity, + * instead of resolving to a specific component. + * + * @param intent the intent + * @param currentUserId the id for the user to resolve as + * @return true if the intent would launch a resolver activity + */ + public boolean wouldLaunchResolverActivity(Intent intent, int currentUserId) { + ActivityInfo targetActivityInfo = getTargetActivityInfo(intent, currentUserId, + false /* onlyDirectBootAware */); + return targetActivityInfo == null; + } + + /** + * Returns info about the target Activity of a given intent, or null if the intent does not + * resolve to a specific component meeting the requirements. + * + * @param onlyDirectBootAware a boolean indicating whether the matched activity packages must + * be direct boot aware when in direct boot mode if false, all packages are considered + * a match even if they are not aware. + * @return the target activity info of the intent it resolves to a specific package or + * {@code null} if it resolved to the resolver activity + */ + public ActivityInfo getTargetActivityInfo(Intent intent, int currentUserId, + boolean onlyDirectBootAware) { + PackageManager packageManager = mContext.getPackageManager(); + int flags = PackageManager.MATCH_DEFAULT_ONLY; + if (!onlyDirectBootAware) { + flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE + | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; + } + final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser( + intent, flags, currentUserId); + if (appList.size() == 0) { + return null; + } + ResolveInfo resolved = packageManager.resolveActivityAsUser(intent, + flags | PackageManager.GET_META_DATA, currentUserId); + if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) { + return null; + } else { + return resolved.activityInfo; + } + } + + /** + * Determines if the given intent resolves to an Activity which is allowed to appear above + * the lock screen. + * + * @param intent the intent to resolve + * @return true if the launched Activity would appear above the lock screen + */ + public boolean wouldShowOverLockscreen(Intent intent, int currentUserId) { + ActivityInfo targetActivityInfo = getTargetActivityInfo(intent, + currentUserId, false /* onlyDirectBootAware */); + return targetActivityInfo != null + && (targetActivityInfo.flags & (ActivityInfo.FLAG_SHOW_WHEN_LOCKED + | ActivityInfo.FLAG_SHOW_FOR_ALL_USERS)) > 0; + } + + /** + * Determines if sending the given intent would result in starting an Intent resolver activity, + * instead of resolving to a specific component. + * + * @param resolved the resolveInfo for the intent as returned by resolveActivityAsUser + * @param appList a list of resolveInfo as returned by queryIntentActivitiesAsUser + * @return true if the intent would launch a resolver activity + */ + public boolean wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList) { + // If the list contains the above resolved activity, then it can't be + // ResolverActivity itself. + for (int i = 0; i < appList.size(); i++) { + ResolveInfo tmp = appList.get(i); + if (tmp.activityInfo.name.equals(resolved.activityInfo.name) + && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) { + return false; + } + } + return true; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java index 895f9b9a1cdf..f649976ccf01 100644 --- a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java +++ b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java @@ -155,8 +155,9 @@ public class DependencyProvider { @Singleton @Provides - public NightDisplayListener provideNightDisplayListener(Context context) { - return new NightDisplayListener(context); + public NightDisplayListener provideNightDisplayListener(Context context, + @Named(BG_HANDLER_NAME) Handler bgHandler) { + return new NightDisplayListener(context, bgHandler); } @Singleton diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index 6bb4fb5ef94a..47ad0c17c414 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -31,7 +31,6 @@ import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.assist.AssistManager; import com.android.systemui.classifier.FalsingManager; -import com.android.systemui.dock.DockManager; import com.android.systemui.fragments.FragmentService; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -220,16 +219,6 @@ public class SystemUIFactory { return SysUiServiceProvider.getComponent(context, StatusBar.class); } - /** - * Provides DockManager. - */ - @Singleton - @Provides - @Nullable - public DockManager providesDockManager(Context context) { - return SysUiServiceProvider.getComponent(context, DockManager.class); - } - @Module protected static class ContextHolder { private Context mContext; diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java index ace086f7af2c..3fc6689b2f19 100644 --- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java @@ -204,24 +204,59 @@ public class AppOpsControllerImpl implements AppOpsController, } /** - * Does the app-op item refer to a user sensitive permission. Only user sensitive permission - * should be shown to the user by default. + * Does the app-op code refer to a user sensitive permission for the specified user id + * and package. Only user sensitive permission should be shown to the user by default. * - * @param item The item + * @param appOpCode The code of the app-op. + * @param uid The uid of the user. + * @param packageName The name of the package. * * @return {@code true} iff the app-op item is user sensitive */ - private boolean isUserSensitive(AppOpItem item) { - String permission = AppOpsManager.opToPermission(item.getCode()); + private boolean isUserSensitive(int appOpCode, int uid, String packageName) { + String permission = AppOpsManager.opToPermission(appOpCode); if (permission == null) { return false; } int permFlags = mContext.getPackageManager().getPermissionFlags(permission, - item.getPackageName(), UserHandle.getUserHandleForUid(item.getUid())); + packageName, UserHandle.getUserHandleForUid(uid)); return (permFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) != 0; } /** + * Does the app-op item refer to an operation that should be shown to the user. + * Only specficic ops (like SYSTEM_ALERT_WINDOW) or ops that refer to user sensitive + * permission should be shown to the user by default. + * + * @param item The item + * + * @return {@code true} iff the app-op item should be shown to the user + */ + private boolean isUserVisible(AppOpItem item) { + return isUserVisible(item.getCode(), item.getUid(), item.getPackageName()); + } + + + /** + * Does the app-op, uid and package name, refer to an operation that should be shown to the + * user. Only specficic ops (like {@link AppOpsManager.OP_SYSTEM_ALERT_WINDOW}) or + * ops that refer to user sensitive permission should be shown to the user by default. + * + * @param item The item + * + * @return {@code true} iff the app-op for should be shown to the user + */ + private boolean isUserVisible(int appOpCode, int uid, String packageName) { + // currently OP_SYSTEM_ALERT_WINDOW does not correspond to a platform permission + // which may be user senstive, so for now always show it to the user. + if (appOpCode == AppOpsManager.OP_SYSTEM_ALERT_WINDOW) { + return true; + } + + return isUserSensitive(appOpCode, uid, packageName); + } + + /** * Returns a copy of the list containing all the active AppOps that the controller tracks. * * @return List of active AppOps information @@ -245,7 +280,7 @@ public class AppOpsControllerImpl implements AppOpsController, for (int i = 0; i < numActiveItems; i++) { AppOpItem item = mActiveItems.get(i); if ((userId == UserHandle.USER_ALL || UserHandle.getUserId(item.getUid()) == userId) - && isUserSensitive(item)) { + && isUserVisible(item)) { list.add(item); } } @@ -255,7 +290,7 @@ public class AppOpsControllerImpl implements AppOpsController, for (int i = 0; i < numNotedItems; i++) { AppOpItem item = mNotedItems.get(i); if ((userId == UserHandle.USER_ALL || UserHandle.getUserId(item.getUid()) == userId) - && isUserSensitive(item)) { + && isUserVisible(item)) { list.add(item); } } @@ -281,7 +316,8 @@ public class AppOpsControllerImpl implements AppOpsController, } private void notifySuscribers(int code, int uid, String packageName, boolean active) { - if (mCallbacksByCode.containsKey(code)) { + if (mCallbacksByCode.containsKey(code) + && isUserVisible(code, uid, packageName)) { for (Callback cb: mCallbacksByCode.get(code)) { cb.onActiveStateChanged(code, uid, packageName, active); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java index 1154515b261c..98f446dea9b1 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java @@ -18,8 +18,6 @@ package com.android.systemui.bubbles; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Path; import android.graphics.Point; import android.graphics.Rect; import android.util.AttributeSet; @@ -36,11 +34,9 @@ public class BadgedImageView extends ImageView { private int mIconSize; private Rect mTempBounds = new Rect(); private Point mTempPoint = new Point(); - private Path mClipPath = new Path(); private float mDotScale = 0f; private int mUpdateDotColor; - private int mBubbleDefaultBgColor; private boolean mShowUpdateDot; private boolean mOnLeft; @@ -59,32 +55,17 @@ public class BadgedImageView extends ImageView { public BadgedImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - setScaleType(ScaleType.CENTER_CROP); mIconSize = getResources().getDimensionPixelSize(R.dimen.individual_bubble_size); mDotRenderer = new BadgeRenderer(mIconSize); TypedArray ta = context.obtainStyledAttributes( new int[] {android.R.attr.colorBackgroundFloating}); - mBubbleDefaultBgColor = ta.getColor(0, Color.WHITE); ta.recycle(); } - // TODO: Clipping oval path isn't great: rerender image into a separate, rounded bitmap and - // then draw would be better @Override public void onDraw(Canvas canvas) { - canvas.save(); - // Circle crop - mClipPath.addOval(getPaddingStart(), getPaddingTop(), - getWidth() - getPaddingEnd(), getHeight() - getPaddingBottom(), Path.Direction.CW); - canvas.clipPath(mClipPath); - canvas.drawColor(mBubbleDefaultBgColor); super.onDraw(canvas); - - // After we've circle cropped what we're showing, restore so we don't clip the badge - canvas.restore(); - - // Draw the badge if (mShowUpdateDot) { getDrawingRect(mTempBounds); mTempPoint.set((getWidth() - mIconSize) / 2, getPaddingTop()); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 4a2731e5437a..e84c64838fd6 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -26,6 +26,7 @@ import static com.android.systemui.statusbar.notification.NotificationAlertingMa import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.Nullable; +import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityTaskManager; import android.app.IActivityTaskManager; @@ -64,6 +65,7 @@ import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.policy.ConfigurationController; import java.lang.annotation.Retention; +import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; @@ -80,8 +82,6 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe private static final String TAG = "BubbleController"; - private static final int MAX_BUBBLES = 5; // TODO: actually enforce this - @Retention(SOURCE) @IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED, DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION}) @@ -94,6 +94,8 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe static final int DISMISS_NOTIF_CANCEL = 5; static final int DISMISS_ACCESSIBILITY_ACTION = 6; + static final int MAX_BUBBLES = 5; // TODO: actually enforce this + // Enables some subset of notifs to automatically become bubbles private static final boolean DEBUG_ENABLE_AUTO_BUBBLE = false; @@ -340,6 +342,9 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe // It's new mStackView.addBubble(notif); } + if (shouldAutoExpand(notif)) { + mStackView.setExpandedBubble(notif); + } updateVisibility(); } @@ -379,9 +384,11 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe } if (shouldAutoBubbleForFlags(mContext, entry) || shouldBubble(entry)) { // TODO: handle group summaries - // It's a new notif, it shows in the shade and as a bubble entry.setIsBubble(true); - entry.setShowInShadeWhenBubble(true); + boolean suppressNotification = entry.getBubbleMetadata() != null + && entry.getBubbleMetadata().getSuppressInitialNotification() + && isForegroundApp(entry.notification.getPackageName()); + entry.setShowInShadeWhenBubble(!suppressNotification); } } @@ -522,6 +529,23 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe || autoBubbleAll; } + private boolean shouldAutoExpand(NotificationEntry entry) { + Notification.BubbleMetadata metadata = entry.getBubbleMetadata(); + return metadata != null && metadata.getAutoExpandBubble() + && isForegroundApp(entry.notification.getPackageName()); + } + + /** + * Return true if the applications with the package name is running in foreground. + * + * @param pkgName application package name. + */ + private boolean isForegroundApp(String pkgName) { + ActivityManager am = mContext.getSystemService(ActivityManager.class); + List<RunningTaskInfo> tasks = am.getRunningTasks(1 /* maxNum */); + return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName()); + } + /** * This task stack listener is responsible for responding to tasks moved to the front * which are on the default (main) display. When this happens, expanded bubbles must be diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java index 8e3afd8bcae0..de887ff6ff86 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java @@ -381,10 +381,18 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList } /** - * Update bubble expanded view header when user toggles dark mode. + * Update header color when user toggles dark mode. */ void updateHeaderColor() { - mHeaderView.setBackgroundColor(mContext.getColor(R.attr.colorAccent)); + TypedArray ta = mContext.obtainStyledAttributes( + new int[] {android.R.attr.colorBackgroundFloating, android.R.attr.colorForeground}); + int bgColor = ta.getColor(0, Color.WHITE /* default */); + int btnColor = ta.getColor(1, Color.BLACK /* default */); + ta.recycle(); + + mHeaderView.setBackgroundColor(bgColor); + mSettingsIcon.setColorFilter(btnColor); + mDeepLinkIcon.setColorFilter(btnColor); } private void updateHeaderView() { @@ -413,7 +421,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList ((TextView) mPermissionView.findViewById(R.id.pkgname)).setText(mAppName); ((TextView) mPermissionView.findViewById(R.id.prompt)).setText( getResources().getString(R.string.bubbles_prompt, mAppName)); - logBubbleClickEvent(mEntry.notification, + logBubbleClickEvent(mEntry, StatsLog.BUBBLE_UICHANGED__ACTION__PERMISSION_DIALOG_SHOWN); } } @@ -437,7 +445,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList } boolean performBackPressIfNeeded() { - if (mActivityView == null || !usingActivityView()) { + if (!usingActivityView()) { return false; } mActivityView.performBackPress(); @@ -509,7 +517,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList mStackView.collapseStack(() -> { try { n.contentIntent.send(); - logBubbleClickEvent(mEntry.notification, + logBubbleClickEvent(mEntry, StatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_APP); } catch (PendingIntent.CanceledException e) { Log.w(TAG, "Failed to send intent for bubble with key: " @@ -521,7 +529,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList mEntry.notification.getUid()); mStackView.collapseStack(() -> { mContext.startActivity(intent); - logBubbleClickEvent(mEntry.notification, + logBubbleClickEvent(mEntry, StatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_SETTINGS); }); } else if (id == R.id.no_bubbles_button) { @@ -544,7 +552,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList mOnBubbleBlockedListener.onBubbleBlocked(mEntry); } mStackView.onExpandedHeightChanged(); - logBubbleClickEvent(mEntry.notification, + logBubbleClickEvent(mEntry, allowed ? StatsLog.BUBBLE_UICHANGED__ACTION__PERMISSION_OPT_IN : StatsLog.BUBBLE_UICHANGED__ACTION__PERMISSION_OPT_OUT); } catch (RemoteException e) { @@ -593,7 +601,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList } private boolean usingActivityView() { - return mBubbleIntent != null; + return mBubbleIntent != null && mActivityView != null; } private void applyRowState(ExpandableNotificationRow view) { @@ -707,10 +715,11 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList /** * Logs bubble UI click event. * - * @param notification the bubble notification that user is interacting with. + * @param entry the bubble notification entry that user is interacting with. * @param action the user interaction enum. */ - private void logBubbleClickEvent(StatusBarNotification notification, int action) { + private void logBubbleClickEvent(NotificationEntry entry, int action) { + StatusBarNotification notification = entry.notification; StatsLog.write(StatsLog.BUBBLE_UI_CHANGED, notification.getPackageName(), notification.getNotification().getChannelId(), @@ -719,7 +728,8 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList mStackView.getBubbleCount(), action, mStackView.getNormalizedXPosition(), - mStackView.getNormalizedYPosition()); + mStackView.getNormalizedYPosition(), + entry.showInShadeWhenBubble()); } private int getDimenForPackageUser(int resId, String pkg, int userId) { diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index 580acb82ebc1..be55829869eb 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -52,6 +52,7 @@ import androidx.dynamicanimation.animation.SpringForce; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.ViewClippingUtil; +import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.bubbles.BubbleController.DismissReason; import com.android.systemui.bubbles.animation.ExpandedAnimationController; @@ -135,7 +136,7 @@ public class BubbleStackView extends FrameLayout { private BubbleExpandedView.OnBubbleBlockedListener mBlockedListener; private boolean mViewUpdatedRequested = false; - private boolean mIsAnimating = false; + private boolean mIsExpansionAnimating = false; private LayoutInflater mInflater; @@ -233,6 +234,11 @@ public class BubbleStackView extends FrameLayout { new SpringForce() .setStiffness(SpringForce.STIFFNESS_LOW) .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)); + mExpandedViewYAnim.addEndListener((anim, cancelled, value, velocity) -> { + if (mIsExpanded && mExpandedBubble != null) { + mExpandedBubble.expandedView.updateView(); + } + }); setClipChildren(false); setFocusable(true); @@ -241,7 +247,7 @@ public class BubbleStackView extends FrameLayout { setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> { final int keyboardHeight = insets.getSystemWindowInsetBottom() - insets.getStableInsetBottom(); - if (!mIsExpanded) { + if (!mIsExpanded || mIsExpansionAnimating) { return view.onApplyWindowInsets(insets); } mImeVisible = keyboardHeight != 0; @@ -265,7 +271,9 @@ public class BubbleStackView extends FrameLayout { * Handle config changes. */ public void onConfigChanged() { - mExpandedBubble.expandedView.updateHeaderColor(); + for (Bubble b: mBubbleData.getBubbles()) { + b.expandedView.updateHeaderColor(); + } } @Override @@ -309,7 +317,8 @@ public class BubbleStackView extends FrameLayout { } switch (action) { case AccessibilityNodeInfo.ACTION_DISMISS: - stackDismissed(BubbleController.DISMISS_ACCESSIBILITY_ACTION); + Dependency.get(BubbleController.class).dismissStack( + BubbleController.DISMISS_ACCESSIBILITY_ACTION); return true; case AccessibilityNodeInfo.ACTION_COLLAPSE: collapseStack(); @@ -415,7 +424,7 @@ public class BubbleStackView extends FrameLayout { * Sets the entry that should be expanded and expands if needed. */ @VisibleForTesting - public void setExpandedBubble(NotificationEntry entry) { + void setExpandedBubble(NotificationEntry entry) { for (int i = 0; i < mBubbleContainer.getChildCount(); i++) { BubbleView bv = (BubbleView) mBubbleContainer.getChildAt(i); if (entry.equals(bv.getEntry())) { @@ -429,7 +438,7 @@ public class BubbleStackView extends FrameLayout { * * @param entry the notification to add to the stack of bubbles. */ - public void addBubble(NotificationEntry entry) { + void addBubble(NotificationEntry entry) { Bubble b = new Bubble(entry, mInflater, this /* stackView */, mBlockedListener); mBubbleData.addBubble(b); @@ -444,12 +453,17 @@ public class BubbleStackView extends FrameLayout { /** * Remove a bubble from the stack. */ - public void removeBubble(String key, int reason) { + void removeBubble(String key, int reason) { Bubble b = mBubbleData.removeBubble(key); if (b == null) { return; } - int removedIndex = dismissBubble(b, reason); + setBubbleDismissed(b, reason); + + // Remove it from the views + int removedIndex = mBubbleContainer.indexOfChild(b.iconView); + mBubbleContainer.removeViewAt(removedIndex); + int bubbleCount = mBubbleContainer.getChildCount(); if (bubbleCount == 0) { // If no bubbles remain, collapse the entire stack. @@ -474,9 +488,9 @@ public class BubbleStackView extends FrameLayout { /** * Dismiss the stack of bubbles. */ - public void stackDismissed(int reason) { + void stackDismissed(int reason) { for (Bubble bubble : mBubbleData.getBubbles()) { - dismissBubble(bubble, reason); + setBubbleDismissed(bubble, reason); } mBubbleData.clear(); collapseStack(); @@ -488,8 +502,7 @@ public class BubbleStackView extends FrameLayout { } /** - * Marks the notification entry as dismissed, cleans up Bubble icon and expanded view UI - * elements and calls deleteIntent if necessary. + * Marks the notification entry as dismissed & calls any delete intents for the bubble. * * <p>Note: This does not remove the Bubble from BubbleData. * @@ -497,17 +510,13 @@ public class BubbleStackView extends FrameLayout { * @param reason code for the reason the dismiss was triggered * @see BubbleController.DismissReason */ - private int dismissBubble(Bubble bubble, @DismissReason int reason) { + private void setBubbleDismissed(Bubble bubble, @DismissReason int reason) { if (DEBUG) { Log.d(TAG, "dismissBubble: " + bubble + " reason=" + reason); } bubble.entry.setBubbleDismissed(true); bubble.expandedView.cleanUpExpandedState(); - // Remove it from the views - int removedIndex = mBubbleContainer.indexOfChild(bubble.iconView); - mBubbleContainer.removeViewAt(removedIndex); - if (reason == BubbleController.DISMISS_USER_GESTURE) { Notification.BubbleMetadata bubbleMetadata = bubble.entry.getBubbleMetadata(); PendingIntent deleteIntent = bubbleMetadata != null @@ -522,7 +531,6 @@ public class BubbleStackView extends FrameLayout { } } } - return removedIndex; } /** @@ -618,24 +626,23 @@ public class BubbleStackView extends FrameLayout { updateExpandedBubble(); applyCurrentState(); - mIsAnimating = true; + mIsExpansionAnimating = true; Runnable updateAfter = () -> { applyCurrentState(); - mIsAnimating = false; + mIsExpansionAnimating = false; requestUpdate(); }; if (shouldExpand) { mBubbleContainer.setController(mExpandedAnimationController); mExpandedAnimationController.expandFromStack( - /* collapseTo */ - mStackAnimationController.getStackPositionAlongNearestHorizontalEdge(), - /* after */ + mStackAnimationController.getStackPositionAlongNearestHorizontalEdge() + /* collapseTo */, () -> { updatePointerPosition(); updateAfter.run(); - }); + } /* after */); } else { mBubbleContainer.cancelAllAnimations(); mExpandedAnimationController.collapseBackToStack( @@ -700,7 +707,7 @@ public class BubbleStackView extends FrameLayout { /** Called with the coordinates to which an individual bubble has been dragged. */ public void onBubbleDragged(View bubble, float x, float y) { - if (!mIsExpanded || mIsAnimating) { + if (!mIsExpanded || mIsExpansionAnimating) { return; } @@ -710,7 +717,7 @@ public class BubbleStackView extends FrameLayout { /** Called when a drag operation on an individual bubble has finished. */ public void onBubbleDragFinish( View bubble, float x, float y, float velX, float velY, boolean dismissed) { - if (!mIsExpanded || mIsAnimating) { + if (!mIsExpanded || mIsExpansionAnimating) { return; } @@ -722,7 +729,7 @@ public class BubbleStackView extends FrameLayout { } void onDragStart() { - if (mIsExpanded || mIsAnimating) { + if (mIsExpanded || mIsExpansionAnimating) { return; } @@ -731,7 +738,7 @@ public class BubbleStackView extends FrameLayout { } void onDragged(float x, float y) { - if (mIsExpanded || mIsAnimating) { + if (mIsExpanded || mIsExpansionAnimating) { return; } @@ -741,7 +748,7 @@ public class BubbleStackView extends FrameLayout { void onDragFinish(float x, float y, float velX, float velY) { // TODO: Add fling to bottom to dismiss. - if (mIsExpanded || mIsAnimating) { + if (mIsExpanded || mIsExpansionAnimating) { return; } @@ -830,7 +837,7 @@ public class BubbleStackView extends FrameLayout { } private void requestUpdate() { - if (mViewUpdatedRequested || mIsAnimating) { + if (mViewUpdatedRequested || mIsExpansionAnimating) { return; } mViewUpdatedRequested = true; @@ -850,7 +857,6 @@ public class BubbleStackView extends FrameLayout { private void applyCurrentState() { Log.d(TAG, "applyCurrentState: mIsExpanded=" + mIsExpanded); - mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE); if (mIsExpanded) { // First update the view so that it calculates a new height (ensuring the y position @@ -860,18 +866,20 @@ public class BubbleStackView extends FrameLayout { if (!mExpandedViewYAnim.isRunning()) { // We're not animating so set the value mExpandedViewContainer.setTranslationY(y); + mExpandedBubble.expandedView.updateView(); } else { - // We are animating so update the value + // We are animating so update the value; there is an end listener on the animator + // that will ensure expandedeView.updateView gets called. mExpandedViewYAnim.animateToFinalPosition(y); } - mExpandedBubble.expandedView.updateView(); } int bubbsCount = mBubbleContainer.getChildCount(); for (int i = 0; i < bubbsCount; i++) { BubbleView bv = (BubbleView) mBubbleContainer.getChildAt(i); bv.updateDotVisibility(); - bv.setZ(bubbsCount - i); + bv.setZ((BubbleController.MAX_BUBBLES + * getResources().getDimensionPixelSize(R.dimen.bubble_elevation)) - i); // Draw the shadow around the circle inscribed within the bubble's bounds. This // (intentionally) does not draw a shadow behind the update dot, which should be drawing @@ -954,7 +962,8 @@ public class BubbleStackView extends FrameLayout { getBubbleCount(), action, getNormalizedXPosition(), - getNormalizedYPosition()); + getNormalizedYPosition(), + false /* unread notification */); } else { StatusBarNotification notification = bubble.entry.notification; StatsLog.write(StatsLog.BUBBLE_UI_CHANGED, @@ -965,7 +974,8 @@ public class BubbleStackView extends FrameLayout { getBubbleCount(), action, getNormalizedXPosition(), - getNormalizedYPosition()); + getNormalizedYPosition(), + bubble.entry.showInShadeWhenBubble()); } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java index 7a68be494cf9..3b9164d60c5c 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java @@ -20,11 +20,11 @@ import android.annotation.Nullable; import android.app.Notification; import android.content.Context; import android.graphics.Color; +import android.graphics.drawable.AdaptiveIconDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.graphics.drawable.InsetDrawable; -import android.graphics.drawable.LayerDrawable; import android.util.AttributeSet; import android.widget.FrameLayout; import android.widget.TextView; @@ -41,6 +41,9 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow public class BubbleView extends FrameLayout { private static final String TAG = "BubbleView"; + private static final int DARK_ICON_ALPHA = 180; + private static final double ICON_MIN_CONTRAST = 4.1; + private static final int DEFAULT_BACKGROUND_COLOR = Color.LTGRAY; // Same value as Launcher3 badge code private static final float WHITE_SCRIM_ALPHA = 0.54f; private Context mContext; @@ -84,7 +87,6 @@ public class BubbleView extends FrameLayout { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - updateViews(); } @Override @@ -206,12 +208,7 @@ public class BubbleView extends FrameLayout { } Drawable iconDrawable = ic.loadDrawable(mContext); if (needsTint) { - // Center icon on coloured background - iconDrawable.setTint(Color.WHITE); // TODO: dark mode - Drawable bg = new ColorDrawable(n.color); - InsetDrawable d = new InsetDrawable(iconDrawable, mIconInset); - Drawable[] layers = {bg, d}; - mBadgedImageView.setImageDrawable(new LayerDrawable(layers)); + mBadgedImageView.setImageDrawable(buildIconWithTint(iconDrawable, n.color)); } else { mBadgedImageView.setImageDrawable(iconDrawable); } @@ -220,6 +217,23 @@ public class BubbleView extends FrameLayout { animateDot(mEntry.showInShadeWhenBubble() /* showDot */); } + private Drawable buildIconWithTint(Drawable iconDrawable, int backgroundColor) { + backgroundColor = ColorUtils.setAlphaComponent(backgroundColor, 255 /* alpha */); + if (backgroundColor == Color.TRANSPARENT) { + // ColorUtils throws exception when background is translucent. + backgroundColor = DEFAULT_BACKGROUND_COLOR; + } + iconDrawable.setTint(Color.WHITE); + double contrastRatio = ColorUtils.calculateContrast(Color.WHITE, backgroundColor); + if (contrastRatio < ICON_MIN_CONTRAST) { + int dark = ColorUtils.setAlphaComponent(Color.BLACK, DARK_ICON_ALPHA); + iconDrawable.setTint(dark); + } + InsetDrawable foreground = new InsetDrawable(iconDrawable, mIconInset); + ColorDrawable background = new ColorDrawable(backgroundColor); + return new AdaptiveIconDrawable(background, foreground); + } + private int determineDominateColor(Drawable d, int defaultTint) { // XXX: should we pull from the drawable, app icon, notif tint? return ColorUtils.blendARGB(defaultTint, Color.WHITE, WHITE_SCRIM_ALPHA); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java index 2fa87d83f75d..0f659c338ce8 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java @@ -226,9 +226,6 @@ public class PhysicsAnimationLayout extends FrameLayout { protected final HashMap<DynamicAnimation.ViewProperty, Runnable> mEndActionForProperty = new HashMap<>(); - /** Set of currently rendered transient views. */ - private final Set<View> mTransientViews = new HashSet<>(); - /** The currently active animation controller. */ private PhysicsAnimationController mController; @@ -328,18 +325,6 @@ public class PhysicsAnimationLayout extends FrameLayout { removeView(getChildAt(index)); } - @Override - public void addTransientView(View view, int index) { - super.addTransientView(view, index); - mTransientViews.add(view); - } - - @Override - public void removeTransientView(View view) { - super.removeTransientView(view); - mTransientViews.remove(view); - } - /** Immediately moves the view from wherever it currently is, to the given index. */ public void moveViewTo(View view, int index) { super.removeView(view); @@ -363,7 +348,9 @@ public class PhysicsAnimationLayout extends FrameLayout { // Tell the controller to animate this view out, and call the callback when it's // finished. mController.onChildRemoved(view, index, () -> { - // Done animating, remove the transient view. + // The controller says it's done with the transient view, cancel animations in case + // any are still running and then remove it. + cancelAnimationsOnView(view); removeTransientView(view); if (callback != null) { @@ -470,13 +457,11 @@ public class PhysicsAnimationLayout extends FrameLayout { DynamicAnimation.ViewProperty property, View child, int index) { SpringAnimation newAnim = new SpringAnimation(child, property); newAnim.addUpdateListener((animation, value, velocity) -> { + final int indexOfChild = indexOfChild(child); final int nextAnimInChain = - mController.getNextAnimationInChain(property, indexOfChild(child)); + mController.getNextAnimationInChain(property, indexOfChild); - // If the controller doesn't want us to chain, or if we're a transient view in the - // process of being removed, don't chain. - if (nextAnimInChain == PhysicsAnimationController.NONE - || mTransientViews.contains(child)) { + if (nextAnimInChain == PhysicsAnimationController.NONE || indexOfChild < 0) { return; } @@ -814,4 +799,9 @@ public class PhysicsAnimationLayout extends FrameLayout { } } } + + @Override + protected boolean canReceivePointerEvents() { + return false; + } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java index a4592d554f0e..3c6dc7317357 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java @@ -87,7 +87,8 @@ public class DozeDockHandler implements DozeMachine.Part { } private void requestPulseOutNow(State dozeState) { - if (dozeState == State.DOZE_REQUEST_PULSE || dozeState == State.DOZE_PULSING) { + if (dozeState == State.DOZE_REQUEST_PULSE || dozeState == State.DOZE_PULSING + || dozeState == State.DOZE_PULSING_BRIGHT) { final int pulseReason = mMachine.getPulseReason(); if (pulseReason == DozeLog.PULSE_REASON_DOCKING) { mDozeHost.stopPulsing(); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java index 36e28dc0156d..060765495f48 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java @@ -71,7 +71,7 @@ public class DozeFactory { new DozeScreenState(wrappedService, handler, params, wakeLock), createDozeScreenBrightness(context, wrappedService, sensorManager, host, params, handler), - new DozeWallpaperState(context, machine), + new DozeWallpaperState(context), new DozeDockHandler(context, machine, host, config, handler, dockManager) }); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java index bd7a421e9762..3c9d4a9704a0 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java @@ -33,7 +33,11 @@ public interface DozeHost { boolean isProvisioned(); boolean isBlockingDoze(); - void extendPulse(); + /** + * Makes a current pulse last for twice as long. + * @param reason why we're extending it. + */ + void extendPulse(int reason); void setAnimateWakeup(boolean animateWakeup); void setAnimateScreenOff(boolean animateScreenOff); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java index c243899c6bc9..8bf2256a4f80 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java @@ -59,6 +59,8 @@ public class DozeMachine { DOZE_REQUEST_PULSE, /** Pulse is showing. Device is awake and showing UI. */ DOZE_PULSING, + /** Pulse is showing with bright wallpaper. Device is awake and showing UI. */ + DOZE_PULSING_BRIGHT, /** Pulse is done showing. Followed by transition to DOZE or DOZE_AOD. */ DOZE_PULSE_DONE, /** Doze is done. DozeService is finished. */ @@ -84,6 +86,7 @@ public class DozeMachine { switch (this) { case DOZE_REQUEST_PULSE: case DOZE_PULSING: + case DOZE_PULSING_BRIGHT: return true; default: return false; @@ -101,6 +104,7 @@ public class DozeMachine { case DOZE: return Display.STATE_OFF; case DOZE_PULSING: + case DOZE_PULSING_BRIGHT: return Display.STATE_ON; case DOZE_AOD: case DOZE_AOD_PAUSING: @@ -188,7 +192,10 @@ public class DozeMachine { @MainThread public State getState() { Assert.isMainThread(); - Preconditions.checkState(!isExecutingTransition()); + if (isExecutingTransition()) { + throw new IllegalStateException("Cannot get state because there were pending " + + "transitions: " + mQueuedRequests.toString()); + } return mState; } @@ -202,6 +209,7 @@ public class DozeMachine { Assert.isMainThread(); Preconditions.checkState(mState == State.DOZE_REQUEST_PULSE || mState == State.DOZE_PULSING + || mState == State.DOZE_PULSING_BRIGHT || mState == State.DOZE_PULSE_DONE, "must be in pulsing state, but is " + mState); return mPulseReason; } @@ -283,7 +291,8 @@ public class DozeMachine { break; case DOZE_PULSE_DONE: Preconditions.checkState( - mState == State.DOZE_REQUEST_PULSE || mState == State.DOZE_PULSING); + mState == State.DOZE_REQUEST_PULSE || mState == State.DOZE_PULSING + || mState == State.DOZE_PULSING_BRIGHT); break; default: break; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java index 1dd3101075b0..bd6882c01bbd 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java @@ -56,6 +56,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi private boolean mRegistered; private int mDefaultDozeBrightness; private boolean mPaused = false; + private boolean mScreenOff = false; private int mLastSensorValue = -1; /** @@ -118,6 +119,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi break; } if (newState != DozeMachine.State.FINISH) { + setScreenOff(newState == DozeMachine.State.DOZE); setPaused(newState == DozeMachine.State.DOZE_AOD_PAUSED); } } @@ -135,15 +137,15 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi try { if (mRegistered) { mLastSensorValue = (int) event.values[0]; - updateBrightnessAndReady(); + updateBrightnessAndReady(false /* force */); } } finally { Trace.endSection(); } } - private void updateBrightnessAndReady() { - if (mRegistered || mDebugBrightnessBucket != -1) { + private void updateBrightnessAndReady(boolean force) { + if (force || mRegistered || mDebugBrightnessBucket != -1) { int sensorValue = mDebugBrightnessBucket == -1 ? mLastSensorValue : mDebugBrightnessBucket; int brightness = computeBrightness(sensorValue); @@ -153,7 +155,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi } int scrimOpacity = -1; - if (mPaused) { + 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, @@ -216,13 +218,20 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi private void setPaused(boolean paused) { if (mPaused != paused) { mPaused = paused; - updateBrightnessAndReady(); + updateBrightnessAndReady(false /* force */); + } + } + + private void setScreenOff(boolean screenOff) { + if (mScreenOff != screenOff) { + mScreenOff = screenOff; + updateBrightnessAndReady(true /* force */); } } @Override public void onReceive(Context context, Intent intent) { mDebugBrightnessBucket = intent.getIntExtra(BRIGHTNESS_BUCKET, -1); - updateBrightnessAndReady(); + updateBrightnessAndReady(false /* force */); } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 7189a48fed1f..0fe6611b4274 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -16,6 +16,7 @@ package com.android.systemui.doze; +import android.annotation.Nullable; import android.app.AlarmManager; import android.app.UiModeManager; import android.content.BroadcastReceiver; @@ -147,7 +148,7 @@ public class DozeTriggers implements DozeMachine.Part { boolean wakeEvent = rawValues != null && rawValues.length > 0 && rawValues[0] != 0; if (isWakeDisplay) { - onWakeScreen(wakeEvent, mMachine.getState()); + onWakeScreen(wakeEvent, mMachine.isExecutingTransition() ? null : mMachine.getState()); } else if (isLongPress) { requestPulse(pulseReason, sensorPerformedProxCheck); } else if (isWakeLockScreen) { @@ -168,7 +169,7 @@ public class DozeTriggers implements DozeMachine.Part { } else if (isPickup) { gentleWakeUp(pulseReason); } else { - mDozeHost.extendPulse(); + mDozeHost.extendPulse(pulseReason); } }, sensorPerformedProxCheck || (mDockManager != null && mDockManager.isDocked()), pulseReason); @@ -212,7 +213,8 @@ public class DozeTriggers implements DozeMachine.Part { final boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING); final boolean aod = (state == DozeMachine.State.DOZE_AOD); - if (state == DozeMachine.State.DOZE_PULSING) { + if (state == DozeMachine.State.DOZE_PULSING + || state == DozeMachine.State.DOZE_PULSING_BRIGHT) { boolean ignoreTouch = near; if (DEBUG) Log.i(TAG, "Prox changed, ignore touch = " + ignoreTouch); mDozeHost.onIgnoreTouchWhilePulsing(ignoreTouch); @@ -227,10 +229,14 @@ public class DozeTriggers implements DozeMachine.Part { } } - private void onWakeScreen(boolean wake, DozeMachine.State state) { + /** + * When a wake screen event is received from a sensor + * @param wake {@code true} when it's time to wake up, {@code false} when we should sleep. + * @param state The current state, or null if the state could not be determined due to enqueued + * transitions. + */ + private void onWakeScreen(boolean wake, @Nullable DozeMachine.State state) { DozeLog.traceWakeDisplay(wake); - boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED); - boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING); sWakeDisplaySensorState = wake; if (wake) { @@ -244,6 +250,8 @@ public class DozeTriggers implements DozeMachine.Part { } }, false /* alreadyPerformedProxCheck */, DozeLog.REASON_SENSOR_WAKE_UP); } else { + boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED); + boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING); if (!pausing && !paused) { mMachine.requestState(DozeMachine.State.DOZE); } @@ -276,6 +284,7 @@ public class DozeTriggers implements DozeMachine.Part { mDozeSensors.setListening(false); break; case DOZE_PULSING: + case DOZE_PULSING_BRIGHT: mDozeSensors.setTouchscreenSensorsListening(false); mDozeSensors.setProxListening(true); break; @@ -306,7 +315,16 @@ public class DozeTriggers implements DozeMachine.Part { private void requestPulse(final int reason, boolean performedProxCheck) { Assert.isMainThread(); - mDozeHost.extendPulse(); + mDozeHost.extendPulse(reason); + + // When already pulsing we're allowed to show the wallpaper directly without + // requesting a new pulse. + if (mMachine.getState() == DozeMachine.State.DOZE_PULSING + && reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { + mMachine.requestState(DozeMachine.State.DOZE_PULSING_BRIGHT); + return; + } + if (mPulsePending || !mAllowPulseTriggers || !canPulse()) { if (mAllowPulseTriggers) { DozeLog.tracePulseDropped(mContext, mPulsePending, mMachine.getState(), diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java index 847182d3ad35..51e96d2eecad 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java @@ -94,7 +94,10 @@ public class DozeUi implements DozeMachine.Part { @Override public void onPulseStarted() { try { - mMachine.requestState(DozeMachine.State.DOZE_PULSING); + mMachine.requestState( + reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN + ? DozeMachine.State.DOZE_PULSING_BRIGHT + : DozeMachine.State.DOZE_PULSING); } catch (IllegalStateException e) { // It's possible that the pulse was asynchronously cancelled while // we were waiting for it to start (under stress conditions.) @@ -148,6 +151,7 @@ public class DozeUi implements DozeMachine.Part { switch (state) { case DOZE_REQUEST_PULSE: case DOZE_PULSING: + case DOZE_PULSING_BRIGHT: case DOZE_PULSE_DONE: mHost.setAnimateWakeup(true); break; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java index ca9f24fd236f..1b3cd881b949 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java @@ -38,19 +38,17 @@ public class DozeWallpaperState implements DozeMachine.Part { private final IWallpaperManager mWallpaperManagerService; private final DozeParameters mDozeParameters; - private final DozeMachine mMachine; private boolean mIsAmbientMode; - public DozeWallpaperState(Context context, DozeMachine machine) { - this(machine, IWallpaperManager.Stub.asInterface( + public DozeWallpaperState(Context context) { + this(IWallpaperManager.Stub.asInterface( ServiceManager.getService(Context.WALLPAPER_SERVICE)), DozeParameters.getInstance(context)); } @VisibleForTesting - DozeWallpaperState(DozeMachine machine, IWallpaperManager wallpaperManagerService, + DozeWallpaperState(IWallpaperManager wallpaperManagerService, DozeParameters parameters) { - mMachine = machine; mWallpaperManagerService = wallpaperManagerService; mDozeParameters = parameters; } @@ -65,16 +63,13 @@ public class DozeWallpaperState implements DozeMachine.Part { case DOZE_AOD_PAUSED: case DOZE_REQUEST_PULSE: case DOZE_PULSE_DONE: - isAmbientMode = true; - break; case DOZE_PULSING: - isAmbientMode = - mMachine.getPulseReason() != DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN; + isAmbientMode = true; break; + case DOZE_PULSING_BRIGHT: default: isAmbientMode = false; } - final boolean animated; if (isAmbientMode) { animated = mDozeParameters.shouldControlScreenOff(); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java index b03b872b877f..6f50baa53e38 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java @@ -286,8 +286,9 @@ public class KeyguardSliceProvider extends SliceProvider implements RowBuilder dndBuilder = new RowBuilder(mDndUri) .setContentDescription(getContext().getResources() .getString(R.string.accessibility_quick_settings_dnd)) - .addEndItem(IconCompat.createWithResource(getContext(), R.drawable.stat_sys_dnd), - ListBuilder.ICON_IMAGE); + .addEndItem( + IconCompat.createWithResource(getContext(), R.drawable.stat_sys_dnd), + ListBuilder.ICON_IMAGE); builder.addRow(dndBuilder); } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 676e59428075..d70d0d80c681 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -90,6 +90,7 @@ import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.NotificationPanelView; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; +import com.android.systemui.util.InjectionInflationController; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -710,7 +711,10 @@ public class KeyguardViewMediator extends SystemUI { mContext.registerReceiver(mDelayedLockBroadcastReceiver, delayedActionFilter, SYSTEMUI_PERMISSION, null /* scheduler */); - mKeyguardDisplayManager = new KeyguardDisplayManager(mContext); + InjectionInflationController injectionInflationController = + new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()); + mKeyguardDisplayManager = new KeyguardDisplayManager(mContext, + injectionInflationController); mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); diff --git a/packages/SystemUI/src/com/android/systemui/media/OWNERS b/packages/SystemUI/src/com/android/systemui/media/OWNERS new file mode 100644 index 000000000000..69ea57bfd397 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/OWNERS @@ -0,0 +1 @@ +per-file MediaProjectionPermissionActivity.java = michaelwr@google.com diff --git a/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt b/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt index d7a2d9acf3b5..02ad0f1766bd 100644 --- a/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt +++ b/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt @@ -17,7 +17,8 @@ data class BatteryStateSnapshot( val timeRemainingMillis: Long, val severeThresholdMillis: Long, val lowThresholdMillis: Long, - val isBasedOnUsage: Boolean + val isBasedOnUsage: Boolean, + val isLowWarningEnabled: Boolean ) { /** * Returns whether hybrid warning logic/copy should be used for this snapshot @@ -48,7 +49,8 @@ data class BatteryStateSnapshot( NO_ESTIMATE_AVAILABLE.toLong(), NO_ESTIMATE_AVAILABLE.toLong(), NO_ESTIMATE_AVAILABLE.toLong(), - false + false, + true ) { this.isHybrid = false } diff --git a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java index bd130f4b40f3..a87922792616 100644 --- a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java +++ b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java @@ -23,4 +23,9 @@ public interface EnhancedEstimates { * show a severe warning to the user. */ long getSevereWarningThreshold(); + + /** + * Returns a boolean indicating if the low warning should be shown at all or not. + */ + boolean getLowWarningEnabled(); } diff --git a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java index 3f2417638f1a..bfb809ecbf34 100644 --- a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java @@ -21,4 +21,9 @@ public class EnhancedEstimatesImpl implements EnhancedEstimates { public long getSevereWarningThreshold() { return 0; } + + @Override + public boolean getLowWarningEnabled() { + return true; + } } diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java index 41bcab53f8e9..10f727bc7189 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java @@ -31,6 +31,7 @@ import android.os.Handler; import android.os.Looper; import android.os.PowerManager; import android.os.UserHandle; +import android.provider.Settings.Secure; import android.text.Annotation; import android.text.Layout; import android.text.SpannableString; @@ -70,6 +71,7 @@ import javax.inject.Singleton; */ @Singleton public class PowerNotificationWarnings implements PowerUI.WarningsUI { + private static final String TAG = PowerUI.TAG + ".Notification"; private static final boolean DEBUG = PowerUI.DEBUG; @@ -119,6 +121,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) .build(); + public static final String EXTRA_CONFIRM_ONLY = "extra_confirm_only"; private final Context mContext; private final NotificationManager mNoMan; @@ -544,10 +547,9 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { updateNotification(); } - private void showStartSaverConfirmation() { + private void showStartSaverConfirmation(boolean confirmOnly) { if (mSaverConfirmation != null) return; final SystemUIDialog d = new SystemUIDialog(mContext); - d.setTitle(R.string.battery_saver_confirmation_title); d.setMessage(getBatterySaverDescription()); // Sad hack for http://b/78261259 and http://b/78298335. Otherwise "Battery" may be split @@ -558,9 +560,19 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { // We need to set LinkMovementMethod to make the link clickable. d.setMessageMovementMethod(LinkMovementMethod.getInstance()); - d.setNegativeButton(android.R.string.cancel, null); - d.setPositiveButton(R.string.battery_saver_confirmation_ok, + if (confirmOnly) { + d.setTitle(R.string.battery_saver_confirmation_title_generic); + d.setPositiveButton(com.android.internal.R.string.confirm_battery_saver, + (dialog, which) -> Secure.putInt( + mContext.getContentResolver(), + Secure.LOW_POWER_WARNING_ACKNOWLEDGED, + 1)); + } else { + d.setTitle(R.string.battery_saver_confirmation_title); + d.setPositiveButton(R.string.battery_saver_confirmation_ok, (dialog, which) -> setSaverMode(true, false)); + d.setNegativeButton(android.R.string.cancel, null); + } d.setShowForAllUsers(true); d.setOnDismissListener((dialog) -> mSaverConfirmation = null); d.show(); @@ -719,7 +731,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { dismissLowBatteryNotification(); } else if (action.equals(ACTION_SHOW_START_SAVER_CONFIRMATION)) { dismissLowBatteryNotification(); - showStartSaverConfirmation(); + showStartSaverConfirmation(intent.getBooleanExtra(EXTRA_CONFIRM_ONLY, false)); } else if (action.equals(ACTION_DISMISSED_WARNING)) { dismissLowBatteryWarning(); } else if (ACTION_CLICKED_TEMP_WARNING.equals(action)) { diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index 18638606a251..4e41108f6496 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -284,7 +284,8 @@ public class PowerUI extends SystemUI { plugged, bucket, mBatteryStatus, mLowBatteryReminderLevels[1], mLowBatteryReminderLevels[0], estimate.getEstimateMillis(), mEnhancedEstimates.getSevereWarningThreshold(), - mEnhancedEstimates.getLowWarningThreshold(), estimate.isBasedOnUsage()); + mEnhancedEstimates.getLowWarningThreshold(), estimate.isBasedOnUsage(), + mEnhancedEstimates.getLowWarningEnabled()); } else { if (DEBUG) { Slog.d(TAG, "using standard"); @@ -351,7 +352,6 @@ public class PowerUI extends SystemUI { Slog.d(TAG, "Low warning marked as shown this cycle"); mLowWarningShownThisChargeCycle = true; } - } else if (shouldDismissHybridWarning(currentSnapshot)) { if (DEBUG) { Slog.d(TAG, "Dismissing warning"); @@ -375,8 +375,9 @@ public class PowerUI extends SystemUI { return false; } - // Only show the low warning once per charge cycle & no battery saver - final boolean canShowWarning = !mLowWarningShownThisChargeCycle && !snapshot.isPowerSaver() + // Only show the low warning if enabled once per charge cycle & no battery saver + final boolean canShowWarning = snapshot.isLowWarningEnabled() + && !mLowWarningShownThisChargeCycle && !snapshot.isPowerSaver() && (snapshot.getTimeRemainingMillis() < snapshot.getLowThresholdMillis() || snapshot.getBatteryLevel() <= snapshot.getLowLevelThreshold()); @@ -386,6 +387,7 @@ public class PowerUI extends SystemUI { || snapshot.getBatteryLevel() <= snapshot.getSevereLevelThreshold()); final boolean canShow = canShowWarning || canShowSevereWarning; + if (DEBUG) { Slog.d(TAG, "Enhanced trigger is: " + canShow + "\nwith battery snapshot:" + " mLowWarningShownThisChargeCycle: " + mLowWarningShownThisChargeCycle diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt index 59b3c3464a69..d08a3733703b 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt @@ -53,9 +53,4 @@ class PrivacyDialogBuilder(private val context: Context, itemsList: List<Privacy else -> types.map { it.getName(context) }.joinWithAnd().toString() } } - - fun getDialogTitle(): String { - return context.getString(R.string.ongoing_privacy_dialog_multiple_apps_title, - joinTypes()) - } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index b93f8d04decc..d6e03060c7f7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -118,7 +118,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne updateResources(); mBrightnessController = new BrightnessController(getContext(), - findViewById(R.id.brightness_icon), findViewById(R.id.brightness_slider)); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java index 7c937a944113..b682cb09b598 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java @@ -160,9 +160,9 @@ public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClic int footerIconId = R.drawable.ic_info_outline; if (vpnName != null || vpnNameWorkProfile != null) { if (mSecurityController.isVpnBranded()) { - footerIconId = R.drawable.ic_qs_branded_vpn; + footerIconId = R.drawable.stat_sys_branded_vpn; } else { - footerIconId = R.drawable.ic_qs_vpn; + footerIconId = R.drawable.stat_sys_vpn_ic; } } if (mFooterIconId != footerIconId) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java index 608f646e77a4..8ed5424cf673 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java @@ -113,6 +113,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta public void saveSpecs(QSTileHost host) { List<String> newSpecs = new ArrayList<>(); + clearAccessibilityState(); for (int i = 1; i < mTiles.size() && mTiles.get(i) != null; i++) { newSpecs.add(mTiles.get(i).spec); } @@ -120,6 +121,17 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta mCurrentSpecs = newSpecs; } + private void clearAccessibilityState() { + if (mAccessibilityAction == ACTION_ADD) { + // Remove blank tile from last spot + mTiles.remove(--mEditIndex); + // Update the tile divider position + mTileDividerIndex--; + notifyDataSetChanged(); + } + mAccessibilityAction = ACTION_NONE; + } + public void resetTileSpecs(QSTileHost host, List<String> specs) { // Notify the host so the tiles get removed callbacks. host.changeTiles(mCurrentSpecs, specs); @@ -333,8 +345,6 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta // Remove the placeholder. mTiles.remove(mEditIndex--); notifyItemRemoved(mEditIndex); - // Don't remove items when the last position is selected. - if (position == mEditIndex - 1) position--; } mAccessibilityAction = ACTION_NONE; move(mAccessibilityFromIndex, position, v); @@ -372,6 +382,8 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta mAccessibilityAction = ACTION_ADD; // Add placeholder for last slot. mTiles.add(mEditIndex++, null); + // Update the tile divider position + mTileDividerIndex++; mNeedsFocus = true; notifyDataSetChanged(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java index 387de716844c..19e20a93ce66 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java @@ -43,8 +43,7 @@ import javax.inject.Inject; /** Quick settings tile: Airplane mode **/ public class AirplaneModeTile extends QSTileImpl<BooleanState> { - private final Icon mIcon = - ResourceIcon.get(R.drawable.ic_signal_airplane); + private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_airplane); private final GlobalSetting mSetting; private final ActivityStarter mActivityStarter; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index 5b85498574a7..ca040762047c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -147,14 +147,15 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { state.icon = ResourceIcon.get(R.drawable.ic_bluetooth_transient_animation); state.contentDescription = state.secondaryLabel; } else { - state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_on); + state.icon = + ResourceIcon.get(com.android.internal.R.drawable.ic_qs_bluetooth); state.contentDescription = mContext.getString( R.string.accessibility_quick_settings_bluetooth) + "," + mContext.getString(R.string.accessibility_not_connected); } state.state = Tile.STATE_ACTIVE; } else { - state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_on); + state.icon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_bluetooth); state.contentDescription = mContext.getString( R.string.accessibility_quick_settings_bluetooth); state.state = Tile.STATE_INACTIVE; @@ -288,7 +289,7 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { // This method returns Pair<Drawable, String> while first value is the drawable return BluetoothDeviceLayerDrawable.createLayerDrawable( context, - R.drawable.ic_qs_bluetooth_connected, + R.drawable.ic_bluetooth_connected, mBatteryLevel, mIconScale); } @@ -309,7 +310,7 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { @Override public Drawable getDrawable(Context context) { // This method returns Pair<Drawable, String> - the first value is the drawable. - return context.getDrawable(R.drawable.ic_qs_bluetooth_connected); + return context.getDrawable(R.drawable.ic_bluetooth_connected); } } @@ -383,12 +384,12 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { for (CachedBluetoothDevice device : devices) { if (mController.getBondState(device) == BluetoothDevice.BOND_NONE) continue; final Item item = new Item(); - item.iconResId = R.drawable.ic_qs_bluetooth_on; + item.iconResId = com.android.internal.R.drawable.ic_qs_bluetooth; item.line1 = device.getName(); item.tag = device; int state = device.getMaxConnectionState(); if (state == BluetoothProfile.STATE_CONNECTED) { - item.iconResId = R.drawable.ic_qs_bluetooth_connected; + item.iconResId = R.drawable.ic_bluetooth_connected; int batteryLevel = device.getBatteryLevel(); if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) { item.icon = new BluetoothBatteryTileIcon(batteryLevel,1 /* iconScale */); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index bdebf79d823b..415870c590a3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -202,8 +202,8 @@ public class CastTile extends QSTileImpl<BooleanState> { if (connecting && !state.value) { state.secondaryLabel = mContext.getString(R.string.quick_settings_connecting); } - state.icon = ResourceIcon.get(state.value ? R.drawable.ic_qs_cast_on - : R.drawable.ic_qs_cast_off); + state.icon = ResourceIcon.get(state.value ? R.drawable.ic_cast_connected + : R.drawable.ic_cast); if (mWifiConnected || state.value) { state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; if (!state.value) { @@ -334,7 +334,7 @@ public class CastTile extends QSTileImpl<BooleanState> { for (CastDevice device : devices) { if (device.state == CastDevice.STATE_CONNECTED) { final Item item = new Item(); - item.iconResId = R.drawable.ic_qs_cast_on; + item.iconResId = R.drawable.ic_cast_connected; item.line1 = getDeviceName(device); item.line2 = mContext.getString(R.string.quick_settings_connected); item.tag = device; @@ -354,7 +354,7 @@ public class CastTile extends QSTileImpl<BooleanState> { final CastDevice device = mVisibleOrder.get(id); if (!devices.contains(device)) continue; final Item item = new Item(); - item.iconResId = R.drawable.ic_qs_cast_off; + item.iconResId = R.drawable.ic_cast; item.line1 = getDeviceName(device); if (device.state == CastDevice.STATE_CONNECTING) { item.line2 = mContext.getString(R.string.quick_settings_connecting); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index c587a39f49e3..38962eb14705 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -25,11 +25,7 @@ import android.content.Intent; import android.content.res.Resources; import android.provider.Settings; import android.service.quicksettings.Tile; -import android.text.SpannableString; -import android.text.SpannableStringBuilder; -import android.text.Spanned; import android.text.TextUtils; -import android.text.style.TextAppearanceSpan; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -49,7 +45,6 @@ import com.android.systemui.qs.CellTileView; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.phone.SystemUIDialog; -import com.android.systemui.statusbar.policy.KeyguardMonitor; import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; @@ -66,15 +61,13 @@ public class CellularTile extends QSTileImpl<SignalState> { private final CellSignalCallback mSignalCallback = new CellSignalCallback(); private final ActivityStarter mActivityStarter; - private final KeyguardMonitor mKeyguardMonitor; @Inject public CellularTile(QSHost host, NetworkController networkController, - ActivityStarter activityStarter, KeyguardMonitor keyguardMonitor) { + ActivityStarter activityStarter) { super(host); mController = networkController; mActivityStarter = activityStarter; - mKeyguardMonitor = keyguardMonitor; mDataController = mController.getMobileDataController(); mDetailAdapter = new CellularDetailAdapter(); mController.observe(getLifecycle(), mSignalCallback); @@ -110,11 +103,7 @@ public class CellularTile extends QSTileImpl<SignalState> { return; } if (mDataController.isMobileDataEnabled()) { - if (mKeyguardMonitor.isSecure() && !mKeyguardMonitor.canSkipBouncer()) { - mActivityStarter.postQSRunnableDismissingKeyguard(this::maybeShowDisableDialog); - } else { - mUiHandler.post(this::maybeShowDisableDialog); - } + maybeShowDisableDialog(); } else { mDataController.setMobileDataEnabled(true); } @@ -192,8 +181,10 @@ public class CellularTile extends QSTileImpl<SignalState> { state.secondaryLabel = r.getString(R.string.status_bar_airplane); } else if (mobileDataEnabled) { state.state = Tile.STATE_ACTIVE; - state.secondaryLabel = appendMobileDataType(getMobileDataSubscriptionName(cb), - cb.dataContentDescription); + state.secondaryLabel = appendMobileDataType( + // Only show carrier name if there are more than 1 subscription + cb.multipleSubs ? cb.dataSubscriptionName : "", + getMobileDataContentName(cb)); } else { state.state = Tile.STATE_INACTIVE; state.secondaryLabel = r.getString(R.string.cell_data_off); @@ -216,24 +207,22 @@ public class CellularTile extends QSTileImpl<SignalState> { if (TextUtils.isEmpty(dataType)) { return current; } - SpannableString type = new SpannableString(dataType); - SpannableStringBuilder builder = new SpannableStringBuilder(current); - builder.append(" "); - builder.append(type, new TextAppearanceSpan(mContext, R.style.TextAppearance_RATBadge), - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - return builder; + if (TextUtils.isEmpty(current)) { + return dataType; + } + return mContext.getString(R.string.mobile_carrier_text_format, current, dataType); } - private CharSequence getMobileDataSubscriptionName(CallbackInfo cb) { - if (cb.roaming && !TextUtils.isEmpty(cb.dataSubscriptionName)) { + private CharSequence getMobileDataContentName(CallbackInfo cb) { + if (cb.roaming && !TextUtils.isEmpty(cb.dataContentDescription)) { String roaming = mContext.getString(R.string.data_connection_roaming); - String dataDescription = cb.dataSubscriptionName.toString(); + String dataDescription = cb.dataContentDescription.toString(); return mContext.getString(R.string.mobile_data_text_format, roaming, dataDescription); } if (cb.roaming) { return mContext.getString(R.string.data_connection_roaming); } - return cb.dataSubscriptionName; + return cb.dataContentDescription; } @Override @@ -254,6 +243,7 @@ public class CellularTile extends QSTileImpl<SignalState> { boolean activityOut; boolean noSim; boolean roaming; + boolean multipleSubs; } private final class CellSignalCallback implements SignalCallback { @@ -272,6 +262,7 @@ public class CellularTile extends QSTileImpl<SignalState> { mInfo.activityIn = activityIn; mInfo.activityOut = activityOut; mInfo.roaming = roaming; + mInfo.multipleSubs = mController.getNumberSubscriptions() > 1; refreshState(mInfo); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 7fcd59f7c931..869fa6b18245 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -235,7 +235,7 @@ public class DndTile extends QSTileImpl<BooleanState> { state.label = getTileLabel(); state.secondaryLabel = TextUtils.emptyIfNull(ZenModeConfig.getDescription(mContext, zen != Global.ZEN_MODE_OFF, mController.getConfig(), false)); - state.icon = ResourceIcon.get(R.drawable.ic_dnd); + state.icon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_dnd); checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME); switch (zen) { case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java index dfa3fb9dafc9..2755e9880b58 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java @@ -35,7 +35,7 @@ import javax.inject.Inject; public class FlashlightTile extends QSTileImpl<BooleanState> implements FlashlightController.FlashlightListener { - private final Icon mIcon = ResourceIcon.get(R.drawable.ic_signal_flashlight); + private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_flashlight); private final FlashlightController mFlashlightController; @Inject diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java index a0f4e24d2f93..837ea9fc5f4e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java @@ -37,7 +37,7 @@ import javax.inject.Inject; /** Quick settings tile: Location **/ public class LocationTile extends QSTileImpl<BooleanState> { - private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_signal_location); + private final Icon mIcon = ResourceIcon.get(R.drawable.ic_location); private final LocationController mController; private final KeyguardMonitor mKeyguard; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java index effa935c5c20..241b375ffeaa 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java @@ -19,11 +19,12 @@ package com.android.systemui.qs.tiles; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_QS_MODE; import android.annotation.Nullable; -import android.app.ActivityManager; import android.content.Intent; import android.hardware.display.ColorDisplayManager; import android.hardware.display.NightDisplayListener; import android.metrics.LogMaker; +import android.os.Handler; +import android.os.Looper; import android.provider.Settings; import android.service.quicksettings.Tile; import android.text.TextUtils; @@ -66,7 +67,7 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> implements public NightDisplayTile(QSHost host) { super(host); mManager = mContext.getSystemService(ColorDisplayManager.class); - mListener = new NightDisplayListener(mContext, ActivityManager.getCurrentUser()); + mListener = new NightDisplayListener(mContext, new Handler(Looper.myLooper())); } @Override @@ -102,7 +103,7 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> implements } // Make a new controller for the new user. - mListener = new NightDisplayListener(mContext, newUserId); + mListener = new NightDisplayListener(mContext, newUserId, new Handler(Looper.myLooper())); if (mIsListening) { mListener.setCallback(this); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java index 21f3d6e77f7b..7ca1e44c93cd 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java @@ -36,7 +36,7 @@ import javax.inject.Inject; /** Quick settings tile: Rotation **/ public class RotationLockTile extends QSTileImpl<BooleanState> { - private final Icon mIcon = ResourceIcon.get(R.drawable.ic_qs_auto_rotate); + private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_auto_rotate); private final RotationLockController mController; @Inject diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java index f921eb9a49a6..7853dc388bcb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java @@ -33,7 +33,7 @@ import javax.inject.Inject; /** Quick settings tile: Work profile on/off */ public class WorkModeTile extends QSTileImpl<BooleanState> implements ManagedProfileController.Callback { - private final Icon mIcon = ResourceIcon.get(R.drawable.ic_signal_workmode_disable); + private final Icon mIcon = ResourceIcon.get(R.drawable.stat_sys_managed_profile_status); private final ManagedProfileController mProfileController; diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index 92195942ca06..ead39c69730e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -46,7 +46,6 @@ import android.os.Looper; import android.os.PatternMatcher; import android.os.RemoteException; import android.os.UserHandle; -import android.provider.Settings; import android.util.Log; import android.view.InputChannel; import android.view.MotionEvent; @@ -60,6 +59,7 @@ import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.InputChannelCompat.InputEventDispatcher; +import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.stackdivider.Divider; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.CallbackController; @@ -439,6 +439,9 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis mSupportsRoundedCornersOnWindows = ScreenDecorationsUtils .supportsRoundedCornersOnWindows(mContext.getResources()); + // Assumes device always starts with back button until launcher tells it that it does not + mBackButtonAlpha = 1.0f; + // Listen for the package update changes. if (mDeviceProvisionedController.getCurrentUser() == UserHandle.USER_SYSTEM) { updateEnabledState(); @@ -589,11 +592,9 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis private int getDefaultInteractionFlags() { // If there is no settings available use device default or get it from settings - final boolean defaultState = getSwipeUpDefaultValue(); - final boolean swipeUpEnabled = getSwipeUpSettingAvailable() - ? getSwipeUpEnabledFromSettings(defaultState) - : defaultState; - return swipeUpEnabled ? 0 : DEFAULT_DISABLE_SWIPE_UP_STATE; + return QuickStepContract.isLegacyMode(mContext) + ? DEFAULT_DISABLE_SWIPE_UP_STATE + : 0; } private void notifyBackButtonAlphaChanged(float alpha, boolean animate) { @@ -638,21 +639,6 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis ActivityManagerWrapper.getInstance().getCurrentUserId()) != null; } - private boolean getSwipeUpDefaultValue() { - return mContext.getResources() - .getBoolean(com.android.internal.R.bool.config_swipe_up_gesture_default); - } - - private boolean getSwipeUpSettingAvailable() { - return mContext.getResources() - .getBoolean(com.android.internal.R.bool.config_swipe_up_gesture_setting_available); - } - - private boolean getSwipeUpEnabledFromSettings(boolean defaultValue) { - return Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED, defaultValue ? 1 : 0) == 1; - } - @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(TAG_OPS + " state:"); @@ -665,11 +651,8 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis pw.print(" quickStepIntent="); pw.println(mQuickStepIntent); pw.print(" quickStepIntentResolved="); pw.println(isEnabled()); - - final boolean swipeUpDefaultValue = getSwipeUpDefaultValue(); - final boolean swipeUpEnabled = getSwipeUpEnabledFromSettings(swipeUpDefaultValue); - pw.print(" swipeUpSetting="); pw.println(swipeUpEnabled); - pw.print(" swipeUpSettingDefault="); pw.println(swipeUpDefaultValue); + pw.print(" navBarMode="); + pw.println(QuickStepContract.getCurrentInteractionMode(mContext)); } public interface OverviewProxyListener { diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java index 79228b9c369e..1e0a9f157ff5 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java +++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java @@ -39,7 +39,6 @@ import android.provider.Settings; import android.service.vr.IVrManager; import android.service.vr.IVrStateCallbacks; import android.util.Log; -import android.widget.ImageView; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -50,11 +49,8 @@ import java.util.ArrayList; public class BrightnessController implements ToggleSlider.Listener { private static final String TAG = "StatusBar.BrightnessController"; - private static final boolean SHOW_AUTOMATIC_ICON = false; - private static final int SLIDER_ANIMATION_DURATION = 3000; - private static final int MSG_UPDATE_ICON = 0; private static final int MSG_UPDATE_SLIDER = 1; private static final int MSG_SET_CHECKED = 2; private static final int MSG_ATTACH_LISTENER = 3; @@ -69,7 +65,6 @@ public class BrightnessController implements ToggleSlider.Listener { private final int mDefaultBacklightForVr; private final Context mContext; - private final ImageView mIcon; private final ToggleSlider mControl; private final boolean mAutomaticAvailable; private final DisplayManager mDisplayManager; @@ -193,10 +188,8 @@ public class BrightnessController implements ToggleSlider.Listener { Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT); mAutomatic = automatic != Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL; - mHandler.obtainMessage(MSG_UPDATE_ICON, mAutomatic ? 1 : 0).sendToTarget(); } else { mHandler.obtainMessage(MSG_SET_CHECKED, 0).sendToTarget(); - mHandler.obtainMessage(MSG_UPDATE_ICON, 0 /* automatic */).sendToTarget(); } } }; @@ -237,9 +230,6 @@ public class BrightnessController implements ToggleSlider.Listener { mExternalChange = true; try { switch (msg.what) { - case MSG_UPDATE_ICON: - updateIcon(msg.arg1 != 0); - break; case MSG_UPDATE_SLIDER: updateSlider(msg.arg1, msg.arg2 != 0); break; @@ -264,9 +254,8 @@ public class BrightnessController implements ToggleSlider.Listener { } }; - public BrightnessController(Context context, ImageView icon, ToggleSlider control) { + public BrightnessController(Context context, ToggleSlider control) { mContext = context; - mIcon = icon; mControl = control; mControl.setMax(GAMMA_SPACE_MAX); mBackgroundHandler = new Handler((Looper) Dependency.get(Dependency.BG_LOOPER)); @@ -347,7 +336,6 @@ public class BrightnessController implements ToggleSlider.Listener { @Override public void onChanged(ToggleSlider toggleSlider, boolean tracking, boolean automatic, int value, boolean stopTracking) { - updateIcon(mAutomatic); if (mExternalChange) return; if (mSliderAnimator != null) { @@ -416,18 +404,6 @@ public class BrightnessController implements ToggleSlider.Listener { mDisplayManager.setTemporaryBrightness(brightness); } - private void setBrightnessAdj(float adj) { - mDisplayManager.setTemporaryAutoBrightnessAdjustment(adj); - } - - private void updateIcon(boolean automatic) { - if (mIcon != null) { - mIcon.setImageResource(automatic && SHOW_AUTOMATIC_ICON ? - com.android.systemui.R.drawable.ic_qs_brightness_auto_on : - com.android.systemui.R.drawable.ic_qs_brightness_auto_off); - } - } - private void updateVrMode(boolean isEnabled) { if (mIsVrModeEnabled != isEnabled) { mIsVrModeEnabled = isEnabled; diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java index 0374a013a90c..d8b4df5e94d8 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java +++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java @@ -24,7 +24,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.Window; import android.view.WindowManager; -import android.widget.ImageView; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -49,9 +48,8 @@ public class BrightnessDialog extends Activity { R.layout.quick_settings_brightness_dialog, null); setContentView(v); - final ImageView icon = findViewById(R.id.brightness_icon); final ToggleSliderView slider = findViewById(R.id.brightness_slider); - mBrightnessController = new BrightnessController(this, icon, slider); + mBrightnessController = new BrightnessController(this, slider); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 8faeb155b1e6..a87e50c50f51 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -308,11 +308,23 @@ public class KeyguardIndicationController implements StateListener { // Walk down a precedence-ordered list of what indication // should be shown based on user or device state if (mDozing) { + // When dozing we ignore any text color and use white instead, because + // colors can be hard to read in low brightness. + mTextView.setTextColor(Color.WHITE); if (!TextUtils.isEmpty(mTransientIndication)) { - mTextView.setTextColor(Color.WHITE); mTextView.switchIndication(mTransientIndication); + } else if (mPowerPluggedIn) { + String indication = computePowerIndication(); + if (animate) { + animateText(mTextView, indication); + } else { + mTextView.switchIndication(indication); + } + } else { + String percentage = NumberFormat.getPercentInstance() + .format(mBatteryLevel / 100f); + mTextView.switchIndication(percentage); } - updateAlphas(); return; } @@ -353,14 +365,6 @@ public class KeyguardIndicationController implements StateListener { } } - private void updateAlphas() { - if (!TextUtils.isEmpty(mTransientIndication)) { - mTextView.setAlpha(1f); - } else { - mTextView.setAlpha(1f - mDarkAmount); - } - } - // animates textView - textView moves up and bounces down private void animateText(KeyguardIndicationTextView textView, String indication) { int yTranslation = mContext.getResources().getInteger( @@ -523,14 +527,6 @@ public class KeyguardIndicationController implements StateListener { pw.println(" computePowerIndication(): " + computePowerIndication()); } - public void setDarkAmount(float darkAmount) { - if (mDarkAmount == darkAmount) { - return; - } - mDarkAmount = darkAmount; - updateAlphas(); - } - @Override public void onStateChanged(int newState) { // don't care @@ -675,6 +671,7 @@ public class KeyguardIndicationController implements StateListener { public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) { super.onBiometricAuthenticated(userId, biometricSourceType); mLastSuccessiveErrorMessage = -1; + mHandler.sendEmptyMessage(MSG_HIDE_TRANSIENT); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java index be63bad47d4a..aeaceb0c11e5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java @@ -79,7 +79,7 @@ public class NotificationListener extends NotificationListenerWithPlugins { } }); NotificationManager noMan = mContext.getSystemService(NotificationManager.class); - onStatusBarIconsBehaviorChanged(noMan.shouldHideSilentStatusBarIcons()); + onSilentStatusBarIconsVisibilityChanged(noMan.shouldHideSilentStatusBarIcons()); } @Override @@ -144,7 +144,7 @@ public class NotificationListener extends NotificationListenerWithPlugins { } @Override - public void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) { + public void onSilentStatusBarIconsVisibilityChanged(boolean hideSilentStatusIcons) { for (NotificationSettingsListener listener : mSettingsListeners) { listener.onStatusBarIconsBehaviorChanged(hideSilentStatusIcons); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java index cb9060bc9574..cf6e64cef365 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java @@ -289,4 +289,9 @@ public class ScrimView extends View implements ConfigurationController.Configura } } } + + @Override + protected boolean canReceivePointerEvents() { + return false; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 9630727c8f3d..d287b92876b5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -552,6 +552,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mEntry.mIsSystemNotification = isSystemNotification(mContext, mStatusBarNotification); } + isNonblockable |= mEntry.channel.isImportanceLockedByOEM(); + isNonblockable |= mEntry.channel.isImportanceLockedByCriticalDeviceFunction(); + if (!isNonblockable && mEntry != null && mEntry.mIsSystemNotification != null) { if (mEntry.mIsSystemNotification) { if (mEntry.channel != null 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 520df9797cc3..ce206816bf1d 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 @@ -399,7 +399,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd private final ViewOutlineProvider mOutlineProvider = new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { - if (mAmbientState.isDarkAtAll() && !mAmbientState.isFullyDark()) { + if (mAmbientState.isDarkAtAll() && !mAmbientState.isFullyDark() || !mShowDarkShelf) { outline.setRoundRect(mBackgroundAnimationRect, mCornerRadius); } else { ViewOutlineProvider.BACKGROUND.getOutline(view, outline); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java index 79056175b595..211a40a91101 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java @@ -70,7 +70,7 @@ public class BarTransitions { private final String mTag; private final View mView; - private final BarBackgroundDrawable mBarBackground; + protected final BarBackgroundDrawable mBarBackground; private int mMode; private boolean mAlwaysOpaque = false; @@ -152,7 +152,7 @@ public class BarTransitions { return mode == MODE_LIGHTS_OUT || mode == MODE_LIGHTS_OUT_TRANSPARENT; } - private static class BarBackgroundDrawable extends Drawable { + protected static class BarBackgroundDrawable extends Drawable { private final int mOpaque; private final int mSemiTransparent; private final int mTransparent; @@ -171,6 +171,7 @@ public class BarTransitions { private int mGradientAlphaStart; private int mColorStart; + private Rect mFrame; public BarBackgroundDrawable(Context context, int gradientResourceId) { @@ -190,6 +191,10 @@ public class BarTransitions { mGradient = context.getDrawable(gradientResourceId); } + public void setFrame(Rect frame) { + mFrame = frame; + } + @Override public void setAlpha(int alpha) { // noop @@ -296,7 +301,11 @@ public class BarTransitions { if (mTintFilter != null) { mPaint.setColorFilter(mTintFilter); } - canvas.drawPaint(mPaint); + if (mFrame != null) { + canvas.drawRect(mFrame, mPaint); + } else { + canvas.drawPaint(mPaint); + } } if (mAnimating) { invalidateSelf(); // keep going diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java index 08a10dc925e3..ac58e681dbbc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java @@ -36,7 +36,8 @@ import javax.inject.Singleton; /** */ @Singleton -public class DarkIconDispatcherImpl implements SysuiDarkIconDispatcher { +public class DarkIconDispatcherImpl implements SysuiDarkIconDispatcher, + LightBarTransitionsController.DarkIntensityApplier { private final LightBarTransitionsController mTransitionsController; private final Rect mTintArea = new Rect(); @@ -54,8 +55,7 @@ public class DarkIconDispatcherImpl implements SysuiDarkIconDispatcher { mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone); mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone); - mTransitionsController = new LightBarTransitionsController(context, - this::setIconTintInternal); + mTransitionsController = new LightBarTransitionsController(context, this); } public LightBarTransitionsController getTransitionsController() { @@ -104,13 +104,19 @@ public class DarkIconDispatcherImpl implements SysuiDarkIconDispatcher { applyIconTint(); } - private void setIconTintInternal(float darkIntensity) { + @Override + public void applyDarkIntensity(float darkIntensity) { mDarkIntensity = darkIntensity; mIconTint = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, mLightModeIconColorSingleTone, mDarkModeIconColorSingleTone); applyIconTint(); } + @Override + public int getTintAnimationDuration() { + return LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION; + } + private void applyIconTint() { for (int i = 0; i < mReceivers.size(); i++) { mReceivers.valueAt(i).onDarkChanged(mTintArea, mDarkIntensity, mIconTint); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java index 236c72c5cc2c..0731a568ae7d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java @@ -108,16 +108,13 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da } String zen = args.getString("zen"); if (zen != null) { - int iconId = zen.equals("important") ? R.drawable.stat_sys_zen_important - : zen.equals("none") ? R.drawable.stat_sys_zen_none - : 0; + int iconId = zen.equals("dnd") ? R.drawable.stat_sys_dnd : 0; updateSlot("zen", null, iconId); } String bt = args.getString("bluetooth"); if (bt != null) { - int iconId = bt.equals("disconnected") ? R.drawable.stat_sys_data_bluetooth - : bt.equals("connected") ? R.drawable.stat_sys_data_bluetooth_connected - : 0; + int iconId = bt.equals("connected") + ? R.drawable.stat_sys_data_bluetooth_connected : 0; updateSlot("bluetooth", null, iconId); } String location = args.getString("location"); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java index 9844d8e5a67a..b7a154d67c10 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java @@ -140,7 +140,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, mHeadsUpInset = mStatusBarHeight + resources.getDimensionPixelSize( R.dimen.heads_up_status_bar_padding); mDisplayCutoutTouchableRegionSize = resources.getDimensionPixelSize( - R.dimen.display_cutout_touchable_region_size); + com.android.internal.R.dimen.display_cutout_touchable_region_size); } @Override 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 847f3ff9f24d..a924680b7043 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; +import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTTON; import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK; import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON; @@ -67,6 +68,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.systemui.ActivityIntentHelper; import com.android.systemui.Dependency; import com.android.systemui.Interpolators; import com.android.systemui.R; @@ -121,6 +123,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private KeyguardAffordanceView mRightAffordanceView; private KeyguardAffordanceView mLeftAffordanceView; private LockIcon mLockIcon; + private ViewGroup mLockIconContainer; private ViewGroup mIndicationArea; private TextView mEnterpriseDisclosure; private TextView mIndicationText; @@ -170,6 +173,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private boolean mDozing; private int mIndicationBottomMargin; private float mDarkAmount; + private int mBurnInXOffset; + private int mBurnInYOffset; + private ActivityIntentHelper mActivityIntentHelper; public KeyguardBottomAreaView(Context context) { this(context, null); @@ -235,17 +241,22 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL protected void onFinishInflate() { super.onFinishInflate(); mLockPatternUtils = new LockPatternUtils(mContext); + mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext), + new ActivityIntentHelper(mContext)); mPreviewContainer = findViewById(R.id.preview_container); mOverlayContainer = findViewById(R.id.overlay_container); mRightAffordanceView = findViewById(R.id.camera_button); mLeftAffordanceView = findViewById(R.id.left_button); mLockIcon = findViewById(R.id.lock_icon); + mLockIconContainer = findViewById(R.id.lock_icon_container); mIndicationArea = findViewById(R.id.keyguard_indication_area); mEnterpriseDisclosure = findViewById( R.id.keyguard_indication_enterprise_disclosure); mIndicationText = findViewById(R.id.keyguard_indication_text); mIndicationBottomMargin = getResources().getDimensionPixelSize( R.dimen.keyguard_indication_margin_bottom); + mBurnInYOffset = getResources().getDimensionPixelSize( + R.dimen.default_burn_in_prevention_offset); updateCameraVisibility(); mUnlockMethodCache = UnlockMethodCache.getInstance(getContext()); mUnlockMethodCache.addListener(this); @@ -254,7 +265,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mLockIcon.update(); setClipChildren(false); setClipToPadding(false); - mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext)); inflateCameraPreview(); mLockIcon.setOnClickListener(this); mLockIcon.setOnLongClickListener(this); @@ -266,6 +276,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mAccessibilityController = Dependency.get(AccessibilityController.class); mAssistManager = Dependency.get(AssistManager.class); mLockIcon.setAccessibilityController(mAccessibilityController); + mActivityIntentHelper = new ActivityIntentHelper(getContext()); updateLeftAffordance(); } @@ -315,6 +326,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL super.onConfigurationChanged(newConfig); mIndicationBottomMargin = getResources().getDimensionPixelSize( R.dimen.keyguard_indication_margin_bottom); + mBurnInYOffset = getResources().getDimensionPixelSize( + R.dimen.default_burn_in_prevention_offset); MarginLayoutParams mlp = (MarginLayoutParams) mIndicationArea.getLayoutParams(); if (mlp.bottomMargin != mIndicationBottomMargin) { mlp.bottomMargin = mIndicationBottomMargin; @@ -459,7 +472,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL public void bindCameraPrewarmService() { Intent intent = getCameraIntent(); - ActivityInfo targetInfo = PreviewInflater.getTargetActivityInfo(mContext, intent, + ActivityInfo targetInfo = mActivityIntentHelper.getTargetActivityInfo(intent, KeyguardUpdateMonitor.getCurrentUser(), true /* onlyDirectBootAware */); if (targetInfo != null && targetInfo.metaData != null) { String clazz = targetInfo.metaData.getString( @@ -500,8 +513,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL public void launchCamera(String source) { final Intent intent = getCameraIntent(); intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source); - boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity( - mContext, intent, KeyguardUpdateMonitor.getCurrentUser()); + boolean wouldLaunchResolverActivity = mActivityIntentHelper.wouldLaunchResolverActivity( + intent, KeyguardUpdateMonitor.getCurrentUser()); if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) { AsyncTask.execute(new Runnable() { @Override @@ -558,8 +571,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL return; } mDarkAmount = darkAmount; - mIndicationController.setDarkAmount(darkAmount); mLockIcon.setDarkAmount(darkAmount); + dozeTimeTick(); } /** @@ -653,6 +666,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL return mLockIcon; } + public ViewGroup getLockIconContainer() { + return mLockIconContainer; + } + public View getIndicationArea() { return mIndicationArea; } @@ -831,6 +848,20 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } } + public void dozeTimeTick() { + int burnInYOffset = getBurnInOffset(mBurnInYOffset * 2, false /* xAxis */) + - mBurnInYOffset; + mIndicationArea.setTranslationY(burnInYOffset * mDarkAmount); + } + + public void setAntiBurnInOffsetX(int burnInXOffset) { + if (mBurnInXOffset == burnInXOffset) { + return; + } + mBurnInXOffset = burnInXOffset; + mIndicationArea.setTranslationX(burnInXOffset); + } + /** * Sets the alpha of the indication areas and affordances, excluding the lock icon. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index fe3a455302d4..5afff814c111 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -123,6 +123,7 @@ public class KeyguardBouncer { return; } ensureView(); + mIsScrimmed = isScrimmed; // On the keyguard, we want to show the bouncer when the user drags up, but it's // not correct to end the falsing session. We still need to verify if those touches @@ -132,13 +133,13 @@ public class KeyguardBouncer { if (isScrimmed) { setExpansion(EXPANSION_VISIBLE); } - mIsScrimmed = isScrimmed; if (resetSecuritySelection) { // showPrimarySecurityScreen() updates the current security method. This is needed in // case we are already showing and the current security method changed. showPrimarySecurityScreen(); } + if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) { return; } @@ -168,8 +169,8 @@ public class KeyguardBouncer { mCallback.onBouncerVisiblityChanged(true /* shown */); } - public boolean isShowingScrimmed() { - return isShowing() && mIsScrimmed; + public boolean isScrimmed() { + return mIsScrimmed; } public ViewGroup getLockIconContainer() { @@ -281,6 +282,7 @@ public class KeyguardBouncer { StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN); mDismissCallbackRegistry.notifyDismissCancelled(); } + mIsScrimmed = false; mFalsingManager.onBouncerHidden(); mCallback.onBouncerVisiblityChanged(false /* shown */); cancelShowRunnable(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java index 4c50d07aa6ea..2bd8d41a24e3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java @@ -17,7 +17,6 @@ package com.android.systemui.statusbar.phone; import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFromDirection; -import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; import android.annotation.ColorInt; import android.content.Context; @@ -102,19 +101,6 @@ public class KeyguardStatusBarView extends RelativeLayout */ private int mCutoutSideNudge = 0; - /** - * How much to move icons to avoid burn in. - */ - private int mBurnInOffset; - private int mCurrentBurnInOffsetX; - private int mCurrentBurnInOffsetY; - - /** - * Ratio representing being in ambient mode or not. - */ - private float mDarkAmount; - private boolean mDozing; - public KeyguardStatusBarView(Context context, AttributeSet attrs) { super(context, attrs); } @@ -186,8 +172,6 @@ public class KeyguardStatusBarView extends RelativeLayout R.dimen.system_icons_super_container_avatarless_margin_end); mCutoutSideNudge = getResources().getDimensionPixelSize( R.dimen.display_cutout_margin_consumption); - mBurnInOffset = getResources().getDimensionPixelSize( - R.dimen.default_burn_in_prevention_offset); mShowPercentAvailable = getContext().getResources().getBoolean( com.android.internal.R.bool.config_battery_percentage_setting_available); } @@ -211,7 +195,7 @@ public class KeyguardStatusBarView extends RelativeLayout mMultiUserSwitch.setVisibility(View.GONE); } } - mBatteryView.setForceShowPercent(mBatteryCharging && mShowPercentAvailable || mDozing); + mBatteryView.setForceShowPercent(mBatteryCharging && mShowPercentAvailable); } private void updateSystemIconsLayoutParams() { @@ -348,7 +332,6 @@ public class KeyguardStatusBarView extends RelativeLayout mIconManager = new TintedIconManager(findViewById(R.id.statusIcons)); Dependency.get(StatusBarIconController.class).addIconGroup(mIconManager); onThemeChanged(); - updateDarkState(); } @Override @@ -492,7 +475,7 @@ public class KeyguardStatusBarView extends RelativeLayout mIconManager.setTint(iconColor); } - applyDarkness(R.id.battery, mEmptyRect, intensity * (1f - mDarkAmount), iconColor); + applyDarkness(R.id.battery, mEmptyRect, intensity, iconColor); applyDarkness(R.id.clock, mEmptyRect, intensity, iconColor); } @@ -513,48 +496,4 @@ public class KeyguardStatusBarView extends RelativeLayout mBatteryView.dump(fd, pw, args); } } - - public void setDozing(boolean dozing) { - if (mDozing == dozing) { - return; - } - mDozing = dozing; - setClipChildren(!dozing); - setClipToPadding(!dozing); - updateVisibilities(); - } - - public void setDarkAmount(float darkAmount) { - mDarkAmount = darkAmount; - if (darkAmount == 0) { - dozeTimeTick(); - } - updateDarkState(); - } - - public void dozeTimeTick() { - mCurrentBurnInOffsetX = getBurnInOffset(mBurnInOffset, true /* xAxis */); - mCurrentBurnInOffsetY = getBurnInOffset(mBurnInOffset, false /* xAxis */); - updateDarkState(); - } - - private void updateDarkState() { - float alpha = 1f - mDarkAmount; - int visibility = alpha != 0f ? VISIBLE : INVISIBLE; - mCarrierLabel.setAlpha(alpha * alpha); - mStatusIconContainer.setAlpha(alpha); - mStatusIconContainer.setVisibility(visibility); - - float iconsX = -mCurrentBurnInOffsetX; - if (mMultiUserSwitch.getVisibility() == VISIBLE) { - // Squared alpha to add a nice easing curve and avoid overlap during animation. - mMultiUserAvatar.setAlpha(alpha * alpha); - iconsX += mMultiUserAvatar.getPaddingLeft() + mMultiUserAvatar.getWidth() - + mMultiUserAvatar.getPaddingRight(); - } - mSystemIconsContainer.setTranslationX(iconsX * mDarkAmount); - mSystemIconsContainer.setTranslationY(mCurrentBurnInOffsetY * mDarkAmount); - updateIconsAndTextColors(); - } - } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java index b622688a8ac6..d7097309ce20 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java @@ -16,9 +16,6 @@ package com.android.systemui.statusbar.phone; -import static com.android.systemui.statusbar.phone.NavBarTintController.DEFAULT_COLOR_ADAPT_TRANSITION_TIME; -import static com.android.systemui.statusbar.phone.NavBarTintController.MIN_COLOR_ADAPT_TRANSITION_TIME; - import android.animation.ValueAnimator; import android.content.Context; import android.os.Bundle; @@ -52,7 +49,6 @@ public class LightBarTransitionsController implements Dumpable, Callbacks, private final DarkIntensityApplier mApplier; private final KeyguardMonitor mKeyguardMonitor; private final StatusBarStateController mStatusBarStateController; - private NavBarTintController mColorAdaptionController; private boolean mTransitionDeferring; private long mTransitionDeferringStartTime; @@ -118,7 +114,8 @@ public class LightBarTransitionsController implements Dumpable, Callbacks, } if (mTransitionPending && mTintChangePending) { mTintChangePending = false; - animateIconTint(mPendingDarkIntensity, 0 /* delay */, getTintAnimationDuration()); + animateIconTint(mPendingDarkIntensity, 0 /* delay */, + mApplier.getTintAnimationDuration()); } mTransitionPending = false; } @@ -159,15 +156,8 @@ public class LightBarTransitionsController implements Dumpable, Callbacks, Math.max(0, mTransitionDeferringStartTime - SystemClock.uptimeMillis()), mTransitionDeferringDuration); } else { - animateIconTint(dark ? 1.0f : 0.0f, 0 /* delay */, getTintAnimationDuration()); - } - } - - public long getTintAnimationDuration() { - if (NavBarTintController.isEnabled(mContext)) { - return Math.max(DEFAULT_COLOR_ADAPT_TRANSITION_TIME, MIN_COLOR_ADAPT_TRANSITION_TIME); + animateIconTint(dark ? 1.0f : 0.0f, 0 /* delay */, mApplier.getTintAnimationDuration()); } - return DEFAULT_TINT_ANIMATION_DURATION; } public float getCurrentDarkIntensity() { @@ -243,5 +233,6 @@ public class LightBarTransitionsController implements Dumpable, Callbacks, */ public interface DarkIntensityApplier { void applyDarkIntensity(float darkIntensity); + int getTintAnimationDuration(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java index 2d54970cdfa8..bf5b60a9437b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java @@ -19,12 +19,16 @@ package com.android.systemui.statusbar.phone; import static android.view.Display.DEFAULT_DISPLAY; import android.content.Context; +import android.content.res.Resources; +import android.graphics.Point; import android.graphics.Rect; import android.os.Handler; -import android.provider.Settings; import android.view.CompositionSamplingListener; import android.view.View; +import com.android.systemui.R; +import com.android.systemui.shared.system.QuickStepContract; + import java.io.PrintWriter; /** @@ -36,9 +40,6 @@ public class NavBarTintController implements View.OnAttachStateChangeListener, public static final int MIN_COLOR_ADAPT_TRANSITION_TIME = 400; public static final int DEFAULT_COLOR_ADAPT_TRANSITION_TIME = 1700; - // Passing the threshold of this luminance value will make the button black otherwise white - private static final float LUMINANCE_THRESHOLD = 0.3f; - private final Handler mHandler = new Handler(); private final NavigationBarView mNavigationBarView; private final LightBarTransitionsController mLightBarController; @@ -49,9 +50,17 @@ public class NavBarTintController implements View.OnAttachStateChangeListener, private boolean mSamplingEnabled = false; private boolean mSamplingListenerRegistered = false; - private float mLastMediaLuma; + private float mLastMedianLuma; + private float mCurrentMedianLuma; private boolean mUpdateOnNextDraw; + private final int mNavBarHeight; + private final int mNavColorSampleMargin; + + // Passing the threshold of this luminance value will make the button black otherwise white + private final float mLuminanceThreshold; + private final float mLuminanceChangeThreshold; + public NavBarTintController(NavigationBarView navigationBarView, LightBarTransitionsController lightBarController) { mSamplingListener = new CompositionSamplingListener( @@ -65,6 +74,13 @@ public class NavBarTintController implements View.OnAttachStateChangeListener, mNavigationBarView.addOnAttachStateChangeListener(this); mNavigationBarView.addOnLayoutChangeListener(this); mLightBarController = lightBarController; + + final Resources res = navigationBarView.getResources(); + mNavBarHeight = res.getDimensionPixelSize(R.dimen.navigation_bar_height); + mNavColorSampleMargin = + res.getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin); + mLuminanceThreshold = res.getFloat(R.dimen.navigation_luminance_threshold); + mLuminanceChangeThreshold = res.getFloat(R.dimen.navigation_luminance_change_threshold); } void onDraw() { @@ -108,8 +124,11 @@ public class NavBarTintController implements View.OnAttachStateChangeListener, if (view != null) { int[] pos = new int[2]; view.getLocationOnScreen(pos); - final Rect samplingBounds = new Rect(pos[0], pos[1], - pos[0] + view.getWidth(), pos[1] + view.getHeight()); + Point displaySize = new Point(); + view.getContext().getDisplay().getRealSize(displaySize); + final Rect samplingBounds = new Rect(pos[0] - mNavColorSampleMargin, + displaySize.y - mNavBarHeight, pos[0] + view.getWidth() + mNavColorSampleMargin, + displaySize.y); if (!samplingBounds.equals(mSamplingBounds)) { mSamplingBounds.set(samplingBounds); requestUpdateSamplingListener(); @@ -143,13 +162,19 @@ public class NavBarTintController implements View.OnAttachStateChangeListener, } private void updateTint(float medianLuma) { - mLastMediaLuma = medianLuma; - if (medianLuma > LUMINANCE_THRESHOLD) { - // Black - mLightBarController.setIconsDark(true /* dark */, true /* animate */); - } else { - // White - mLightBarController.setIconsDark(false /* dark */, true /* animate */); + mLastMedianLuma = medianLuma; + + // If the difference between the new luma and the current luma is larger than threshold + // then apply the current luma, this is to prevent small changes causing colors to flicker + if (Math.abs(mCurrentMedianLuma - mLastMedianLuma) > mLuminanceChangeThreshold) { + if (medianLuma > mLuminanceThreshold) { + // Black + mLightBarController.setIconsDark(true /* dark */, true /* animate */); + } else { + // White + mLightBarController.setIconsDark(false /* dark */, true /* animate */); + } + mCurrentMedianLuma = medianLuma; } } @@ -161,14 +186,12 @@ public class NavBarTintController implements View.OnAttachStateChangeListener, : "false")); pw.println(" mSamplingListenerRegistered: " + mSamplingListenerRegistered); pw.println(" mSamplingBounds: " + mSamplingBounds); - pw.println(" mLastMediaLuma: " + mLastMediaLuma); + pw.println(" mLastMedianLuma: " + mLastMedianLuma); + pw.println(" mCurrentMedianLuma: " + mCurrentMedianLuma); } public static boolean isEnabled(Context context) { return context.getDisplayId() == DEFAULT_DISPLAY - && Settings.Global.getInt(context.getContentResolver(), - NavigationPrototypeController.NAV_COLOR_ADAPT_ENABLE_SETTING, 0) == 1 - && Settings.Global.getInt(context.getContentResolver(), - NavigationPrototypeController.SHOW_HOME_HANDLE_SETTING, 0) == 1; + && QuickStepContract.isGesturalMode(context); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java index 1478a0780eb7..c77b16b23e67 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java @@ -71,7 +71,7 @@ public class NavigationBackAction extends NavigationGestureAction { @Override protected void onGestureStart(MotionEvent event) { - if (!QuickStepController.shouldhideBackButton(getContext())) { + if (!QuickStepController.shouldHideBackButton(getContext())) { mNavigationBarView.getBackButton().setAlpha(0 /* alpha */, true /* animate */, BACK_BUTTON_FADE_OUT_ALPHA); } @@ -85,7 +85,7 @@ public class NavigationBackAction extends NavigationGestureAction { @Override protected void onGestureEnd() { mHandler.removeCallbacks(mExecuteBackRunnable); - if (!QuickStepController.shouldhideBackButton(getContext())) { + if (!QuickStepController.shouldHideBackButton(getContext())) { mNavigationBarView.getBackButton().setAlpha( mProxySender.getBackButtonAlpha(), true /* animate */); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java index 4c7fdb0a6a7a..48974649191a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarEdgePanel.java @@ -108,7 +108,7 @@ public class NavigationBarEdgePanel extends View { public static NavigationBarEdgePanel create(@NonNull Context context, int width, int height, int gravity) { final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(width, height, - WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, + WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 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 ea30451175d4..94856234503c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java @@ -201,7 +201,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback @Override public void onBackButtonAlphaChanged(float alpha, boolean animate) { final ButtonDispatcher backButton = mNavigationBarView.getBackButton(); - if (QuickStepController.shouldhideBackButton(getContext())) { + if (QuickStepController.shouldHideBackButton(getContext())) { // If property was changed to hide/show back button, going home will trigger // launcher to to change the back button alpha to reflect property change backButton.setVisibility(View.GONE); @@ -988,11 +988,11 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback if (Intent.ACTION_SCREEN_ON.equals(action)) { // Enabled and screen is on, start it again if enabled if (NavBarTintController.isEnabled(getContext())) { - mNavigationBarView.getColorAdaptionController().start(); + mNavigationBarView.getTintController().start(); } } else { // Screen off disable it - mNavigationBarView.getColorAdaptionController().stop(); + mNavigationBarView.getTintController().stop(); } } if (Intent.ACTION_USER_SWITCHED.equals(action)) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java index faa2ab105816..26aa617db167 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java @@ -38,6 +38,7 @@ import com.android.systemui.plugins.PluginListener; import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.shared.plugins.PluginManager; +import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.phone.ReverseLinearLayout.ReverseRelativeLayout; import com.android.systemui.statusbar.policy.KeyButtonView; import com.android.systemui.tuner.TunerService; @@ -136,10 +137,12 @@ public class NavigationBarInflaterView extends FrameLayout } protected String getDefaultLayout() { - final int defaultResource = mOverviewProxyService.shouldShowSwipeUpUI() - ? R.string.config_navBarLayoutQuickstep - : R.string.config_navBarLayout; - return mContext.getString(defaultResource); + final int defaultResource = QuickStepContract.isGesturalMode(getContext()) + ? R.string.config_navBarLayoutHandle + : mOverviewProxyService.shouldShowSwipeUpUI() + ? R.string.config_navBarLayoutQuickstep + : R.string.config_navBarLayout; + return getContext().getString(defaultResource); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java index 3984405f8e09..8ff6cc9b3d93 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java @@ -16,7 +16,11 @@ package com.android.systemui.statusbar.phone; +import static com.android.systemui.statusbar.phone.NavBarTintController.DEFAULT_COLOR_ADAPT_TRANSITION_TIME; +import static com.android.systemui.statusbar.phone.NavBarTintController.MIN_COLOR_ADAPT_TRANSITION_TIME; + import android.content.Context; +import android.graphics.Rect; import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; @@ -30,7 +34,8 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.Dependency; import com.android.systemui.R; -public final class NavigationBarTransitions extends BarTransitions { +public final class NavigationBarTransitions extends BarTransitions implements + LightBarTransitionsController.DarkIntensityApplier { private final NavigationBarView mView; private final IStatusBarService mBarService; @@ -58,8 +63,7 @@ public final class NavigationBarTransitions extends BarTransitions { mView = view; mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); - mLightTransitionsController = new LightBarTransitionsController(view.getContext(), - this::applyDarkIntensity); + mLightTransitionsController = new LightBarTransitionsController(view.getContext(), this); mAllowAutoDimWallpaperNotVisible = view.getContext().getResources() .getBoolean(R.bool.config_navigation_bar_enable_auto_dim_no_visible_wallpaper); @@ -105,6 +109,10 @@ public final class NavigationBarTransitions extends BarTransitions { applyLightsOut(true, false); } + void setBackgroundFrame(Rect frame) { + mBarBackground.setFrame(frame); + } + @Override protected boolean isLightsOut(int mode) { return super.isLightsOut(mode) || (mAllowAutoDimWallpaperNotVisible && mAutoDim @@ -119,6 +127,7 @@ public final class NavigationBarTransitions extends BarTransitions { protected void onTransition(int oldMode, int newMode, boolean animate) { super.onTransition(oldMode, newMode, animate); applyLightsOut(animate, false /*force*/); + mView.onBarTransition(newMode); } private void applyLightsOut(boolean animate, boolean force) { @@ -164,4 +173,12 @@ public final class NavigationBarTransitions extends BarTransitions { } mView.onDarkIntensityChange(darkIntensity); } + + @Override + public int getTintAnimationDuration() { + if (NavBarTintController.isEnabled(mView.getContext())) { + return Math.max(DEFAULT_COLOR_ADAPT_TRANSITION_TIME, MIN_COLOR_ADAPT_TRANSITION_TIME); + } + return LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index ef82b3402b15..f22ecf6792bc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone; +import static android.content.Intent.ACTION_OVERLAY_CHANGED; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID; import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT; @@ -29,6 +30,7 @@ import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE; import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW; import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ROTATION; +import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE; import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_VIEWS; import android.animation.LayoutTransition; @@ -41,7 +43,10 @@ import android.annotation.DrawableRes; import android.annotation.IntDef; import android.annotation.SuppressLint; import android.app.StatusBarManager; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ParceledListSlice; import android.content.res.Configuration; import android.graphics.Canvas; @@ -50,8 +55,6 @@ import android.graphics.Rect; import android.graphics.Region; import android.graphics.Region.Op; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; import android.os.RemoteException; import android.os.SystemProperties; import android.util.AttributeSet; @@ -90,6 +93,7 @@ import com.android.systemui.recents.RecentsOnboarding; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.NavigationBarCompat; +import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.systemui.statusbar.phone.NavigationPrototypeController.GestureAction; import com.android.systemui.statusbar.phone.NavigationPrototypeController.OnPrototypeChangedListener; @@ -150,10 +154,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav private final NavigationBarTransitions mBarTransitions; private final OverviewProxyService mOverviewProxyService; - // workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288) - final static boolean WORKAROUND_INVALID_LAYOUT = true; - final static int MSG_CHECK_INVALID_LAYOUT = 8686; - // performs manual animation in sync with layout transitions private final NavTransitionListener mTransitionListener = new NavTransitionListener(); @@ -173,7 +173,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav private RecentsOnboarding mRecentsOnboarding; private NotificationPanelView mPanelView; - private NavBarTintController mColorAdaptionController; + private NavBarTintController mTintController; private boolean mAssistantAvailable; private NavigationPrototypeController mPrototypeController; private NavigationGestureAction[] mDefaultGestureMap; @@ -260,29 +260,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } }; - private class H extends Handler { - public void handleMessage(Message m) { - switch (m.what) { - case MSG_CHECK_INVALID_LAYOUT: - final String how = "" + m.obj; - final int w = getWidth(); - final int h = getHeight(); - final int vw = getCurrentView().getWidth(); - final int vh = getCurrentView().getHeight(); - - if (h != vh || w != vw) { - Log.w(TAG, String.format( - "*** Invalid layout in navigation bar (%s this=%dx%d cur=%dx%d)", - how, w, h, vw, vh)); - if (WORKAROUND_INVALID_LAYOUT) { - requestLayout(); - } - } - break; - } - } - } - private final AccessibilityDelegate mQuickStepAccessibilityDelegate = new AccessibilityDelegate() { private AccessibilityAction mToggleOverviewAction; @@ -309,6 +286,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } }; + // TODO(b/112934365): To be removed private OnPrototypeChangedListener mPrototypeListener = new OnPrototypeChangedListener() { @Override public void onGestureRemap(int[] actions) { @@ -318,21 +296,23 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav @Override public void onBackButtonVisibilityChanged(boolean visible) { if (!inScreenPinning()) { - getBackButton().setVisibility(visible ? VISIBLE : GONE); + getBackButton().setVisibility(QuickStepController.shouldHideBackButton(getContext()) + ? GONE : VISIBLE); } } @Override public void onHomeButtonVisibilityChanged(boolean visible) { - getHomeButton().setVisibility(visible ? VISIBLE : GONE); + getHomeButton().setVisibility(QuickStepController.shouldHideHomeButton(getContext()) + ? GONE : VISIBLE); } @Override public void onColorAdaptChanged(boolean enabled) { if (enabled) { - mColorAdaptionController.start(); + mTintController.start(); } else { - mColorAdaptionController.stop(); + mTintController.stop(); } } @@ -348,7 +328,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav @Override public void onHomeHandleVisiblilityChanged(boolean visible) { - showHomeHandle(visible); + showHomeHandle(QuickStepController.showHomeHandle(getContext())); } @Override @@ -367,8 +347,11 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav post(() -> { // When the ime changes visibility, resize the edge panels to not cover the ime final int width = mPrototypeController.getEdgeSensitivityWidth(); - final int height = mContext.getDisplay().getHeight() - imeHeight - - getResources().getDimensionPixelOffset(R.dimen.status_bar_height); + int height = mContext.getDisplay().getHeight() - imeHeight; + if (!imeVisible) { + // Hide the navigation bar area at the bottom for gestures + height -= getResources().getDimensionPixelOffset(R.dimen.navigation_bar_height); + } if (mLeftEdgePanel != null) { mLeftEdgePanel.setDimensions(width, height); } @@ -397,6 +380,13 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } }; + private BroadcastReceiver mOverlaysChangedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + showHomeHandle(QuickStepController.showHomeHandle(getContext())); + } + }; + public NavigationBarView(Context context, AttributeSet attrs) { super(context, attrs); @@ -450,14 +440,18 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav mQuickScrubAction, null /* swipeLeftEdgeAction */, null /* swipeRightEdgeAction */ }; - mPrototypeController = new NavigationPrototypeController(mHandler, mContext); + mPrototypeController = new NavigationPrototypeController(context); mPrototypeController.register(); mPrototypeController.setOnPrototypeChangedListener(mPrototypeListener); - mColorAdaptionController = new NavBarTintController(this, getLightTransitionsController()); + mTintController = new NavBarTintController(this, getLightTransitionsController()); + + IntentFilter filter = new IntentFilter(ACTION_OVERLAY_CHANGED); + filter.addDataScheme("package"); + context.registerReceiver(mOverlaysChangedReceiver, filter); } - public NavBarTintController getColorAdaptionController() { - return mColorAdaptionController; + public NavBarTintController getTintController() { + return mTintController; } public BarTransitions getBarTransitions() { @@ -483,12 +477,17 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); - mColorAdaptionController.onDraw(); + mTintController.onDraw(); } private void updateNavigationGestures() { if (mGestureHelper instanceof QuickStepController) { - final int[] assignedMap = mPrototypeController.getGestureActionMap(); + // TODO: Clarify this when we remove the prototype controller + final int[] gesturalMap = {0, 7, 1, 1, 3, 3}; + final int[] normalMap = {0, 0, 0, 0, 0, 0}; + final int[] assignedMap = QuickStepContract.isGesturalMode(getContext()) + ? gesturalMap + : normalMap; ((QuickStepController) mGestureHelper).setGestureActions( getNavigationActionFromType(assignedMap[0], mDefaultGestureMap[0]), getNavigationActionFromType(assignedMap[1], mDefaultGestureMap[1]), @@ -559,6 +558,17 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav return super.onTouchEvent(event); } + void onBarTransition(int newMode) { + if (newMode == MODE_OPAQUE) { + // If the nav bar background is opaque, stop auto tinting since we know the icons are + // showing over a dark background + mTintController.stop(); + getLightTransitionsController().setIconsDark(false /* dark */, true /* animate */); + } else { + mTintController.start(); + } + } + private boolean shouldDeadZoneConsumeTouchEvents(MotionEvent event) { if (mDeadZone.onTouchEvent(event) || mDeadZoneConsuming) { switch (event.getActionMasked()) { @@ -591,8 +601,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav getHomeButton().abortCurrentGesture(); } - private H mHandler = new H(); - public View getCurrentView() { return mCurrentView; } @@ -647,6 +655,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } public boolean isQuickScrubEnabled() { + // TODO(b/112934365): Remove this sys prop flag return SystemProperties.getBoolean("persist.quickstep.scrub.enabled", true) && mOverviewProxyService.isEnabled() && isOverviewEnabled() && ((mOverviewProxyService.getInteractionFlags() & FLAG_DISABLE_QUICK_SCRUB) == 0); @@ -793,17 +802,17 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav mBarTransitions.reapplyDarkIntensity(); - boolean disableHome = ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0); + boolean disableHome = QuickStepController.shouldHideHomeButton(getContext()) + || ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0); // TODO(b/113914868): investigation log for disappearing home button Log.i(TAG, "updateNavButtonIcons (b/113914868): home disabled=" + disableHome + " mDisabledFlags=" + mDisabledFlags); - disableHome |= mPrototypeController.hideHomeButton(); // Always disable recents when alternate car mode UI is active and for secondary displays. boolean disableRecent = isRecentsButtonDisabled(); - boolean disableBack = QuickStepController.shouldhideBackButton(getContext()) + boolean disableBack = QuickStepController.shouldHideBackButton(getContext()) || (((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0) && !useAltBack); // When screen pinning, don't hide back and home when connected service or back and @@ -822,7 +831,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav disableBack = disableRecent = false; } - ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons); + ViewGroup navButtons = getCurrentView().findViewById(R.id.nav_buttons); if (navButtons != null) { LayoutTransition lt = navButtons.getLayoutTransition(); if (lt != null) { @@ -977,14 +986,13 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } private void showHomeHandle(boolean visible) { - mNavigationInflaterView.onTuningChanged(NAV_BAR_VIEWS, - visible ? getContext().getString(R.string.config_navBarLayoutHandle) : null); + mNavigationInflaterView.onTuningChanged(NAV_BAR_VIEWS, null); // Color adaption is tied with showing home handle, only avaliable if visible if (visible) { - mColorAdaptionController.start(); + mTintController.start(); } else { - mColorAdaptionController.stop(); + mTintController.stop(); } } @@ -995,7 +1003,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav // TODO(b/112934365): move this back to NavigationBarFragment when prototype is removed private void updateAssistantAvailability() { - boolean available = mAssistantAvailable && mPrototypeController.isAssistantGestureEnabled(); + boolean available = mAssistantAvailable && QuickStepContract.isGesturalMode(getContext()); if (mOverviewProxyService.getProxy() != null) { try { mOverviewProxyService.getProxy().onAssistantAvailable(available); @@ -1193,23 +1201,37 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int w = MeasureSpec.getSize(widthMeasureSpec); + int h = MeasureSpec.getSize(heightMeasureSpec); if (DEBUG) Log.d(TAG, String.format( - "onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh)); + "onMeasure: (%dx%d) old: (%dx%d)", w, h, getMeasuredWidth(), getMeasuredHeight())); - final boolean newVertical = w > 0 && h > w; + final boolean newVertical = w > 0 && h > w + && !QuickStepContract.isGesturalMode(getContext()); if (newVertical != mIsVertical) { mIsVertical = newVertical; if (DEBUG) { - Log.d(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w, + Log.d(TAG, String.format("onMeasure: h=%d, w=%d, vert=%s", h, w, mIsVertical ? "y" : "n")); } reorient(); notifyVerticalChangedListener(newVertical); } - postCheckForInvalidLayout("sizeChanged"); - super.onSizeChanged(w, h, oldw, oldh); + if (QuickStepContract.isGesturalMode(getContext())) { + // Update the nav bar background to match the height of the visible nav bar + int height = mIsVertical + ? getResources().getDimensionPixelSize( + com.android.internal.R.dimen.navigation_bar_height_landscape) + : getResources().getDimensionPixelSize( + com.android.internal.R.dimen.navigation_bar_height); + int frameHeight = getResources().getDimensionPixelSize( + com.android.internal.R.dimen.navigation_bar_frame_height); + mBarTransitions.setBackgroundFrame(new Rect(0, frameHeight - height, w, h)); + } + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); } private void notifyVerticalChangedListener(boolean newVertical) { @@ -1235,9 +1257,9 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { - mColorAdaptionController.start(); + mTintController.start(); } else { - mColorAdaptionController.stop(); + mTintController.stop(); } } @@ -1264,28 +1286,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav return uiCarModeChanged; } - /* - @Override - protected void onLayout (boolean changed, int left, int top, int right, int bottom) { - if (DEBUG) Log.d(TAG, String.format( - "onLayout: %s (%d,%d,%d,%d)", - changed?"changed":"notchanged", left, top, right, bottom)); - super.onLayout(changed, left, top, right, bottom); - } - - // uncomment this for extra defensiveness in WORKAROUND_INVALID_LAYOUT situations: if all else - // fails, any touch on the display will fix the layout. - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - if (DEBUG) Log.d(TAG, "onInterceptTouchEvent: " + ev.toString()); - if (ev.getAction() == MotionEvent.ACTION_DOWN) { - postCheckForInvalidLayout("touch"); - } - return super.onInterceptTouchEvent(ev); - } - */ - - private String getResourceName(int resId) { if (resId != 0) { final android.content.res.Resources res = getContext().getResources(); @@ -1299,10 +1299,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav } } - private void postCheckForInvalidLayout(final String how) { - mHandler.obtainMessage(MSG_CHECK_INVALID_LAYOUT, 0, 0, how).sendToTarget(); - } - private static String visibilityToString(int vis) { switch (vis) { case View.INVISIBLE: @@ -1324,7 +1320,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav NavGesture.class, false /* Only one */); setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled()); - if (mPrototypeController.isEnabled()) { + if (QuickStepContract.isGesturalMode(getContext())) { WindowManager wm = (WindowManager) getContext() .getSystemService(Context.WINDOW_SERVICE); int width = mPrototypeController.getEdgeSensitivityWidth(); @@ -1355,6 +1351,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav mGestureHelper.destroy(); } mPrototypeController.unregister(); + getContext().unregisterReceiver(mOverlaysChangedReceiver); setUpSwipeUpOnboarding(false); for (int i = 0; i < mButtonDispatchers.size(); ++i) { mButtonDispatchers.valueAt(i).onDestroy(); @@ -1445,7 +1442,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav mGestureHelper.dump(pw); } mRecentsOnboarding.dump(pw); - mColorAdaptionController.dump(pw); + mTintController.dump(pw); } @Override @@ -1471,7 +1468,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav void onVerticalChanged(boolean isVertical); } - private final Consumer<Boolean> mDockedListener = exists -> mHandler.post(() -> { + private final Consumer<Boolean> mDockedListener = exists -> post(() -> { mDockedStackExists = exists; updateRecentsIcon(); }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java index 968074c6af59..7dc71f590ecd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java @@ -57,6 +57,7 @@ public class NavigationHandle extends View implements ButtonInterface { mLightColor = Utils.getColorAttrDefaultColor(lightContext, R.attr.singleToneColor); mDarkColor = Utils.getColorAttrDefaultColor(darkContext, R.attr.singleToneColor); mPaint.setAntiAlias(true); + setFocusable(false); } @Override @@ -68,7 +69,7 @@ public class NavigationHandle extends View implements ButtonInterface { int height = mRadius * 2; int width = getWidth(); int y = (navHeight - mBottom - height); - canvas.drawRoundRect(mRadius, y, width - mRadius, y + height, mRadius, mRadius, mPaint); + canvas.drawRoundRect(0, y, width, y + height, mRadius, mRadius, mPaint); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java index 979de07fce73..47a10547688b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java @@ -17,7 +17,9 @@ package com.android.systemui.statusbar.phone; import android.annotation.IntDef; +import android.content.ComponentCallbacks; import android.content.Context; +import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Point; @@ -25,6 +27,8 @@ import android.net.Uri; import android.os.Handler; import android.provider.Settings; +import com.android.systemui.shared.system.QuickStepContract; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -33,7 +37,7 @@ import java.lang.annotation.RetentionPolicy; * prototypes to run in the system. The class will handle communication changes from the settings * app and call back to listeners. */ -public class NavigationPrototypeController extends ContentObserver { +public class NavigationPrototypeController extends ContentObserver implements ComponentCallbacks { private static final String HIDE_BACK_BUTTON_SETTING = "quickstepcontroller_hideback"; private static final String HIDE_HOME_BUTTON_SETTING = "quickstepcontroller_hidehome"; private static final String PROTOTYPE_ENABLED = "prototype_enabled"; @@ -67,8 +71,8 @@ public class NavigationPrototypeController extends ContentObserver { private final Context mContext; - public NavigationPrototypeController(Handler handler, Context context) { - super(handler); + public NavigationPrototypeController(Context context) { + super(new Handler()); mContext = context; updateSwipeLTRBackSetting(); } @@ -85,9 +89,9 @@ public class NavigationPrototypeController extends ContentObserver { registerObserver(HIDE_HOME_BUTTON_SETTING); registerObserver(GESTURE_MATCH_SETTING); registerObserver(NAV_COLOR_ADAPT_ENABLE_SETTING); - registerObserver(EDGE_SENSITIVITY_WIDTH_SETTING); registerObserver(SHOW_HOME_HANDLE_SETTING); registerObserver(ENABLE_ASSISTANT_GESTURE); + mContext.registerComponentCallbacks(this); } /** @@ -95,6 +99,7 @@ public class NavigationPrototypeController extends ContentObserver { */ public void unregister() { mContext.getContentResolver().unregisterContentObserver(this); + mContext.unregisterComponentCallbacks(this); } @Override @@ -115,9 +120,6 @@ public class NavigationPrototypeController extends ContentObserver { } else if (path.endsWith(NAV_COLOR_ADAPT_ENABLE_SETTING)) { mListener.onColorAdaptChanged( NavBarTintController.isEnabled(mContext)); - } else if (path.endsWith(EDGE_SENSITIVITY_WIDTH_SETTING)) { - mListener.onEdgeSensitivityChanged(getEdgeSensitivityWidth(), - getEdgeSensitivityHeight()); } else if (path.endsWith(SHOW_HOME_HANDLE_SETTING)) { mListener.onHomeHandleVisiblilityChanged(showHomeHandle()); } else if (path.endsWith(ENABLE_ASSISTANT_GESTURE)) { @@ -130,7 +132,7 @@ public class NavigationPrototypeController extends ContentObserver { * @return the width for edge swipe */ public int getEdgeSensitivityWidth() { - return convertDpToPixel(getGlobalInt(EDGE_SENSITIVITY_WIDTH_SETTING, 0)); + return QuickStepContract.getEdgeSensitivityWidth(mContext); } /** @@ -202,6 +204,18 @@ public class NavigationPrototypeController extends ContentObserver { return (int) (dp * Resources.getSystem().getDisplayMetrics().density); } + @Override + public void onConfigurationChanged(Configuration newConfig) { + if (mListener != null) { + mListener.onEdgeSensitivityChanged(getEdgeSensitivityWidth(), + getEdgeSensitivityHeight()); + } + } + + @Override + public void onLowMemory() { + } + public interface OnPrototypeChangedListener { void onGestureRemap(@GestureAction int[] actions); void onBackButtonVisibilityChanged(boolean visible); 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 253bdfb1a206..02bad736723d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -92,6 +92,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.statusbar.policy.ZenModeController; +import com.android.systemui.util.InjectionInflationController; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -141,6 +142,7 @@ public class NotificationPanelView extends PanelView implements private static final AnimationProperties CLOCK_ANIMATION_PROPERTIES = new AnimationProperties() .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); + private final InjectionInflationController mInjectionInflationController; private final PowerManager mPowerManager; private final AccessibilityManager mAccessibilityManager; private final NotificationWakeUpCoordinator mWakeUpCoordinator; @@ -336,10 +338,12 @@ public class NotificationPanelView extends PanelView implements @Inject public NotificationPanelView(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs, + InjectionInflationController injectionInflationController, NotificationWakeUpCoordinator coordinator, PulseExpansionHandler pulseExpansionHandler) { super(context, attrs); setWillNotDraw(!DEBUG); + mInjectionInflationController = injectionInflationController; mFalsingManager = FalsingManager.getInstance(context); mPowerManager = context.getSystemService(PowerManager.class); mWakeUpCoordinator = coordinator; @@ -475,10 +479,11 @@ public class NotificationPanelView extends PanelView implements // Re-inflate the status view group. int index = indexOfChild(mKeyguardStatusView); removeView(mKeyguardStatusView); - mKeyguardStatusView = (KeyguardStatusView) LayoutInflater.from(mContext).inflate( - R.layout.keyguard_status_view, - this, - false); + mKeyguardStatusView = (KeyguardStatusView) mInjectionInflationController + .injectable(LayoutInflater.from(mContext)).inflate( + R.layout.keyguard_status_view, + this, + false); addView(mKeyguardStatusView, index); // Re-associate the clock container with the keyguard clock switch. @@ -490,10 +495,11 @@ public class NotificationPanelView extends PanelView implements index = indexOfChild(mKeyguardBottomArea); removeView(mKeyguardBottomArea); KeyguardBottomAreaView oldBottomArea = mKeyguardBottomArea; - mKeyguardBottomArea = (KeyguardBottomAreaView) LayoutInflater.from(mContext).inflate( - R.layout.keyguard_bottom_area, - this, - false); + mKeyguardBottomArea = (KeyguardBottomAreaView) mInjectionInflationController + .injectable(LayoutInflater.from(mContext)).inflate( + R.layout.keyguard_bottom_area, + this, + false); mKeyguardBottomArea.initFrom(oldBottomArea); addView(mKeyguardBottomArea, index); initBottomArea(); @@ -629,6 +635,7 @@ public class NotificationPanelView extends PanelView implements } mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding); mNotificationStackScroller.setAntiBurnInOffsetX(mClockPositionResult.clockX); + mKeyguardBottomArea.setAntiBurnInOffsetX(mClockPositionResult.clockX); mStackScrollerMeasuringPass++; requestScrollerTopPaddingUpdate(animate); @@ -1880,7 +1887,7 @@ public class NotificationPanelView extends PanelView implements float newAlpha = Math.min(getKeyguardContentsAlpha(), alphaQsExpansion) * mKeyguardStatusBarAnimateAlpha; mKeyguardStatusBar.setAlpha(newAlpha); - mKeyguardStatusBar.setVisibility(newAlpha != 0f ? VISIBLE : INVISIBLE); + mKeyguardStatusBar.setVisibility(newAlpha != 0f && !mDozing ? VISIBLE : INVISIBLE); } private void updateKeyguardBottomAreaAlpha() { @@ -2367,12 +2374,11 @@ public class NotificationPanelView extends PanelView implements positionClockAndNotifications(); } - private static float interpolate(float t, float start, float end) { - return (1 - t) * start + t * end; - } - private void updateDozingVisibilities(boolean animate) { mKeyguardBottomArea.setDozing(mDozing, animate); + if (!mDozing && animate) { + animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD); + } } @Override @@ -2808,7 +2814,7 @@ public class NotificationPanelView extends PanelView implements if (mDozing) { mNotificationStackScroller.setShowDarkShelf(!hasCustomClock()); } - mKeyguardStatusBar.setDozing(mDozing); + mKeyguardBottomArea.setDozing(mDozing, animate); if (mBarState == StatusBarState.KEYGUARD || mBarState == StatusBarState.SHADE_LOCKED) { @@ -2823,7 +2829,6 @@ public class NotificationPanelView extends PanelView implements public void onDozeAmountChanged(float linearAmount, float amount) { mInterpolatedDarkAmount = amount; mLinearDarkAmount = linearAmount; - mKeyguardStatusBar.setDarkAmount(mInterpolatedDarkAmount); mKeyguardStatusView.setDarkAmount(mInterpolatedDarkAmount); mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount); positionClockAndNotifications(); @@ -2855,7 +2860,7 @@ public class NotificationPanelView extends PanelView implements } public void dozeTimeTick() { - mKeyguardStatusBar.dozeTimeTick(); + mKeyguardBottomArea.dozeTimeTick(); mKeyguardStatusView.dozeTimeTick(); if (mInterpolatedDarkAmount > 0) { positionClockAndNotifications(); @@ -3034,6 +3039,7 @@ public class NotificationPanelView extends PanelView implements } ViewGroup bouncerContainer = mBouncer.getLockIconContainer(); + ViewGroup bottomContainer = mKeyguardBottomArea.getLockIconContainer(); LockIcon lockIcon = mKeyguardBottomArea.getLockIcon(); if (mBouncer.isAnimatingAway()) { @@ -3045,9 +3051,21 @@ public class NotificationPanelView extends PanelView implements return; } + // Lock icon needs to be re-parented in case of a scrimmed bouncer, + // otherwise it would be under the scrim. + if (mBouncer.isScrimmed() && bouncerContainer != null + && lockIcon.getParent() != bouncerContainer) { + ((ViewGroup) lockIcon.getParent()).removeView(lockIcon); + bouncerContainer.addView(lockIcon); + } else if (!mBouncer.isScrimmed() && bottomContainer != null + && lockIcon.getParent() != bottomContainer) { + ((ViewGroup) lockIcon.getParent()).removeView(lockIcon); + bottomContainer.addView(lockIcon); + } + float translation = 0; - if (bouncerContainer != null) { - float bottomAreaContainerY = getCommonTop(lockIcon); + if (bouncerContainer != null && bottomContainer != null && !mBouncer.isScrimmed()) { + float bottomAreaContainerY = getCommonTop(bottomContainer); float bouncerLockY = getCommonTop(bouncerContainer); if (bouncerLockY < bottomAreaContainerY) { translation = bouncerLockY - bottomAreaContainerY; @@ -3063,7 +3081,7 @@ public class NotificationPanelView extends PanelView implements private static float getCommonTop(View view) { float y = view.getTop(); ViewGroup parent = (ViewGroup) view.getParent(); - while (!(parent instanceof StatusBarWindowView)) { + while (!(parent instanceof StatusBarWindowView) && parent != null) { y += parent.getY(); parent = (ViewGroup) parent.getParent(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index b7a78738828e..183fdb46a795 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -201,7 +201,7 @@ public class PhoneStatusBarPolicy mIconController.setIconVisibility(mSlotAlarmClock, false); // zen - mIconController.setIcon(mSlotZen, R.drawable.stat_sys_zen_important, null); + mIconController.setIcon(mSlotZen, R.drawable.stat_sys_dnd, null); mIconController.setIconVisibility(mSlotZen, false); // volume @@ -339,11 +339,11 @@ public class PhoneStatusBarPolicy zenDescription = mContext.getString(R.string.quick_settings_dnd_label); } else if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) { zenVisible = true; - zenIconId = R.drawable.stat_sys_zen_none; + zenIconId = R.drawable.stat_sys_dnd; zenDescription = mContext.getString(R.string.interruption_level_none); } else if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { zenVisible = true; - zenIconId = R.drawable.stat_sys_zen_important; + zenIconId = R.drawable.stat_sys_dnd; zenDescription = mContext.getString(R.string.interruption_level_priority); } @@ -388,13 +388,12 @@ public class PhoneStatusBarPolicy } private final void updateBluetooth() { - int iconId = R.drawable.stat_sys_data_bluetooth; + int iconId = R.drawable.stat_sys_data_bluetooth_connected; String contentDescription = mContext.getString(R.string.accessibility_quick_settings_bluetooth_on); boolean bluetoothVisible = false; if (mBluetooth != null) { if (mBluetooth.isBluetoothConnected()) { - iconId = R.drawable.stat_sys_data_bluetooth_connected; contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected); bluetoothVisible = mBluetooth.isBluetoothEnabled(); } @@ -582,8 +581,8 @@ public class PhoneStatusBarPolicy String contentDescription = mContext.getString(hasMic ? R.string.accessibility_status_bar_headset : R.string.accessibility_status_bar_headphones); - mIconController.setIcon(mSlotHeadset, hasMic ? R.drawable.ic_headset_mic - : R.drawable.ic_headset, contentDescription); + mIconController.setIcon(mSlotHeadset, hasMic ? R.drawable.stat_sys_headset_mic + : R.drawable.stat_sys_headset, contentDescription); mIconController.setIconVisibility(mSlotHeadset, true); } else { mIconController.setIconVisibility(mSlotHeadset, false); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java index 3398fd34c921..8053ec7e5838 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java @@ -29,7 +29,6 @@ import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE; import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW; import static com.android.systemui.statusbar.phone.NavigationBarView.WINDOW_TARGET_BOTTOM; -import static com.android.systemui.statusbar.phone.NavigationPrototypeController.EDGE_SENSITIVITY_WIDTH_SETTING; import android.annotation.Nullable; import android.content.Context; @@ -58,6 +57,7 @@ import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.utilities.Utilities; import com.android.systemui.shared.system.InputChannelCompat.InputEventDispatcher; import com.android.systemui.shared.system.NavigationBarCompat; +import com.android.systemui.shared.system.QuickStepContract; import java.io.PrintWriter; @@ -72,6 +72,7 @@ public class QuickStepController implements GestureHelper { /** Experiment to swipe home button left to execute a back key press */ private static final String HIDE_BACK_BUTTON_PROP = "quickstepcontroller_hideback"; + private static final String HIDE_HOME_BUTTON_PROP = "quickstepcontroller_hidehome"; private static final String ENABLE_CLICK_THROUGH_NAV_PROP = "quickstepcontroller_clickthrough"; private static final String GESTURE_REGION_THRESHOLD_SETTING = "gesture_region_threshold"; private static final long BACK_BUTTON_FADE_IN_ALPHA = 150; @@ -148,7 +149,7 @@ public class QuickStepController implements GestureHelper { public void setComponents(NavigationBarView navigationBarView) { mNavigationBarView = navigationBarView; - mNavigationBarView.getBackButton().setVisibility(shouldhideBackButton(mContext) + mNavigationBarView.getBackButton().setVisibility(shouldHideBackButton(mContext) ? View.GONE : View.VISIBLE); } @@ -262,10 +263,7 @@ public class QuickStepController implements GestureHelper { mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix); mAllowGestureDetection = true; mNotificationsVisibleOnDown = !mNavigationBarView.isNotificationsFullyCollapsed(); - final int defaultRegionThreshold = mContext.getResources() - .getDimensionPixelOffset(R.dimen.navigation_bar_default_edge_width); - mGestureRegionThreshold = convertDpToPixel(getIntGlobalSetting(mContext, - EDGE_SENSITIVITY_WIDTH_SETTING, defaultRegionThreshold)); + mGestureRegionThreshold = QuickStepContract.getEdgeSensitivityWidth(mContext); break; } case MotionEvent.ACTION_MOVE: { @@ -355,7 +353,7 @@ public class QuickStepController implements GestureHelper { if (mCurrentAction != null) { mCurrentAction.endGesture(); } - } else if (getBoolGlobalSetting(mContext, ENABLE_CLICK_THROUGH_NAV_PROP) + } else if (QuickStepContract.isNavBarClickThrough(mContext) && !mClickThroughPressed) { // Enable click through functionality where no gesture has been detected and // not passed the drag slop so inject a touch event at the same location @@ -700,6 +698,8 @@ public class QuickStepController implements GestureHelper { return (int) (dp * Resources.getSystem().getDisplayMetrics().density); } + // TODO(112934365): Clean up following methods when cleaning up nav bar experiments + static boolean getBoolGlobalSetting(Context context, String key) { return Settings.Global.getInt(context.getContentResolver(), key, 0) != 0; } @@ -708,7 +708,24 @@ public class QuickStepController implements GestureHelper { return Settings.Global.getInt(context.getContentResolver(), key, defaultValue); } - public static boolean shouldhideBackButton(Context context) { - return getBoolGlobalSetting(context, HIDE_BACK_BUTTON_PROP); + /** + * @return whether to hide the back button. + */ + public static boolean shouldHideBackButton(Context context) { + return QuickStepContract.isGesturalMode(context); + } + + /** + * @return whether to hide the home button. + */ + public static boolean shouldHideHomeButton(Context context) { + return QuickStepContract.isGesturalMode(context); + } + + /** + * @return whether to show the home handle. + */ + public static boolean showHomeHandle(Context context) { + return QuickStepContract.isGesturalMode(context); } } 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 1949badf0513..0d2fe13b9a09 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -92,7 +92,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo /** * Scrim opacity when the phone is about to wake-up. */ - public static final float AOD2_SCRIM_ALPHA = 0.6f; + public static final float WAKE_SENSOR_SCRIM_ALPHA = 0.6f; /** * A scrim varies its opacity based on a busyness factor, for example * how many notifications are currently visible. @@ -458,6 +458,23 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo mState.AOD.setAodFrontScrimAlpha(alpha); } + /** + * If the lock screen sensor is active. + */ + public void setWakeLockScreenSensorActive(boolean active) { + for (ScrimState state : ScrimState.values()) { + state.setWakeLockScreenSensorActive(active); + } + + if (mState == ScrimState.PULSING) { + float newBehindAlpha = mState.getBehindAlpha(); + if (mCurrentBehindAlpha != newBehindAlpha) { + mCurrentBehindAlpha = newBehindAlpha; + updateScrims(); + } + } + } + protected void scheduleUpdate() { if (mUpdatePending) return; @@ -904,10 +921,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo } } - public void setPulseReason(int pulseReason) { - ScrimState.PULSING.setPulseReason(pulseReason); - } - public interface Callback { default void onStart() { } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java index 2f161d5cd192..d152ecd8b930 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java @@ -19,7 +19,6 @@ package com.android.systemui.statusbar.phone; import android.graphics.Color; import android.os.Trace; -import com.android.systemui.doze.DozeLog; import com.android.systemui.statusbar.ScrimView; import com.android.systemui.statusbar.notification.stack.StackStateAnimator; @@ -129,16 +128,15 @@ public enum ScrimState { @Override public void prepare(ScrimState previousState) { mCurrentInFrontAlpha = 0f; - if (mPulseReason == DozeLog.PULSE_REASON_NOTIFICATION - || mPulseReason == DozeLog.PULSE_REASON_DOCKING - || mPulseReason == DozeLog.PULSE_REASON_INTENT) { - mCurrentBehindAlpha = previousState.getBehindAlpha(); - } else { - mCurrentBehindAlpha = ScrimController.AOD2_SCRIM_ALPHA; - } mCurrentBehindTint = Color.BLACK; mBlankScreen = mDisplayRequiresBlanking; } + + @Override + public float getBehindAlpha() { + return mWakeLockScreenSensorActive ? ScrimController.WAKE_SENSOR_SCRIM_ALPHA + : AOD.getBehindAlpha(); + } }, /** @@ -199,7 +197,7 @@ public enum ScrimState { int mIndex; boolean mHasBackdrop; boolean mLaunchingAffordanceWithPreview; - int mPulseReason; + boolean mWakeLockScreenSensorActive; ScrimState(int index) { mIndex = index; @@ -264,10 +262,6 @@ public enum ScrimState { mAodFrontScrimAlpha = aodFrontScrimAlpha; } - public void setPulseReason(int pulseReason) { - mPulseReason = pulseReason; - } - public void setScrimBehindAlphaKeyguard(float scrimBehindAlphaKeyguard) { mScrimBehindAlphaKeyguard = scrimBehindAlphaKeyguard; } @@ -287,4 +281,8 @@ public enum ScrimState { public void setHasBackdrop(boolean hasBackdrop) { mHasBackdrop = hasBackdrop; } + + public void setWakeLockScreenSensorActive(boolean active) { + mWakeLockScreenSensorActive = active; + } }
\ No newline at end of file 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 319a504c17a5..db91d0160391 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -25,6 +25,7 @@ import static android.app.StatusBarManager.WindowVisibleState; import static android.app.StatusBarManager.windowStateToString; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; +import static com.android.systemui.Dependency.MAIN_HANDLER; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING; @@ -126,6 +127,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.keyguard.ViewMediatorCallback; +import com.android.systemui.ActivityIntentHelper; import com.android.systemui.ActivityStarterDelegate; import com.android.systemui.AutoReinflateContainer; import com.android.systemui.DemoMode; @@ -219,7 +221,6 @@ import com.android.systemui.statusbar.policy.KeyguardMonitor; import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; -import com.android.systemui.statusbar.policy.PreviewInflater; import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserInfoControllerImpl; @@ -433,6 +434,9 @@ public class StatusBar extends SystemUI implements DemoMode, public void onUserSetupChanged() { final boolean userSetup = mDeviceProvisionedController.isUserSetup( mDeviceProvisionedController.getCurrentUser()); + // STOPSHIP(kozynski, b/129405675) Remove log + Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for user " + + mDeviceProvisionedController.getCurrentUser()); if (MULTIUSER_DEBUG) { Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s", userSetup, mUserSetup)); @@ -586,11 +590,12 @@ public class StatusBar extends SystemUI implements DemoMode, mEntryManager.updateNotifications(); updateScrimController(); }; + private ActivityIntentHelper mActivityIntentHelper; @Override public void onActiveStateChanged(int code, int uid, String packageName, boolean active) { mForegroundServiceController.onAppOpChanged(code, uid, packageName, active); - Dependency.get(Dependency.MAIN_HANDLER).post(() -> { + Dependency.get(MAIN_HANDLER).post(() -> { mNotificationListController.updateNotificationsForAppOp(code, uid, packageName, active); }); } @@ -635,6 +640,7 @@ public class StatusBar extends SystemUI implements DemoMode, mNavigationBarController = Dependency.get(NavigationBarController.class); mBubbleController = Dependency.get(BubbleController.class); mBubbleController.setExpandListener(mBubbleExpandListener); + mActivityIntentHelper = new ActivityIntentHelper(mContext); KeyguardSliceProvider sliceProvider = KeyguardSliceProvider.getAttachedInstance(); if (sliceProvider != null) { sliceProvider.initDependencies(mMediaManager, mStatusBarStateController); @@ -1069,7 +1075,8 @@ public class StatusBar extends SystemUI implements DemoMode, mRemoteInputManager, mStatusBarRemoteInputCallback, mGroupManager, mLockscreenUserManager, shadeController, mKeyguardMonitor, mNotificationInterruptionStateProvider, mMetricsLogger, - new LockPatternUtils(mContext)); + new LockPatternUtils(mContext), Dependency.get(MAIN_HANDLER), + mActivityIntentHelper); mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter); @@ -1293,13 +1300,16 @@ public class StatusBar extends SystemUI implements DemoMode, * the user intends to use the lock screen user switcher, QS in not needed. */ private void updateQsExpansionEnabled() { - mNotificationPanel.setQsExpansionEnabled(mDeviceProvisionedController.isDeviceProvisioned() + final boolean expandEnabled = mDeviceProvisionedController.isDeviceProvisioned() && (mUserSetup || mUserSwitcherController == null || !mUserSwitcherController.isSimpleUserSwitcher()) && ((mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0) && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0) && !mDozing - && !ONLY_CORE_APPS); + && !ONLY_CORE_APPS; + mNotificationPanel.setQsExpansionEnabled(expandEnabled); + // STOPSHIP(kozynski, b/129405675) Remove log + Log.d(TAG, "updateQsExpansionEnabled - QS Expand enabled: " + expandEnabled); } public void addQsTile(ComponentName tile) { @@ -2449,8 +2459,8 @@ public class StatusBar extends SystemUI implements DemoMode, final Callback callback, int flags) { if (onlyProvisioned && !mDeviceProvisionedController.isDeviceProvisioned()) return; - final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( - mContext, intent, mLockscreenUserManager.getCurrentUserId()); + final boolean afterKeyguardGone = mActivityIntentHelper.wouldLaunchResolverActivity( + intent, mLockscreenUserManager.getCurrentUserId()); Runnable runnable = () -> { mAssistManager.hideAssist(); intent.setFlags( @@ -3898,7 +3908,6 @@ public class StatusBar extends SystemUI implements DemoMode, @Override public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) { - mScrimController.setPulseReason(reason); if (reason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS) { mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:LONG_PRESS"); @@ -3906,6 +3915,10 @@ public class StatusBar extends SystemUI implements DemoMode, return; } + if (reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { + mScrimController.setWakeLockScreenSensorActive(true); + } + boolean passiveAuthInterrupt = reason == DozeLog.PULSE_REASON_NOTIFICATION; // Set the state to pulsing, so ScrimController will know what to do once we ask it to // execute the transition. The pulse callback will then be invoked when the scrims @@ -3924,6 +3937,7 @@ public class StatusBar extends SystemUI implements DemoMode, mPulsing = false; callback.onPulseFinished(); updateNotificationPanelTouchState(); + mScrimController.setWakeLockScreenSensorActive(false); setPulsing(false); } @@ -4000,7 +4014,10 @@ public class StatusBar extends SystemUI implements DemoMode, } @Override - public void extendPulse() { + public void extendPulse(int reason) { + if (reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { + mScrimController.setWakeLockScreenSensorActive(true); + } if (mDozeScrimController.isPulsing() && mAmbientPulseManager.hasNotifications()) { mAmbientPulseManager.extendPulse(); } else { @@ -4315,7 +4332,7 @@ public class StatusBar extends SystemUI implements DemoMode, public void startPendingIntentDismissingKeyguard( final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback) { final boolean afterKeyguardGone = intent.isActivity() - && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(), + && mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(), mLockscreenUserManager.getCurrentUserId()); executeActionDismissingKeyguard(() -> { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 441285138afd..3b32d95262cd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -86,6 +86,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void onFullyShown() { updateStates(); mStatusBar.wakeUpIfDozing(SystemClock.uptimeMillis(), mContainer, "BOUNCER_VISIBLE"); + mNotificationPanelView.updateLockIcon(); } @Override @@ -96,6 +97,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb @Override public void onFullyHidden() { updateStates(); + mNotificationPanelView.updateLockIcon(); } @Override @@ -758,8 +760,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } public boolean bouncerNeedsScrimming() { - return mOccluded || mBouncer.willDismissWithAction() || mBouncer.needsFullscreenBouncer() - || mStatusBar.isFullScreenUserSwitcherState() || mBouncer.isShowingScrimmed(); + return mOccluded || mBouncer.willDismissWithAction() + || mStatusBar.isFullScreenUserSwitcherState() + || (mBouncer.isShowing() && mBouncer.isScrimmed()) + || mBouncer.isFullscreenBouncer(); } public void dump(PrintWriter pw) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java index 7e45507b4985..215f5c4dfc5b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -16,7 +16,6 @@ package com.android.systemui.statusbar.phone; -import static com.android.systemui.Dependency.MAIN_HANDLER; import static com.android.systemui.statusbar.phone.StatusBar.getActivityOptions; import android.app.ActivityManager; @@ -29,6 +28,7 @@ import android.app.TaskStackBuilder; import android.content.Context; import android.content.Intent; import android.os.AsyncTask; +import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; @@ -43,6 +43,7 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.internal.widget.LockPatternUtils; +import com.android.systemui.ActivityIntentHelper; import com.android.systemui.Dependency; import com.android.systemui.EventLogTags; import com.android.systemui.UiOffloadThread; @@ -65,7 +66,6 @@ import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.policy.HeadsUpUtil; import com.android.systemui.statusbar.policy.KeyguardMonitor; -import com.android.systemui.statusbar.policy.PreviewInflater; /** * Status bar implementation of {@link NotificationActivityStarter}. @@ -97,6 +97,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit private final IStatusBarService mBarService; private final CommandQueue mCommandQueue; private final IDreamManager mDreamManager; + private final Handler mMainThreadHandler; + private final ActivityIntentHelper mActivityIntentHelper; private boolean mIsCollapsingToShowActivityOverLockscreen; @@ -121,7 +123,9 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit KeyguardMonitor keyguardMonitor, NotificationInterruptionStateProvider notificationInterruptionStateProvider, MetricsLogger metricsLogger, - LockPatternUtils lockPatternUtils) { + LockPatternUtils lockPatternUtils, + Handler mainThreadHandler, + ActivityIntentHelper activityIntentHelper) { mContext = context; mNotificationPanel = panel; mPresenter = presenter; @@ -150,6 +154,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit } }); mStatusBarRemoteInputCallback = remoteInputCallback; + mMainThreadHandler = mainThreadHandler; + mActivityIntentHelper = activityIntentHelper; } /** @@ -176,12 +182,11 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit boolean isActivityIntent = intent.isActivity(); final boolean afterKeyguardGone = isActivityIntent - && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(), + && mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(), mLockscreenUserManager.getCurrentUserId()); final boolean wasOccluded = mShadeController.isOccluded(); boolean showOverLockscreen = mKeyguardMonitor.isShowing() - && PreviewInflater.wouldShowOverLockscreen(mContext, - intent.getIntent(), + && mActivityIntentHelper.wouldShowOverLockscreen(intent.getIntent(), mLockscreenUserManager.getCurrentUserId()); ActivityStarter.OnDismissAction postKeyguardAction = () -> handleNotificationClickAfterKeyguardDismissed( @@ -358,7 +363,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit mActivityLaunchAnimator.setLaunchResult(launchResult, true /* isActivityIntent */); if (shouldCollapse()) { // Putting it back on the main thread, since we're touching views - Dependency.get(MAIN_HANDLER).post(() -> mCommandQueue.animateCollapsePanels( + mMainThreadHandler.post(() -> mCommandQueue.animateCollapsePanels( CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */)); } }); @@ -425,7 +430,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit if (Looper.getMainLooper().isCurrentThread()) { mShadeController.collapsePanel(); } else { - Dependency.get(MAIN_HANDLER).post(mShadeController::collapsePanel); + mMainThreadHandler.post(mShadeController::collapsePanel); } } @@ -444,7 +449,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit private void removeNotification(StatusBarNotification notification) { // We have to post it to the UI thread for synchronization - Dependency.get(MAIN_HANDLER).post(() -> { + mMainThreadHandler.post(() -> { Runnable removeRunnable = () -> mEntryManager.performRemoveNotification(notification); if (mPresenter.isCollapsing()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java index 21d9dcc6897d..471d5113a502 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java @@ -33,6 +33,7 @@ import android.os.UserHandle; import android.view.View; import android.view.ViewParent; +import com.android.systemui.ActivityIntentHelper; import com.android.systemui.Dependency; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -46,7 +47,6 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.policy.KeyguardMonitor; -import com.android.systemui.statusbar.policy.PreviewInflater; import javax.inject.Inject; import javax.inject.Singleton; @@ -64,6 +64,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, Dependency.get(NotificationLockscreenUserManager.class); private final ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class); private final Context mContext; + private final ActivityIntentHelper mActivityIntentHelper; private View mPendingWorkRemoteInputView; private View mPendingRemoteInputView; private final ShadeController mShadeController = Dependency.get(ShadeController.class); @@ -83,6 +84,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, mKeyguardManager = context.getSystemService(KeyguardManager.class); mCommandQueue = getComponent(context, CommandQueue.class); mCommandQueue.addCallback(this); + mActivityIntentHelper = new ActivityIntentHelper(mContext); } @Override @@ -220,8 +222,8 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks, NotificationRemoteInputManager.ClickHandler defaultHandler) { final boolean isActivity = pendingIntent.isActivity(); if (isActivity) { - final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( - mContext, pendingIntent.getIntent(), mLockscreenUserManager.getCurrentUserId()); + final boolean afterKeyguardGone = mActivityIntentHelper.wouldLaunchResolverActivity( + pendingIntent.getIntent(), mLockscreenUserManager.getCurrentUserId()); mActivityStarter.dismissKeyguardThenExecute(() -> { try { ActivityManager.getService().resumeAppSwitches(); 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 a8ae5f65a2a0..96090571685e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -114,17 +114,19 @@ public class StatusBarWindowView extends FrameLayout { if (mSingleTapEnabled) { mService.wakeUpIfDozing(SystemClock.uptimeMillis(), StatusBarWindowView.this, "SINGLE_TAP"); + return true; } - return mSingleTapEnabled; + return false; } @Override public boolean onDoubleTap(MotionEvent e) { - if (mDoubleTapEnabled) { + if (mDoubleTapEnabled || mSingleTapEnabled) { mService.wakeUpIfDozing(SystemClock.uptimeMillis(), StatusBarWindowView.this, "DOUBLE_TAP"); + return true; } - return mDoubleTapEnabled; + return false; } }; private final TunerService.Tunable mTunable = (key, newValue) -> { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java index f5e745f650a9..db2523e40ded 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java @@ -21,9 +21,10 @@ import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; import android.net.Uri; +import android.os.Handler; import android.provider.Settings.Global; import android.provider.Settings.Secure; -import android.os.Handler; +import android.util.Log; import com.android.systemui.settings.CurrentUserTracker; @@ -39,6 +40,7 @@ import javax.inject.Singleton; public class DeviceProvisionedControllerImpl extends CurrentUserTracker implements DeviceProvisionedController { + private static final String TAG = DeviceProvisionedControllerImpl.class.getSimpleName(); private final ArrayList<DeviceProvisionedListener> mListeners = new ArrayList<>(); private final ContentResolver mContentResolver; private final Context mContext; @@ -59,6 +61,8 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen mSettingsObserver = new ContentObserver(mainHandler) { @Override public void onChange(boolean selfChange, Uri uri, int userId) { + // STOPSHIP(kozynski, b/129405675) Remove log + Log.d(TAG, "Setting change: " + uri); if (mUserSetupUri.equals(uri)) { notifySetupChanged(); } else { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java index 3c8ed6ebf279..b53ff0e45cea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java @@ -16,9 +16,11 @@ package com.android.systemui.statusbar.policy; +import android.annotation.NonNull; import android.app.ActivityManager; import android.content.Context; +import com.android.internal.util.Preconditions; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.settings.CurrentUserTracker; @@ -69,7 +71,8 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback } @Override - public void addCallback(Callback callback) { + public void addCallback(@NonNull Callback callback) { + Preconditions.checkNotNull(callback, "Callback must not be null. b/128895449"); mCallbacks.add(callback); if (mCallbacks.size() != 0 && !mListening) { mListening = true; @@ -81,7 +84,8 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback } @Override - public void removeCallback(Callback callback) { + public void removeCallback(@NonNull Callback callback) { + Preconditions.checkNotNull(callback, "Callback must not be null. b/128895449"); if (mCallbacks.remove(callback) && mCallbacks.size() == 0 && mListening) { mListening = false; mKeyguardUpdateMonitor.removeCallback(this); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index 5bd394fb7187..c5996a1e1b00 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -470,10 +470,16 @@ public class MobileSignalController extends SignalController< mNetworkController.recalculateEmergency(); } // Fill in the network name if we think we have it. - if (mCurrentState.networkName == mNetworkNameDefault && mServiceState != null + if (mCurrentState.networkName.equals(mNetworkNameDefault) && mServiceState != null && !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) { mCurrentState.networkName = mServiceState.getOperatorAlphaShort(); } + // If this is the data subscription, update the currentState data name + if (mCurrentState.networkNameData.equals(mNetworkNameDefault) && mServiceState != null + && mCurrentState.dataSim + && !TextUtils.isEmpty(mServiceState.getDataOperatorAlphaShort())) { + mCurrentState.networkNameData = mServiceState.getDataOperatorAlphaShort(); + } notifyListenersIfNecessary(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 51fef7d73993..71db618d6076 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -37,6 +37,7 @@ public interface NetworkController extends CallbackController<SignalCallback>, D DataUsageController getMobileDataController(); DataSaverController getDataSaverController(); String getMobileDataNetworkName(); + int getNumberSubscriptions(); boolean hasVoiceCallingFeature(); 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 ef39912b6578..d01430a97783 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -376,6 +376,11 @@ public class NetworkControllerImpl extends BroadcastReceiver return controller != null ? controller.getState().networkNameData : ""; } + @Override + public int getNumberSubscriptions() { + return mMobileSignalControllers.size(); + } + public boolean isEmergencyOnly() { if (mMobileSignalControllers.size() == 0) { // When there are no active subscriptions, determine emengency state from last diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java index 92034b2be0ed..3d317143eb51 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java @@ -19,7 +19,6 @@ package com.android.systemui.statusbar.policy; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; @@ -29,6 +28,7 @@ import android.view.View; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.systemui.ActivityIntentHelper; import com.android.systemui.statusbar.phone.KeyguardPreviewContainer; import java.util.List; @@ -41,13 +41,16 @@ public class PreviewInflater { private static final String TAG = "PreviewInflater"; private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout"; + private final ActivityIntentHelper mActivityIntentHelper; private Context mContext; private LockPatternUtils mLockPatternUtils; - public PreviewInflater(Context context, LockPatternUtils lockPatternUtils) { + public PreviewInflater(Context context, LockPatternUtils lockPatternUtils, + ActivityIntentHelper activityIntentHelper) { mContext = context; mLockPatternUtils = lockPatternUtils; + mActivityIntentHelper = activityIntentHelper; } public View inflatePreview(Intent intent) { @@ -130,7 +133,7 @@ public class PreviewInflater { ResolveInfo resolved = packageManager.resolveActivityAsUser(intent, flags | PackageManager.GET_META_DATA, KeyguardUpdateMonitor.getCurrentUser()); - if (wouldLaunchResolverActivity(resolved, appList)) { + if (mActivityIntentHelper.wouldLaunchResolverActivity(resolved, appList)) { return null; } if (resolved == null || resolved.activityInfo == null) { @@ -140,63 +143,6 @@ public class PreviewInflater { resolved.activityInfo.metaData); } - public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent, - int currentUserId) { - return getTargetActivityInfo(ctx, intent, currentUserId, false /* onlyDirectBootAware */) - == null; - } - - public static boolean wouldShowOverLockscreen(Context ctx, Intent intent, int currentUserId) { - ActivityInfo targetActivityInfo = getTargetActivityInfo(ctx, intent, currentUserId, - false /* onlyDirectBootAware */); - return targetActivityInfo != null - && (targetActivityInfo.flags & (ActivityInfo.FLAG_SHOW_WHEN_LOCKED - | ActivityInfo.FLAG_SHOW_FOR_ALL_USERS)) > 0; - } - - /** - * @param onlyDirectBootAware a boolean indicating whether the matched activity packages must - * be direct boot aware when in direct boot mode if false, all - * packages are considered a match even if they are not aware. - * @return the target activity info of the intent it resolves to a specific package or - * {@code null} if it resolved to the resolver activity - */ - public static ActivityInfo getTargetActivityInfo(Context ctx, Intent intent, - int currentUserId, boolean onlyDirectBootAware) { - PackageManager packageManager = ctx.getPackageManager(); - int flags = PackageManager.MATCH_DEFAULT_ONLY; - if (!onlyDirectBootAware) { - flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE - | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; - } - final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser( - intent, flags, currentUserId); - if (appList.size() == 0) { - return null; - } - ResolveInfo resolved = packageManager.resolveActivityAsUser(intent, - flags | PackageManager.GET_META_DATA, currentUserId); - if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) { - return null; - } else { - return resolved.activityInfo; - } - } - - private static boolean wouldLaunchResolverActivity( - ResolveInfo resolved, List<ResolveInfo> appList) { - // If the list contains the above resolved activity, then it can't be - // ResolverActivity itself. - for (int i = 0; i < appList.size(); i++) { - ResolveInfo tmp = appList.get(i); - if (tmp.activityInfo.name.equals(resolved.activityInfo.name) - && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) { - return false; - } - } - return true; - } - private static class WidgetInfo { String contextPackage; int layoutId; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java index 72f4fc7820a5..e57cff789a23 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java @@ -118,7 +118,8 @@ public final class SmartReplyConstants { mRequiresTargetingP = readDeviceConfigBooleanOrDefaultIfEmpty( SystemUiDeviceConfigFlags.SSIN_REQUIRES_TARGETING_P, mDefaultRequiresP); - mMaxSqueezeRemeasureAttempts = readDeviceConfigIntegerOrDefaultIfEmpty( + mMaxSqueezeRemeasureAttempts = DeviceConfig.getInt( + DeviceConfig.NAMESPACE_SYSTEMUI, SystemUiDeviceConfigFlags.SSIN_MAX_SQUEEZE_REMEASURE_ATTEMPTS, mDefaultMaxSqueezeRemeasureAttempts); mEditChoicesBeforeSending = readDeviceConfigBooleanOrDefaultIfEmpty( @@ -127,10 +128,12 @@ public final class SmartReplyConstants { mShowInHeadsUp = readDeviceConfigBooleanOrDefaultIfEmpty( SystemUiDeviceConfigFlags.SSIN_SHOW_IN_HEADS_UP, mDefaultShowInHeadsUp); - mMinNumSystemGeneratedReplies = readDeviceConfigIntegerOrDefaultIfEmpty( + mMinNumSystemGeneratedReplies = DeviceConfig.getInt( + DeviceConfig.NAMESPACE_SYSTEMUI, SystemUiDeviceConfigFlags.SSIN_MIN_NUM_SYSTEM_GENERATED_REPLIES, mDefaultMinNumSystemGeneratedReplies); - mMaxNumActions = readDeviceConfigIntegerOrDefaultIfEmpty( + mMaxNumActions = DeviceConfig.getInt( + DeviceConfig.NAMESPACE_SYSTEMUI, SystemUiDeviceConfigFlags.SSIN_MAX_NUM_ACTIONS, mDefaultMaxNumActions); } @@ -152,21 +155,6 @@ public final class SmartReplyConstants { return defaultValue; } - private static int readDeviceConfigIntegerOrDefaultIfEmpty(String propertyName, - int defaultValue) { - String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_SYSTEMUI, propertyName); - if (TextUtils.isEmpty(value)) { - return defaultValue; - } - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - Log.e(TAG, "Tried to read an integer flag, property name=" - + propertyName + ", value=" + value); - return defaultValue; - } - } - /** Returns whether smart replies in notifications are enabled. */ public boolean isEnabled() { return mEnabled; diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java index fa4b3fe4be18..ecf608beb91c 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java @@ -16,14 +16,17 @@ package com.android.systemui.usb; +import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.hardware.usb.ParcelableUsbPort; import android.hardware.usb.UsbManager; import android.hardware.usb.UsbPort; import android.os.Bundle; +import android.util.Log; import android.view.Window; import android.view.WindowManager; +import android.widget.Toast; import com.android.internal.app.AlertActivity; import com.android.internal.app.AlertController; @@ -36,7 +39,6 @@ public class UsbContaminantActivity extends AlertActivity implements DialogInterface.OnClickListener { private static final String TAG = "UsbContaminantActivity"; - private UsbDisconnectedReceiver mDisconnectedReceiver; private UsbPort mUsbPort; @Override @@ -55,8 +57,10 @@ public class UsbContaminantActivity extends AlertActivity final AlertController.AlertParams ap = mAlertParams; ap.mTitle = getString(R.string.usb_contaminant_title); ap.mMessage = getString(R.string.usb_contaminant_message); - ap.mPositiveButtonText = getString(android.R.string.ok); - ap.mPositiveButtonListener = this; + ap.mNegativeButtonText = getString(android.R.string.ok); + ap.mNeutralButtonText = getString(R.string.usb_disable_contaminant_detection); + ap.mNegativeButtonListener = this; + ap.mNeutralButtonListener = this; setupAlert(); } @@ -68,6 +72,15 @@ public class UsbContaminantActivity extends AlertActivity @Override public void onClick(DialogInterface dialog, int which) { + if (which == AlertDialog.BUTTON_NEUTRAL) { + try { + mUsbPort.enableContaminantDetection(false); + Toast.makeText(this, R.string.usb_port_enabled, + Toast.LENGTH_SHORT).show(); + } catch (Exception e) { + Log.e(TAG, "Unable to notify Usb service", e); + } + } finish(); } } diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java index e6b6672d3544..7705e4ecfaea 100644 --- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java +++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java @@ -23,6 +23,7 @@ import android.view.InflateException; import android.view.LayoutInflater; import android.view.View; +import com.android.keyguard.KeyguardClockSwitch; import com.android.systemui.SystemUIFactory; import com.android.systemui.qs.QSCarrierGroup; import com.android.systemui.qs.QSFooterImpl; @@ -130,6 +131,11 @@ public class InjectionInflationController { * Creates the QSCarrierGroup */ QSCarrierGroup createQSCarrierGroup(); + + /** + * Creates the KeyguardClockSwitch. + */ + KeyguardClockSwitch createKeyguardClockSwitch(); } /** diff --git a/packages/SystemUI/src/com/android/systemui/volume/CaptionsToggleImageButton.java b/packages/SystemUI/src/com/android/systemui/volume/CaptionsToggleImageButton.java new file mode 100644 index 000000000000..8ec66e4bcc30 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/volume/CaptionsToggleImageButton.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2019 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.volume; + +import android.content.Context; +import android.util.AttributeSet; + +import com.android.keyguard.AlphaOptimizedImageButton; +import com.android.systemui.R; + +/** Toggle button in Volume Dialog that allows extra state for when streams are opted-out */ +public class CaptionsToggleImageButton extends AlphaOptimizedImageButton { + + private static final int[] OPTED_OUT_STATE = new int[] { R.attr.optedOut }; + + private boolean mComponentEnabled = false; + private boolean mOptedOut = false; + + public CaptionsToggleImageButton(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public int[] onCreateDrawableState(int extraSpace) { + int[] state = super.onCreateDrawableState(extraSpace + 1); + if (mOptedOut) { + mergeDrawableStates(state, OPTED_OUT_STATE); + } + return state; + } + + Runnable setComponentEnabled(boolean isComponentEnabled) { + this.mComponentEnabled = isComponentEnabled; + + return this.setImageResourceAsync(this.mComponentEnabled + ? R.drawable.ic_volume_odi_captions + : R.drawable.ic_volume_odi_captions_disabled); + } + + boolean getComponentEnabled() { + return this.mComponentEnabled; + } + + /** Sets whether or not the current stream has opted out of captions */ + void setOptedOut(boolean isOptedOut) { + this.mOptedOut = isOptedOut; + refreshDrawableState(); + } + + boolean getOptedOut() { + return this.mOptedOut; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java index 2fa8889a02f9..a3db533bb7d0 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java @@ -282,6 +282,13 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa Settings.Secure.ODI_CAPTIONS_ENABLED, isEnabled ? 1 : 0); } + @Override + public boolean isCaptionStreamOptedOut() { + int currentValue = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.ODI_CAPTIONS_OPTED_OUT, 0); + return currentValue == 1; + } + public void getCaptionsComponentState(boolean fromTooltip) { if (mDestroyed) return; mWorker.obtainMessage(W.GET_CAPTIONS_COMPONENT_STATE, fromTooltip).sendToTarget(); diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index cdda216c5220..35a245000628 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -95,6 +95,7 @@ import com.android.systemui.plugins.VolumeDialogController; import com.android.systemui.plugins.VolumeDialogController.State; import com.android.systemui.plugins.VolumeDialogController.StreamState; import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; +import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import java.io.PrintWriter; @@ -108,7 +109,8 @@ import java.util.List; * * Methods ending in "H" must be called on the (ui) handler. */ -public class VolumeDialogImpl implements VolumeDialog { +public class VolumeDialogImpl implements VolumeDialog, + ConfigurationController.ConfigurationListener { private static final String TAG = Util.logTag(VolumeDialogImpl.class); private static final long USER_ATTEMPT_GRACE_PERIOD = 1000; @@ -133,7 +135,7 @@ public class VolumeDialogImpl implements VolumeDialog { private ViewGroup mRinger; private ImageButton mRingerIcon; private ViewGroup mODICaptionsView; - private ImageButton mODICaptionsIcon; + private CaptionsToggleImageButton mODICaptionsIcon; private View mSettingsView; private ImageButton mSettingsIcon; private FrameLayout mZenIcon; @@ -175,6 +177,11 @@ public class VolumeDialogImpl implements VolumeDialog { Prefs.getBoolean(context, Prefs.Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, false); } + @Override + public void onUiModeChanged() { + mContext.getTheme().applyStyle(mContext.getThemeResId(), true); + } + public void init(int windowType, Callback callback) { initDialog(); @@ -182,12 +189,15 @@ public class VolumeDialogImpl implements VolumeDialog { mController.addCallback(mControllerCallbackH, mHandler); mController.getState(); + + Dependency.get(ConfigurationController.class).addCallback(this); } @Override public void destroy() { mController.removeCallback(mControllerCallbackH); mHandler.removeCallbacksAndMessages(null); + Dependency.get(ConfigurationController.class).removeCallback(this); } private void initDialog() { @@ -278,7 +288,7 @@ public class VolumeDialogImpl implements VolumeDialog { addRow(AudioManager.STREAM_RING, R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true, false); addRow(STREAM_ALARM, - R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, true, false); + R.drawable.ic_alarm, R.drawable.ic_volume_alarm_mute, true, false); addRow(AudioManager.STREAM_VOICE_CALL, com.android.internal.R.drawable.ic_phone, com.android.internal.R.drawable.ic_phone, false, false); @@ -587,11 +597,15 @@ public class VolumeDialogImpl implements VolumeDialog { } private void updateCaptionsIcon() { - mHandler.post( - mODICaptionsIcon.setImageResourceAsync( - mController.areCaptionsEnabled() - ? R.drawable.ic_volume_odi_captions - : R.drawable.ic_volume_odi_captions_disabled)); + boolean componentEnabled = mController.areCaptionsEnabled(); + if (mODICaptionsIcon.getComponentEnabled() != componentEnabled) { + mHandler.post(mODICaptionsIcon.setComponentEnabled(componentEnabled)); + } + + boolean isOptedOut = mController.isCaptionStreamOptedOut(); + if (mODICaptionsIcon.getOptedOut() != isOptedOut) { + mHandler.post(() -> mODICaptionsIcon.setOptedOut(isOptedOut)); + } } private void onCaptionIconClicked() { @@ -952,7 +966,7 @@ public class VolumeDialogImpl implements VolumeDialog { } private void updateVolumeRowH(VolumeRow row) { - if (D.BUG) Log.d(TAG, "updateVolumeRowH s=" + row.stream); + if (D.BUG) Log.i(TAG, "updateVolumeRowH s=" + row.stream); if (mState == null) return; final StreamState ss = mState.states.get(row.stream); if (ss == null) return; |