diff options
22 files changed, 472 insertions, 88 deletions
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 685eedc31303..769fd487c2a9 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -2754,12 +2754,11 @@ public class ApplicationPackageManager extends PackageManager { public Drawable loadUnbadgedItemIcon(@NonNull PackageItemInfo itemInfo, @Nullable ApplicationInfo appInfo) { if (itemInfo.showUserIcon != UserHandle.USER_NULL) { - Bitmap bitmap = getUserManager().getUserIcon(itemInfo.showUserIcon); - if (bitmap == null) { - return UserIcons.getDefaultUserIcon( - mContext.getResources(), itemInfo.showUserIcon, /* light= */ false); - } - return new BitmapDrawable(bitmap); + // Indicates itemInfo is for a different user (e.g. a profile's parent), so use a + // generic user icon (users generally lack permission to view each other's actual icons) + int targetUserId = itemInfo.showUserIcon; + return UserIcons.getDefaultUserIcon( + mContext.getResources(), targetUserId, /* light= */ false); } Drawable dr = null; if (itemInfo.packageName != null) { diff --git a/core/java/android/content/om/TEST_MAPPING b/core/java/android/content/om/TEST_MAPPING new file mode 100644 index 000000000000..d35dfdbf32c8 --- /dev/null +++ b/core/java/android/content/om/TEST_MAPPING @@ -0,0 +1,26 @@ +{ + "presubmit": [ + { + "name": "FrameworksServicesTests", + "options": [ + { + "include-filter": "com.android.server.om" + } + ] + }, + { + "name": "OverlayDeviceTests" + }, + { + "name": "OverlayHostTests" + }, + { + "name": "CtsAppSecurityHostTestCases", + "options": [ + { + "include-filter": "android.appsecurity.cts.OverlayHostTest" + } + ] + } + ] +} diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java index 081c5ad78762..d0ab8f713de8 100644 --- a/core/java/android/content/pm/PackageItemInfo.java +++ b/core/java/android/content/pm/PackageItemInfo.java @@ -159,7 +159,7 @@ public class PackageItemInfo { public Bundle metaData; /** - * If different of UserHandle.USER_NULL, The icon of this item will be the one of that user. + * If different of UserHandle.USER_NULL, The icon of this item will represent that user. * @hide */ public int showUserIcon; diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java index 50e7ec30ec3a..df54209bc043 100644 --- a/core/java/android/text/util/Linkify.java +++ b/core/java/android/text/util/Linkify.java @@ -67,6 +67,14 @@ import java.util.regex.Pattern; * create <code>http://example.com</code> when the clickable URL link is * created. * + * <p class="note"><b>Note:</b> When using {@link #MAP_ADDRESSES} or {@link #ALL} + * to match street addresses on API level {@link android.os.Build.VERSION_CODES#O_MR1} + * and earlier, methods in this class may throw + * {@link android.util.AndroidRuntimeException} or other exceptions if the + * device's WebView implementation is currently being updated, because + * {@link android.webkit.WebView#findAddress} is required to match street + * addresses. + * * @see MatchFilter * @see TransformFilter */ @@ -95,10 +103,11 @@ public class Linkify { /** * Bit field indicating that street addresses should be matched in methods that - * take an options mask. Note that this uses the - * {@link android.webkit.WebView#findAddress(String) findAddress()} method in - * {@link android.webkit.WebView} for finding addresses, which has various - * limitations and has been deprecated. + * take an options mask. Note that this should be avoided, as it uses the + * {@link android.webkit.WebView#findAddress(String)} method, which has various + * limitations and has been deprecated: see the documentation for + * {@link android.webkit.WebView#findAddress(String)} for more information. + * * @deprecated use {@link android.view.textclassifier.TextClassifier#generateLinks( * TextLinks.Request)} instead and avoid it even when targeting API levels where no alternative * is available. diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 137b67c6e63e..14be73dec41c 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -1603,9 +1603,9 @@ public class WebView extends AbsoluteLayout } /** - * Gets the first substring consisting of the address of a physical - * location. Currently, only addresses in the United States are detected, - * and consist of: + * Gets the first substring which appears to be the address of a physical + * location. Only addresses in the United States can be detected, which + * must consist of: * <ul> * <li>a house number</li> * <li>a street name</li> @@ -1621,9 +1621,17 @@ public class WebView extends AbsoluteLayout * or abbreviated using USPS standards. The house number may not exceed * five digits. * + * <p class="note"><b>Note:</b> This function is deprecated and should be + * avoided on all API levels, as it cannot detect addresses outside of the + * United States and has a high rate of false positives. On API level + * {@link android.os.Build.VERSION_CODES#O_MR1} and earlier, it also causes + * the entire WebView implementation to be loaded and initialized, which + * can throw {@link android.util.AndroidRuntimeException} or other exceptions + * if the WebView implementation is currently being updated. + * * @param addr the string to search for addresses * @return the address, or if no address is found, {@code null} - * @deprecated this method is superseded by {@link TextClassifier#generateLinks( + * @deprecated This method is superseded by {@link TextClassifier#generateLinks( * android.view.textclassifier.TextLinks.Request)}. Avoid using this method even when targeting * API levels where no alternative is available. */ diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index a9e183ad5bf2..073965b35101 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -4960,6 +4960,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * android.text.util.Linkify#ALL Linkify.ALL} and peers for * possible values. * + * <p class="note"><b>Note:</b> + * {@link android.text.util.Linkify#MAP_ADDRESSES Linkify.MAP_ADDRESSES} + * is deprecated and should be avoided; see its documentation. + * * @attr ref android.R.styleable#TextView_autoLink */ @android.view.RemotableViewMethod diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 1a1615026bdf..585a27978c4f 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -1160,16 +1160,17 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind // Note: We don't need to check for IN_SCREEN or INSET_DECOR because unlike the status bar, // these flags wouldn't make the window draw behind the navigation bar, unless // LAYOUT_HIDE_NAVIGATION was set. + boolean hideNavigation = (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0; boolean forceConsumingNavBar = (mForceWindowDrawsBarBackgrounds && (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0 && (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0 - && (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) - || mLastShouldAlwaysConsumeSystemBars; + && !hideNavigation) + || (mLastShouldAlwaysConsumeSystemBars && hideNavigation); boolean consumingNavBar = ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 && (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0 - && (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) + && !hideNavigation) || forceConsumingNavBar; // If we didn't request fullscreen layout, but we still got it because of the diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 81accdf82b00..2f301946402b 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -1560,7 +1560,8 @@ <flag name="email" value="0x02" /> <!-- Match phone numbers. --> <flag name="phone" value="0x04" /> - <!-- Match map addresses. --> + <!-- Match map addresses. + Deprecated: see {@link android.text.util.Linkify#MAP_ADDRESSES}. --> <flag name="map" value="0x08" /> <!-- Match all patterns (equivalent to web|email|phone|map). --> <flag name="all" value="0x0f" /> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 9bd56ad2f91d..14abb77aad7d 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -3279,7 +3279,8 @@ various workspace stacks. 0 - Nav bar is always opaque when either the freeform stack or docked stack is visible. 1 - Nav bar is always translucent when the freeform stack is visible, otherwise always - opaque. + opaque. + 2 - Nav bar is never forced opaque. --> <integer name="config_navBarOpacityMode">0</integer> diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index 84842563cbdc..e9eda4f5577b 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -83,7 +83,7 @@ public class ImageWallpaper extends WallpaperService { @Override public void onCreate(SurfaceHolder surfaceHolder) { setFixedSizeAllowed(true); - setOffsetNotificationsEnabled(false); + setOffsetNotificationsEnabled(true); updateSurfaceSize(); } @@ -96,6 +96,12 @@ public class ImageWallpaper extends WallpaperService { } @Override + public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, + float yOffsetStep, int xPixelOffset, int yPixelOffset) { + mRenderer.updateOffsets(xOffset, yOffset); + } + + @Override public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) { mRenderer.updateAmbientMode(inAmbientMode, (mNeedTransition || animationDuration != 0) ? animationDuration : 0); diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java index 5d85cbf88f4e..b615a5f32835 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java @@ -52,6 +52,13 @@ public interface GLWallpaperRenderer { void updateAmbientMode(boolean inAmbientMode, long duration); /** + * Notify the wallpaper offsets changed. + * @param xOffset offset along x axis. + * @param yOffset offset along y axis. + */ + void updateOffsets(float xOffset, float yOffset); + + /** * Ask renderer to report the surface size it needs. */ Size reportSurfaceSize(); diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java index 4be7623f90f2..626d0cfed997 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java @@ -33,9 +33,12 @@ import static android.opengl.GLES20.glUniform1i; import static android.opengl.GLES20.glVertexAttribPointer; import android.graphics.Bitmap; +import android.graphics.Rect; import android.opengl.GLUtils; import android.util.Log; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; @@ -91,6 +94,8 @@ class ImageGLWallpaper { private int mUniTexture; private int mTextureId; + private float[] mCurrentTexCoordinate; + ImageGLWallpaper(ImageGLProgram program) { mProgram = program; @@ -195,4 +200,106 @@ class ImageGLWallpaper { glUniform1i(mUniTexture, 0); } + /** + * This method adjust s(x-axis), t(y-axis) texture coordinates to get current display area + * of texture and will be used during transition. + * The adjustment happens if either the width or height of the surface is larger than + * corresponding size of the display area. + * If both width and height are larger than corresponding size of the display area, + * the adjustment will happen at both s, t side. + * + * @param surface The size of the surface. + * @param scissor The display area. + * @param xOffset The offset amount along s axis. + * @param yOffset The offset amount along t axis. + */ + void adjustTextureCoordinates(Rect surface, Rect scissor, float xOffset, float yOffset) { + mCurrentTexCoordinate = TEXTURES.clone(); + + if (surface == null || scissor == null) { + mTextureBuffer.put(mCurrentTexCoordinate); + mTextureBuffer.position(0); + return; + } + + int surfaceWidth = surface.width(); + int surfaceHeight = surface.height(); + int scissorWidth = scissor.width(); + int scissorHeight = scissor.height(); + + if (surfaceWidth > scissorWidth) { + // Calculate the new s pos in pixels. + float pixelS = (float) Math.round((surfaceWidth - scissorWidth) * xOffset); + // Calculate the s pos in texture coordinate. + float coordinateS = pixelS / surfaceWidth; + // Calculate the percentage occupied by the scissor width in surface width. + float surfacePercentageW = (float) scissorWidth / surfaceWidth; + // Need also consider the case if surface height is smaller than scissor height. + if (surfaceHeight < scissorHeight) { + // We will narrow the surface percentage to keep aspect ratio. + surfacePercentageW *= (float) surfaceHeight / scissorHeight; + } + // Determine the final s pos, also limit the legal s pos to prevent from out of range. + float s = coordinateS + surfacePercentageW > 1f ? 1f - surfacePercentageW : coordinateS; + // Traverse the s pos in texture coordinates array and adjust the s pos accordingly. + for (int i = 0; i < mCurrentTexCoordinate.length; i += 2) { + // indices 2, 4 and 6 are the end of s coordinates. + if (i == 2 || i == 4 || i == 6) { + mCurrentTexCoordinate[i] = Math.min(1f, s + surfacePercentageW); + } else { + mCurrentTexCoordinate[i] = s; + } + } + } + + if (surfaceHeight > scissorHeight) { + // Calculate the new t pos in pixels. + float pixelT = (float) Math.round((surfaceHeight - scissorHeight) * yOffset); + // Calculate the t pos in texture coordinate. + float coordinateT = pixelT / surfaceHeight; + // Calculate the percentage occupied by the scissor height in surface height. + float surfacePercentageH = (float) scissorHeight / surfaceHeight; + // Need also consider the case if surface width is smaller than scissor width. + if (surfaceWidth < scissorWidth) { + // We will narrow the surface percentage to keep aspect ratio. + surfacePercentageH *= (float) surfaceWidth / scissorWidth; + } + // Determine the final t pos, also limit the legal t pos to prevent from out of range. + float t = coordinateT + surfacePercentageH > 1f ? 1f - surfacePercentageH : coordinateT; + // Traverse the t pos in texture coordinates array and adjust the t pos accordingly. + for (int i = 1; i < mCurrentTexCoordinate.length; i += 2) { + // indices 1, 3 and 11 are the end of t coordinates. + if (i == 1 || i == 3 || i == 11) { + mCurrentTexCoordinate[i] = Math.min(1f, t + surfacePercentageH); + } else { + mCurrentTexCoordinate[i] = t; + } + } + } + + mTextureBuffer.put(mCurrentTexCoordinate); + mTextureBuffer.position(0); + } + + /** + * Called to dump current state. + * @param prefix prefix. + * @param fd fd. + * @param out out. + * @param args args. + */ + public void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) { + StringBuilder sb = new StringBuilder(); + sb.append('{'); + if (mCurrentTexCoordinate != null) { + for (int i = 0; i < mCurrentTexCoordinate.length; i++) { + sb.append(mCurrentTexCoordinate[i]).append(','); + if (i == mCurrentTexCoordinate.length - 1) { + sb.deleteCharAt(sb.length() - 1); + } + } + } + sb.append('}'); + out.print(prefix); out.print("mTexCoordinates="); out.println(sb.toString()); + } } diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java index 21711fb1890c..93d8dd6146a6 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java @@ -29,6 +29,8 @@ import android.graphics.Rect; import android.util.Log; import android.util.MathUtils; import android.util.Size; +import android.view.DisplayInfo; +import android.view.WindowManager; import com.android.systemui.R; @@ -41,8 +43,8 @@ import java.io.PrintWriter; public class ImageWallpaperRenderer implements GLWallpaperRenderer, ImageRevealHelper.RevealStateListener { private static final String TAG = ImageWallpaperRenderer.class.getSimpleName(); - private static final float SCALE_VIEWPORT_MIN = 0.98f; - private static final float SCALE_VIEWPORT_MAX = 1f; + private static final float SCALE_VIEWPORT_MIN = 1f; + private static final float SCALE_VIEWPORT_MAX = 1.1f; private final WallpaperManager mWallpaperManager; private final ImageGLProgram mProgram; @@ -51,8 +53,13 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer, private final ImageRevealHelper mImageRevealHelper; private SurfaceProxy mProxy; - private Rect mSurfaceSize; + private final Rect mScissor; + private final Rect mSurfaceSize = new Rect(); + private final Rect mViewport = new Rect(); private Bitmap mBitmap; + private boolean mScissorMode; + private float mXOffset; + private float mYOffset; public ImageWallpaperRenderer(Context context, SurfaceProxy proxy) { mWallpaperManager = context.getSystemService(WallpaperManager.class); @@ -60,6 +67,11 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer, Log.w(TAG, "WallpaperManager not available"); } + DisplayInfo displayInfo = new DisplayInfo(); + WindowManager wm = context.getSystemService(WindowManager.class); + wm.getDefaultDisplay().getDisplayInfo(displayInfo); + mScissor = new Rect(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight); + mProxy = proxy; mProgram = new ImageGLProgram(context); mWallpaper = new ImageGLWallpaper(mProgram); @@ -91,7 +103,7 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer, mBitmap = mWallpaperManager.getBitmap(); mWallpaperManager.forgetLoadedWallpaper(); if (mBitmap != null) { - mSurfaceSize = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight()); + mSurfaceSize.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight()); } } return mBitmap != null; @@ -107,13 +119,17 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer, float threshold = mImageProcessHelper.getThreshold(); float reveal = mImageRevealHelper.getReveal(); - glClear(GL_COLOR_BUFFER_BIT); - glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_AOD2OPACITY), 1); glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_PER85), threshold); glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_REVEAL), reveal); - scaleViewport(reveal); + glClear(GL_COLOR_BUFFER_BIT); + // We only need to scale viewport while doing transition. + if (mScissorMode) { + scaleViewport(reveal); + } else { + glViewport(0, 0, mSurfaceSize.width(), mSurfaceSize.height()); + } mWallpaper.useTexture(); mWallpaper.draw(); } @@ -124,6 +140,15 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer, } @Override + public void updateOffsets(float xOffset, float yOffset) { + mXOffset = xOffset; + mYOffset = yOffset; + int left = (int) ((mSurfaceSize.width() - mScissor.width()) * xOffset); + int right = left + mScissor.width(); + mScissor.set(left, mScissor.top, right, mScissor.bottom); + } + + @Override public Size reportSurfaceSize() { return new Size(mSurfaceSize.width(), mSurfaceSize.height()); } @@ -134,15 +159,18 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer, } private void scaleViewport(float reveal) { - int width = mSurfaceSize.width(); - int height = mSurfaceSize.height(); + int left = mScissor.left; + int top = mScissor.top; + int width = mScissor.width(); + int height = mScissor.height(); // Interpolation between SCALE_VIEWPORT_MAX and SCALE_VIEWPORT_MIN by reveal. - float vpScaled = MathUtils.lerp(SCALE_VIEWPORT_MAX, SCALE_VIEWPORT_MIN, reveal); + float vpScaled = MathUtils.lerp(SCALE_VIEWPORT_MIN, SCALE_VIEWPORT_MAX, reveal); // Calculate the offset amount from the lower left corner. - float offset = (SCALE_VIEWPORT_MAX - vpScaled) / 2; + float offset = (SCALE_VIEWPORT_MIN - vpScaled) / 2; // Change the viewport. - glViewport((int) (width * offset), (int) (height * offset), + mViewport.set((int) (left + width * offset), (int) (top + height * offset), (int) (width * vpScaled), (int) (height * vpScaled)); + glViewport(mViewport.left, mViewport.top, mViewport.right, mViewport.bottom); } @Override @@ -152,11 +180,19 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer, @Override public void onRevealStart() { + mScissorMode = true; + // Use current display area of texture. + mWallpaper.adjustTextureCoordinates(mSurfaceSize, mScissor, mXOffset, mYOffset); mProxy.preRender(); } @Override public void onRevealEnd() { + mScissorMode = false; + // reset texture coordinates to use full texture. + mWallpaper.adjustTextureCoordinates(null, null, 0, 0); + // We need draw full texture back before finishing render. + mProxy.requestRender(); mProxy.postRender(); } @@ -164,6 +200,12 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer, public void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) { out.print(prefix); out.print("mProxy="); out.print(mProxy); out.print(prefix); out.print("mSurfaceSize="); out.print(mSurfaceSize); + out.print(prefix); out.print("mScissor="); out.print(mScissor); + out.print(prefix); out.print("mViewport="); out.print(mViewport); + out.print(prefix); out.print("mScissorMode="); out.print(mScissorMode); + out.print(prefix); out.print("mXOffset="); out.print(mXOffset); + out.print(prefix); out.print("mYOffset="); out.print(mYOffset); out.print(prefix); out.print("threshold="); out.print(mImageProcessHelper.getThreshold()); + mWallpaper.dump(prefix, fd, out, args); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index fd76a79eab2e..ca12deb3904e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -43,6 +43,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.widget.LockPatternUtils; +import com.android.internal.widget.ViewClippingUtil; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.settingslib.Utils; @@ -118,6 +119,13 @@ public class KeyguardIndicationController implements StateListener, private final DevicePolicyManager mDevicePolicyManager; private boolean mDozing; + private final ViewClippingUtil.ClippingParameters mClippingParams = + new ViewClippingUtil.ClippingParameters() { + @Override + public boolean shouldFinish(View view) { + return view == mIndicationArea; + } + }; /** * Creates a new KeyguardIndicationController and registers callbacks. @@ -413,6 +421,7 @@ public class KeyguardIndicationController implements StateListener, R.integer.wired_charging_keyguard_text_animation_duration_down); textView.animate().cancel(); float translation = textView.getTranslationY(); + ViewClippingUtil.setClippingDeactivated(textView, true, mClippingParams); textView.animate() .translationYBy(yTranslation) .setInterpolator(Interpolators.LINEAR) @@ -434,6 +443,8 @@ public class KeyguardIndicationController implements StateListener, @Override public void onAnimationEnd(Animator animation) { if (mCancelled) { + ViewClippingUtil.setClippingDeactivated(textView, false, + mClippingParams); return; } textView.animate() @@ -445,6 +456,12 @@ public class KeyguardIndicationController implements StateListener, public void onAnimationCancel(Animator animation) { textView.setTranslationY(translation); } + + @Override + public void onAnimationEnd(Animator animation) { + ViewClippingUtil.setClippingDeactivated(textView, false, + mClippingParams); + } }); } }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java index 905a8e68f3d1..4ea1ed5b9451 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java @@ -320,7 +320,7 @@ public class NotificationLockscreenUserManagerImpl implements private boolean hideSilentNotificationsOnLockscreen() { return Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 0) == 0; + Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1) == 0; } private void setShowLockscreenNotifications(boolean show) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java index a4965ba59c6a..f5016da29ad7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java @@ -73,8 +73,7 @@ public class FloatingRotationButton implements RotationButton { return false; } mIsShowing = true; - int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; + int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(mDiameter, mDiameter, mMargin, mMargin, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, flags, PixelFormat.TRANSLUCENT); 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 4e4d6a42c4b6..e3dcbeb0ce65 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -303,6 +303,8 @@ public class NotificationPanelView extends PanelView implements private int mCurrentPanelAlpha; private final Paint mAlphaPaint = new Paint(); private Runnable mPanelAlphaEndAction; + private float mBottomAreaShadeAlpha; + private final ValueAnimator mBottomAreaShadeAlphaAnimator; private AnimatorListenerAdapter mAnimatorListenerAdapter = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -366,6 +368,14 @@ public class NotificationPanelView extends PanelView implements mPulseExpansionHandler = pulseExpansionHandler; mThemeResId = context.getThemeResId(); dynamicPrivacyController.addListener(this); + + mBottomAreaShadeAlphaAnimator = ValueAnimator.ofFloat(1f, 0); + mBottomAreaShadeAlphaAnimator.addUpdateListener(animation -> { + mBottomAreaShadeAlpha = (float) animation.getAnimatedValue(); + updateKeyguardBottomAreaAlpha(); + }); + mBottomAreaShadeAlphaAnimator.setDuration(160); + mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT); } /** @@ -1368,10 +1378,20 @@ public class NotificationPanelView extends PanelView implements updateDozingVisibilities(false /* animate */); } + maybeAnimateBottomAreaAlpha(); resetHorizontalPanelPosition(); updateQsState(); } + private void maybeAnimateBottomAreaAlpha() { + mBottomAreaShadeAlphaAnimator.cancel(); + if (mBarState == StatusBarState.SHADE_LOCKED) { + mBottomAreaShadeAlphaAnimator.start(); + } else { + mBottomAreaShadeAlpha = 1f; + } + } + private final Runnable mAnimateKeyguardStatusViewInvisibleEndRunnable = new Runnable() { @Override public void run() { @@ -1980,6 +2000,7 @@ public class NotificationPanelView extends PanelView implements ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f, 0f, 1f, getExpandedFraction()); float alpha = Math.min(expansionAlpha, 1 - getQsExpansionFraction()); + alpha *= mBottomAreaShadeAlpha; mKeyguardBottomArea.setAffordanceAlpha(alpha); mKeyguardBottomArea.setImportantForAccessibility(alpha == 0f ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS @@ -2890,6 +2911,10 @@ public class NotificationPanelView extends PanelView implements mNotificationStackScroller.setDark(mDozing, animate, wakeUpTouchLocation); mKeyguardBottomArea.setDozing(mDozing, animate); + if (dozing) { + mBottomAreaShadeAlphaAnimator.cancel(); + } + if (mBarState == StatusBarState.KEYGUARD || mBarState == StatusBarState.SHADE_LOCKED) { updateDozingVisibilities(animate); diff --git a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml index f1d2e0b27353..96ed7b4cc353 100644 --- a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml +++ b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml @@ -37,6 +37,15 @@ {@link Window#setEnsuringNavigationBarContrastWhenTransparent}. --> <bool name="config_navBarNeedsScrim">false</bool> + <!-- Controls the opacity of the navigation bar depending on the visibility of the + various workspace stacks. + 0 - Nav bar is always opaque when either the freeform stack or docked stack is visible. + 1 - Nav bar is always translucent when the freeform stack is visible, otherwise always + opaque. + 2 - Nav bar is never forced opaque. + --> + <integer name="config_navBarOpacityMode">2</integer> + <!-- Controls whether seamless rotation should be allowed even though the navbar can move (which normally prevents seamless rotation). --> <bool name="config_allowSeamlessRotationDespiteNavBarMoving">true</bool> diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 0a7684553c08..7569363a7134 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -201,7 +201,7 @@ public class AppOpsService extends IAppOpsService.Stub { @VisibleForTesting final SparseArray<UidState> mUidStates = new SparseArray<>(); - private final HistoricalRegistry mHistoricalRegistry = new HistoricalRegistry(this); + final HistoricalRegistry mHistoricalRegistry = new HistoricalRegistry(this); long mLastRealtime; diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java index 69a1c9f584cb..9cf342c0e4fb 100644 --- a/services/core/java/com/android/server/appop/HistoricalRegistry.java +++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java @@ -108,6 +108,12 @@ import java.util.concurrent.TimeUnit; * must be called with the mInMemoryLock, xxxDMLocked suffix means the method * must be called with the mOnDiskLock and mInMemoryLock locks acquired in that * exact order. + * <p> + * INITIALIZATION: We can initialize persistence only after the system is ready + * as we need to check the optional configuration override from the settings + * database which is not initialized at the time the app ops service is created. + * This means that all entry points that touch persistence should be short + * circuited via isPersistenceInitialized() check. */ // TODO (bug:122218838): Make sure we handle start of epoch time // TODO (bug:122218838): Validate changed time is handled correctly @@ -177,14 +183,33 @@ final class HistoricalRegistry { // Object managing persistence (read/write) @GuardedBy("mOnDiskLock") - private Persistence mPersistence = new Persistence(mBaseSnapshotInterval, - mIntervalCompressionMultiplier); + private Persistence mPersistence; HistoricalRegistry(@NonNull Object lock) { mInMemoryLock = lock; - if (mMode != AppOpsManager.HISTORICAL_MODE_DISABLED) { - synchronized (mOnDiskLock) { - synchronized (mInMemoryLock) { + } + + void systemReady(@NonNull ContentResolver resolver) { + final Uri uri = Settings.Global.getUriFor(Settings.Global.APPOP_HISTORY_PARAMETERS); + resolver.registerContentObserver(uri, false, new ContentObserver( + FgThread.getHandler()) { + @Override + public void onChange(boolean selfChange) { + updateParametersFromSetting(resolver); + } + }); + + updateParametersFromSetting(resolver); + + synchronized (mOnDiskLock) { + synchronized (mInMemoryLock) { + if (mMode != AppOpsManager.HISTORICAL_MODE_DISABLED) { + // Can be uninitialized if there is no config in the settings table. + if (!isPersistenceInitializedMLocked()) { + mPersistence = new Persistence(mBaseSnapshotInterval, + mIntervalCompressionMultiplier); + } + // When starting always adjust history to now. final long lastPersistTimeMills = mPersistence.getLastPersistTimeMillisDLocked(); @@ -197,16 +222,8 @@ final class HistoricalRegistry { } } - void systemReady(@NonNull ContentResolver resolver) { - updateParametersFromSetting(resolver); - final Uri uri = Settings.Global.getUriFor(Settings.Global.APPOP_HISTORY_PARAMETERS); - resolver.registerContentObserver(uri, false, new ContentObserver( - FgThread.getHandler()) { - @Override - public void onChange(boolean selfChange) { - updateParametersFromSetting(resolver); - } - }); + private boolean isPersistenceInitializedMLocked() { + return mPersistence != null; } private void updateParametersFromSetting(@NonNull ContentResolver resolver) { @@ -274,6 +291,11 @@ final class HistoricalRegistry { makeRelativeToEpochStart(currentOps, nowMillis); currentOps.accept(visitor); + if(isPersistenceInitializedMLocked()) { + Slog.e(LOG_TAG, "Interaction before persistence initialized"); + return; + } + final List<HistoricalOps> ops = mPersistence.readHistoryDLocked(); if (ops != null) { // TODO (bug:122218838): Make sure this is properly dumped @@ -302,12 +324,21 @@ final class HistoricalRegistry { void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName, @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis, @OpFlags int flags, @NonNull RemoteCallback callback) { - final HistoricalOps result = new HistoricalOps(beginTimeMillis, endTimeMillis); - mPersistence.collectHistoricalOpsDLocked(result, uid, packageName, opNames, - beginTimeMillis, endTimeMillis, flags); - final Bundle payload = new Bundle(); - payload.putParcelable(AppOpsManager.KEY_HISTORICAL_OPS, result); - callback.sendResult(payload); + synchronized (mOnDiskLock) { + synchronized (mInMemoryLock) { + if (!isPersistenceInitializedMLocked()) { + Slog.e(LOG_TAG, "Interaction before persistence initialized"); + callback.sendResult(new Bundle()); + return; + } + final HistoricalOps result = new HistoricalOps(beginTimeMillis, endTimeMillis); + mPersistence.collectHistoricalOpsDLocked(result, uid, packageName, opNames, + beginTimeMillis, endTimeMillis, flags); + final Bundle payload = new Bundle(); + payload.putParcelable(AppOpsManager.KEY_HISTORICAL_OPS, result); + callback.sendResult(payload); + } + } } void getHistoricalOps(int uid, @NonNull String packageName, @@ -331,6 +362,12 @@ final class HistoricalRegistry { boolean collectOpsFromDisk; synchronized (mInMemoryLock) { + if (!isPersistenceInitializedMLocked()) { + Slog.e(LOG_TAG, "Interaction before persistence initialized"); + callback.sendResult(new Bundle()); + return; + } + currentOps = getUpdatedPendingHistoricalOpsMLocked(currentTimeMillis); if (!(inMemoryAdjBeginTimeMillis >= currentOps.getEndTimeMillis() || inMemoryAdjEndTimeMillis <= currentOps.getBeginTimeMillis())) { @@ -374,6 +411,10 @@ final class HistoricalRegistry { @UidState int uidState, @OpFlags int flags) { synchronized (mInMemoryLock) { if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) { + if (!isPersistenceInitializedMLocked()) { + Slog.e(LOG_TAG, "Interaction before persistence initialized"); + return; + } getUpdatedPendingHistoricalOpsMLocked(System.currentTimeMillis()) .increaseAccessCount(op, uid, packageName, uidState, flags, 1); } @@ -384,6 +425,10 @@ final class HistoricalRegistry { @UidState int uidState, @OpFlags int flags) { synchronized (mInMemoryLock) { if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) { + if (!isPersistenceInitializedMLocked()) { + Slog.e(LOG_TAG, "Interaction before persistence initialized"); + return; + } getUpdatedPendingHistoricalOpsMLocked(System.currentTimeMillis()) .increaseRejectCount(op, uid, packageName, uidState, flags, 1); } @@ -394,6 +439,10 @@ final class HistoricalRegistry { @UidState int uidState, @OpFlags int flags, long increment) { synchronized (mInMemoryLock) { if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) { + if (!isPersistenceInitializedMLocked()) { + Slog.e(LOG_TAG, "Interaction before persistence initialized"); + return; + } getUpdatedPendingHistoricalOpsMLocked(System.currentTimeMillis()) .increaseAccessDuration(op, uid, packageName, uidState, flags, increment); } @@ -404,6 +453,8 @@ final class HistoricalRegistry { long baseSnapshotInterval, long intervalCompressionMultiplier) { synchronized (mOnDiskLock) { synchronized (mInMemoryLock) { + // NOTE: We allow this call if persistence is not initialized as + // it is a part of the persistence initialization process. boolean resampleHistory = false; Slog.i(LOG_TAG, "New history parameters: mode:" + AppOpsManager.historicalModeToString(mMode) + " baseSnapshotInterval:" @@ -412,7 +463,7 @@ final class HistoricalRegistry { if (mMode != mode) { mMode = mode; if (mMode == AppOpsManager.HISTORICAL_MODE_DISABLED) { - clearHistoryOnDiskLocked(); + clearHistoryOnDiskDLocked(); } } if (mBaseSnapshotInterval != baseSnapshotInterval) { @@ -433,6 +484,10 @@ final class HistoricalRegistry { void offsetHistory(long offsetMillis) { synchronized (mOnDiskLock) { synchronized (mInMemoryLock) { + if (!isPersistenceInitializedMLocked()) { + Slog.e(LOG_TAG, "Interaction before persistence initialized"); + return; + } final List<HistoricalOps> history = mPersistence.readHistoryDLocked(); clearHistory(); if (history != null) { @@ -453,6 +508,10 @@ final class HistoricalRegistry { void addHistoricalOps(HistoricalOps ops) { final List<HistoricalOps> pendingWrites; synchronized (mInMemoryLock) { + if (!isPersistenceInitializedMLocked()) { + Slog.e(LOG_TAG, "Interaction before persistence initialized"); + return; + } // The history files start from mBaseSnapshotInterval - take this into account. ops.offsetBeginAndEndTime(mBaseSnapshotInterval); mPendingWrites.offerFirst(ops); @@ -468,6 +527,10 @@ final class HistoricalRegistry { } void resetHistoryParameters() { + if (!isPersistenceInitializedMLocked()) { + Slog.e(LOG_TAG, "Interaction before persistence initialized"); + return; + } setHistoryParameters(DEFAULT_MODE, DEFAULT_SNAPSHOT_INTERVAL_MILLIS, DEFAULT_COMPRESSION_STEP); } @@ -475,6 +538,10 @@ final class HistoricalRegistry { void clearHistory(int uid, String packageName) { synchronized (mOnDiskLock) { synchronized (mInMemoryLock) { + if (!isPersistenceInitializedMLocked()) { + Slog.e(LOG_TAG, "Interaction before persistence initialized"); + return; + } if (mMode != AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) { return; } @@ -493,18 +560,24 @@ final class HistoricalRegistry { void clearHistory() { synchronized (mOnDiskLock) { - clearHistoryOnDiskLocked(); + synchronized (mInMemoryLock) { + if (!isPersistenceInitializedMLocked()) { + Slog.e(LOG_TAG, "Interaction before persistence initialized"); + return; + } + clearHistoryOnDiskDLocked(); + } } } - private void clearHistoryOnDiskLocked() { + private void clearHistoryOnDiskDLocked() { BackgroundThread.getHandler().removeMessages(MSG_WRITE_PENDING_HISTORY); synchronized (mInMemoryLock) { mCurrentHistoricalOps = null; mNextPersistDueTimeMillis = System.currentTimeMillis(); mPendingWrites.clear(); } - mPersistence.clearHistoryDLocked(); + Persistence.clearHistoryDLocked(); } private @NonNull HistoricalOps getUpdatedPendingHistoricalOpsMLocked(long now) { @@ -639,7 +712,7 @@ final class HistoricalRegistry { mIntervalCompressionMultiplier = intervalCompressionMultiplier; } - private final AtomicDirectory mHistoricalAppOpsDir = new AtomicDirectory( + private static final AtomicDirectory sHistoricalAppOpsDir = new AtomicDirectory( new File(new File(Environment.getDataSystemDirectory(), "appops"), "history")); private File generateFile(@NonNull File baseDir, int depth) { @@ -663,8 +736,8 @@ final class HistoricalRegistry { persistHistoricalOpsDLocked(historicalOps); } - void clearHistoryDLocked() { - mHistoricalAppOpsDir.delete(); + static void clearHistoryDLocked() { + sHistoricalAppOpsDir.delete(); } void persistHistoricalOpsDLocked(@NonNull List<HistoricalOps> ops) { @@ -673,8 +746,8 @@ final class HistoricalRegistry { enforceOpsWellFormed(ops); } try { - final File newBaseDir = mHistoricalAppOpsDir.startWrite(); - final File oldBaseDir = mHistoricalAppOpsDir.getBackupDirectory(); + final File newBaseDir = sHistoricalAppOpsDir.startWrite(); + final File oldBaseDir = sHistoricalAppOpsDir.getBackupDirectory(); final HistoricalFilesInvariant filesInvariant; if (DEBUG) { filesInvariant = new HistoricalFilesInvariant(); @@ -686,10 +759,10 @@ final class HistoricalRegistry { if (DEBUG) { filesInvariant.stopTracking(newBaseDir); } - mHistoricalAppOpsDir.finishWrite(); + sHistoricalAppOpsDir.finishWrite(); } catch (Throwable t) { wtf("Failed to write historical app ops, restoring backup", t, null); - mHistoricalAppOpsDir.failWrite(); + sHistoricalAppOpsDir.failWrite(); } } @@ -715,22 +788,36 @@ final class HistoricalRegistry { long getLastPersistTimeMillisDLocked() { File baseDir = null; try { - baseDir = mHistoricalAppOpsDir.startRead(); + baseDir = sHistoricalAppOpsDir.startRead(); final File[] files = baseDir.listFiles(); if (files != null && files.length > 0) { - final Set<File> historyFiles = new ArraySet<>(); - Collections.addAll(historyFiles, files); - for (int i = 0;; i++) { - final File file = generateFile(baseDir, i); - if (historyFiles.contains(file)) { - return file.lastModified(); + File shortestFile = null; + for (File candidate : files) { + final String candidateName = candidate.getName(); + if (!candidateName.endsWith(HISTORY_FILE_SUFFIX)) { + continue; + } + if (shortestFile == null) { + shortestFile = candidate; + } else if (candidateName.length() < shortestFile.getName().length()) { + shortestFile = candidate; } } + if (shortestFile == null) { + return 0; + } + final String shortestNameNoExtension = shortestFile.getName() + .replace(HISTORY_FILE_SUFFIX, ""); + try { + return Long.parseLong(shortestNameNoExtension); + } catch (NumberFormatException e) { + return 0; + } } - mHistoricalAppOpsDir.finishRead(); + sHistoricalAppOpsDir.finishRead(); } catch (Throwable e) { wtf("Error reading historical app ops. Deleting history.", e, baseDir); - mHistoricalAppOpsDir.delete(); + sHistoricalAppOpsDir.delete(); } return 0; } @@ -755,7 +842,7 @@ final class HistoricalRegistry { long filterBeginTimeMillis, long filterEndTimeMillis, @OpFlags int filterFlags) { File baseDir = null; try { - baseDir = mHistoricalAppOpsDir.startRead(); + baseDir = sHistoricalAppOpsDir.startRead(); final HistoricalFilesInvariant filesInvariant; if (DEBUG) { filesInvariant = new HistoricalFilesInvariant(); @@ -770,11 +857,11 @@ final class HistoricalRegistry { if (DEBUG) { filesInvariant.stopTracking(baseDir); } - mHistoricalAppOpsDir.finishRead(); + sHistoricalAppOpsDir.finishRead(); return ops; } catch (Throwable t) { wtf("Error reading historical app ops. Deleting history.", t, baseDir); - mHistoricalAppOpsDir.delete(); + sHistoricalAppOpsDir.delete(); } return null; } @@ -1241,7 +1328,7 @@ final class HistoricalRegistry { private void writeHistoricalOpsDLocked(@Nullable List<HistoricalOps> allOps, long intervalOverflowMillis, @NonNull File file) throws IOException { - final FileOutputStream output = mHistoricalAppOpsDir.openWrite(file); + final FileOutputStream output = sHistoricalAppOpsDir.openWrite(file); try { final XmlSerializer serializer = Xml.newSerializer(); serializer.setOutput(output, StandardCharsets.UTF_8.name()); @@ -1263,9 +1350,9 @@ final class HistoricalRegistry { } serializer.endTag(null, TAG_HISTORY); serializer.endDocument(); - mHistoricalAppOpsDir.closeWrite(output); + sHistoricalAppOpsDir.closeWrite(output); } catch (IOException e) { - mHistoricalAppOpsDir.failWrite(output); + sHistoricalAppOpsDir.failWrite(output); throw e; } } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 21f01ff38a0e..7badc7a43774 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -198,6 +198,8 @@ public class DisplayPolicy { private static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0; // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque. private static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1; + // Nav bar is never forced opaque. + private static final int NAV_BAR_FORCE_TRANSPARENT = 2; /** * These are the system UI flags that, when changing, can cause the layout @@ -3288,8 +3290,10 @@ public class DisplayPolicy { : mTopFullscreenOpaqueWindowState; vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); - final int dockedVis = mStatusBarController.applyTranslucentFlagLw( + int dockedVis = mStatusBarController.applyTranslucentFlagLw( mTopDockedOpaqueWindowState, 0, 0); + dockedVis = mNavigationBarController.applyTranslucentFlagLw( + mTopDockedOpaqueWindowState, dockedVis, 0); final boolean fullscreenDrawsStatusBarBackground = drawsStatusBarBackground(vis, mTopFullscreenOpaqueWindowState); @@ -3297,6 +3301,8 @@ public class DisplayPolicy { drawsStatusBarBackground(dockedVis, mTopDockedOpaqueWindowState); final boolean fullscreenDrawsNavBarBackground = drawsNavigationBarBackground(vis, mTopFullscreenOpaqueWindowState); + final boolean dockedDrawsNavigationBarBackground = + drawsNavigationBarBackground(dockedVis, mTopDockedOpaqueWindowState); // prevent status bar interaction from clearing certain flags int type = win.getAttrs().type; @@ -3321,7 +3327,7 @@ public class DisplayPolicy { } vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing, - fullscreenDrawsNavBarBackground); + fullscreenDrawsNavBarBackground, dockedDrawsNavigationBarBackground); // update status bar boolean immersiveSticky = @@ -3439,8 +3445,14 @@ public class DisplayPolicy { */ private int configureNavBarOpacity(int visibility, boolean dockedStackVisible, boolean freeformStackVisible, boolean isDockedDividerResizing, - boolean fullscreenDrawsBackground) { - if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { + boolean fullscreenDrawsBackground, boolean dockedDrawsNavigationBarBackground) { + if (mNavBarOpacityMode == NAV_BAR_FORCE_TRANSPARENT) { + if (fullscreenDrawsBackground && dockedDrawsNavigationBarBackground) { + visibility = setNavBarTransparentFlag(visibility); + } else if (dockedStackVisible) { + visibility = setNavBarOpaqueFlag(visibility); + } + } else if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) { visibility = setNavBarOpaqueFlag(visibility); } else if (fullscreenDrawsBackground) { diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java index d90117905de6..552058f6e8c2 100644 --- a/services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsServiceTest.java @@ -37,12 +37,15 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.Process; import android.os.RemoteCallback; +import android.provider.Settings; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -68,11 +71,14 @@ public class AppOpsServiceTest { private File mAppOpsFile; private Context mContext; private Handler mHandler; + private AppOpsManager mAppOpsManager; private AppOpsService mAppOpsService; private String mMyPackageName; private int mMyUid; private long mTestStartMillis; + private static String sDefaultAppopHistoryParameters; + @Before public void setUp() { mContext = InstrumentationRegistry.getTargetContext(); @@ -88,11 +94,29 @@ public class AppOpsServiceTest { mMyPackageName = mContext.getOpPackageName(); mMyUid = Process.myUid(); + mAppOpsManager = mContext.getSystemService(AppOpsManager.class); mAppOpsService = new AppOpsService(mAppOpsFile, mHandler); + mAppOpsService.mHistoricalRegistry.systemReady(mContext.getContentResolver()); mAppOpsService.mContext = mContext; mTestStartMillis = System.currentTimeMillis(); } + @BeforeClass + public static void configureDesiredAppopHistoryParameters() { + final Context context = InstrumentationRegistry.getTargetContext(); + sDefaultAppopHistoryParameters = Settings.Global.getString(context.getContentResolver(), + Settings.Global.APPOP_HISTORY_PARAMETERS); + Settings.Global.putString(InstrumentationRegistry.getTargetContext().getContentResolver(), + Settings.Global.APPOP_HISTORY_PARAMETERS, null); + } + + @AfterClass + public static void restoreDefaultAppopHistoryParameters() { + Settings.Global.putString(InstrumentationRegistry.getTargetContext().getContentResolver(), + Settings.Global.APPOP_HISTORY_PARAMETERS, + sDefaultAppopHistoryParameters); + } + @Test public void testGetOpsForPackage_noOpsLogged() { assertThat(getLoggedOps()).isNull(); |