summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/RedactingFileDescriptor.java26
-rw-r--r--core/java/android/view/IWindowSession.aidl2
-rw-r--r--core/java/android/view/View.java15
-rw-r--r--core/java/com/android/internal/app/PlatLogoActivity.java505
-rw-r--r--core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java83
-rw-r--r--core/java/com/android/internal/policy/DecorView.java5
-rw-r--r--core/res/AndroidManifest.xml4
-rw-r--r--core/res/res/drawable-nodpi/android_logotype.xml42
-rw-r--r--core/res/res/drawable-nodpi/platlogo.xml26
-rw-r--r--core/res/res/layout/platlogo_layout.xml50
-rw-r--r--core/res/res/values/config.xml4
-rw-r--r--core/res/res/values/symbols.xml5
-rw-r--r--core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java80
-rw-r--r--packages/EasterEgg/AndroidManifest.xml40
-rw-r--r--packages/EasterEgg/res/drawable/icon_bg.xml2
-rw-r--r--packages/EasterEgg/res/drawable/p_icon.xml (renamed from packages/EasterEgg/res/drawable/icon.xml)0
-rw-r--r--packages/EasterEgg/res/drawable/pixel_bg.xml27
-rw-r--r--packages/EasterEgg/res/drawable/q.xml27
-rw-r--r--packages/EasterEgg/res/drawable/q_icon.xml19
-rw-r--r--packages/EasterEgg/res/drawable/q_smaller.xml23
-rw-r--r--packages/EasterEgg/res/layout/activity_quares.xml46
-rw-r--r--packages/EasterEgg/res/values-night/q_colors.xml22
-rw-r--r--packages/EasterEgg/res/values/q_colors.xml31
-rw-r--r--packages/EasterEgg/res/values/q_puzzles.xml214
-rw-r--r--packages/EasterEgg/res/values/strings.xml11
-rw-r--r--packages/EasterEgg/res/values/styles.xml12
-rw-r--r--packages/EasterEgg/src/com/android/egg/quares/Quare.kt168
-rw-r--r--packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt312
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java6
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java66
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java65
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java2
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java10
-rw-r--r--services/core/java/com/android/server/locksettings/PasswordSlotManager.java2
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerServiceImpl.java44
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java34
-rw-r--r--services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java16
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java83
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyInternal.java27
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java46
-rw-r--r--services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java72
-rw-r--r--services/core/java/com/android/server/policy/TEST_MAPPING3
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java13
-rw-r--r--services/core/java/com/android/server/wm/ScreenRotationAnimation.java1
-rw-r--r--services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java7
-rw-r--r--services/java/com/android/server/SystemServer.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java16
-rw-r--r--telephony/java/com/android/internal/telephony/CarrierAppUtils.java12
82 files changed, 2306 insertions, 478 deletions
diff --git a/core/java/android/os/RedactingFileDescriptor.java b/core/java/android/os/RedactingFileDescriptor.java
index 4e5eaac3442f..a1ed2146b38e 100644
--- a/core/java/android/os/RedactingFileDescriptor.java
+++ b/core/java/android/os/RedactingFileDescriptor.java
@@ -35,7 +35,7 @@ import java.util.Arrays;
/**
* Variant of {@link FileDescriptor} that allows its creator to specify regions
- * that should be redacted (appearing as zeros to the reader).
+ * that should be redacted.
*
* @hide
*/
@@ -44,13 +44,16 @@ public class RedactingFileDescriptor {
private static final boolean DEBUG = true;
private volatile long[] mRedactRanges;
+ private volatile long[] mFreeOffsets;
private FileDescriptor mInner = null;
private ParcelFileDescriptor mOuter = null;
- private RedactingFileDescriptor(Context context, File file, int mode, long[] redactRanges)
+ private RedactingFileDescriptor(
+ Context context, File file, int mode, long[] redactRanges, long[] freeOffsets)
throws IOException {
mRedactRanges = checkRangesArgument(redactRanges);
+ mFreeOffsets = freeOffsets;
try {
try {
@@ -88,13 +91,17 @@ public class RedactingFileDescriptor {
*
* @param file The underlying file to open.
* @param mode The {@link ParcelFileDescriptor} mode to open with.
- * @param redactRanges List of file offsets that should be redacted, stored
+ * @param redactRanges List of file ranges that should be redacted, stored
* as {@code [start1, end1, start2, end2, ...]}. Start values are
* inclusive and end values are exclusive.
+ * @param freePositions List of file offsets at which the four byte value 'free' should be
+ * written instead of zeros within parts of the file covered by {@code redactRanges}.
+ * Non-redacted bytes will not be modified even if covered by a 'free'. This is
+ * useful for overwriting boxes in ISOBMFF files with padding data.
*/
public static ParcelFileDescriptor open(Context context, File file, int mode,
- long[] redactRanges) throws IOException {
- return new RedactingFileDescriptor(context, file, mode, redactRanges).mOuter;
+ long[] redactRanges, long[] freePositions) throws IOException {
+ return new RedactingFileDescriptor(context, file, mode, redactRanges, freePositions).mOuter;
}
/**
@@ -169,6 +176,15 @@ public class RedactingFileDescriptor {
for (long j = start; j < end; j++) {
data[(int) (j - offset)] = 0;
}
+ // Overwrite data at 'free' offsets within the redaction ranges.
+ for (long freeOffset : mFreeOffsets) {
+ final long freeEnd = freeOffset + 4;
+ final long redactFreeStart = Math.max(freeOffset, start);
+ final long redactFreeEnd = Math.min(freeEnd, end);
+ for (long j = redactFreeStart; j < redactFreeEnd; j++) {
+ data[(int) (j - offset)] = (byte) "free".charAt((int) (j - freeOffset));
+ }
+ }
}
return n;
}
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index caab00c3863e..775ec9920575 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -300,5 +300,5 @@ interface IWindowSession {
/**
* Called when the system gesture exclusion has changed.
*/
- void reportSystemGestureExclusionChanged(IWindow window, in List<Rect> exclusionRects);
+ oneway void reportSystemGestureExclusionChanged(IWindow window, in List<Rect> exclusionRects);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bf6191ec61eb..1275e46ed421 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -967,6 +967,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
static boolean sBrokenInsetsDispatch;
+ /**
+ * Prior to Q, calling
+ * {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)}
+ * did not call update the window format so the opacity of the background was not correctly
+ * applied to the window. Some applications rely on this misbehavior to work properly.
+ * <p>
+ * From Q, {@link com.android.internal.policy.DecorView#setBackgroundDrawable(Drawable)} is
+ * the same as {@link com.android.internal.policy.DecorView#setWindowBackground(Drawable)}
+ * which updates the window format.
+ * @hide
+ */
+ protected static boolean sBrokenWindowBackground;
+
/** @hide */
@IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
@Retention(RetentionPolicy.SOURCE)
@@ -5104,6 +5117,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
sBrokenInsetsDispatch = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL
|| targetSdkVersion < Build.VERSION_CODES.Q;
+ sBrokenWindowBackground = targetSdkVersion < Build.VERSION_CODES.Q;
+
sCompatibilityDone = true;
}
}
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index 57785443919e..157e0a74712b 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -16,252 +16,167 @@
package com.android.internal.app;
+import android.animation.ObjectAnimator;
import android.animation.TimeAnimator;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Intent;
+import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.ColorFilter;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
+import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
-import android.view.MotionEvent.PointerCoords;
import android.view.View;
-import android.widget.FrameLayout;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import com.android.internal.R;
import org.json.JSONObject;
+/**
+ * @hide
+ */
public class PlatLogoActivity extends Activity {
- FrameLayout layout;
- TimeAnimator anim;
- PBackground bg;
-
- private class PBackground extends Drawable {
- private float maxRadius, radius, x, y, dp;
- private int[] palette;
- private int darkest;
- private float offset;
-
- public PBackground() {
- randomizePalette();
- }
-
- /**
- * set inner radius of "p" logo
- */
- public void setRadius(float r) {
- this.radius = Math.max(48*dp, r);
- }
-
- /**
- * move the "p"
- */
- public void setPosition(float x, float y) {
- this.x = x;
- this.y = y;
- }
-
- /**
- * for animating the "p"
- */
- public void setOffset(float o) {
- this.offset = o;
- }
-
- /**
- * rough luminance calculation
- * https://www.w3.org/TR/AERT/#color-contrast
- */
- public float lum(int rgb) {
- return ((Color.red(rgb) * 299f) + (Color.green(rgb) * 587f) + (Color.blue(rgb) * 114f)) / 1000f;
- }
-
- /**
- * create a random evenly-spaced color palette
- * guaranteed to contrast!
- */
- public void randomizePalette() {
- final int slots = 2 + (int)(Math.random() * 2);
- float[] color = new float[] { (float) Math.random() * 360f, 1f, 1f };
- palette = new int[slots];
- darkest = 0;
- for (int i=0; i<slots; i++) {
- palette[i] = Color.HSVToColor(color);
- color[0] = (color[0] + 360f/slots) % 360f;
- if (lum(palette[i]) < lum(palette[darkest])) darkest = i;
- }
-
- final StringBuilder str = new StringBuilder();
- for (int c : palette) {
- str.append(String.format("#%08x ", c));
- }
- Log.v("PlatLogoActivity", "color palette: " + str);
- }
-
- @Override
- public void draw(Canvas canvas) {
- if (dp == 0) dp = getResources().getDisplayMetrics().density;
- final float width = canvas.getWidth();
- final float height = canvas.getHeight();
- if (radius == 0) {
- setPosition(width / 2, height / 2);
- setRadius(width / 6);
- }
- final float inner_w = radius * 0.667f;
-
- final Paint paint = new Paint();
- paint.setStrokeCap(Paint.Cap.BUTT);
- canvas.translate(x, y);
-
- Path p = new Path();
- p.moveTo(-radius, height);
- p.lineTo(-radius, 0);
- p.arcTo(-radius, -radius, radius, radius, -180, 270, false);
- p.lineTo(-radius, radius);
-
- float w = Math.max(canvas.getWidth(), canvas.getHeight()) * 1.414f;
- paint.setStyle(Paint.Style.FILL);
-
- int i=0;
- while (w > radius*2 + inner_w*2) {
- paint.setColor(0xFF000000 | palette[i % palette.length]);
- // for a slower but more complete version:
- // paint.setStrokeWidth(w);
- // canvas.drawPath(p, paint);
- canvas.drawOval(-w/2, -w/2, w/2, w/2, paint);
- w -= inner_w * (1.1f + Math.sin((i/20f + offset) * 3.14159f));
- i++;
- }
-
- // the innermost circle needs to be a constant color to avoid rapid flashing
- paint.setColor(0xFF000000 | palette[(darkest+1) % palette.length]);
- canvas.drawOval(-radius, -radius, radius, radius, paint);
-
- p.reset();
- p.moveTo(-radius, height);
- p.lineTo(-radius, 0);
- p.arcTo(-radius, -radius, radius, radius, -180, 270, false);
- p.lineTo(-radius + inner_w, radius);
-
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeWidth(inner_w*2);
- paint.setColor(palette[darkest]);
- canvas.drawPath(p, paint);
- paint.setStrokeWidth(inner_w);
- paint.setColor(0xFFFFFFFF);
- canvas.drawPath(p, paint);
- }
-
- @Override
- public void setAlpha(int alpha) {
-
- }
-
- @Override
- public void setColorFilter(ColorFilter colorFilter) {
-
- }
+ ImageView mZeroView, mOneView;
+ BackslashDrawable mBackslash;
+ int mClicks;
+
+ static final Paint sPaint = new Paint();
+ static {
+ sPaint.setStyle(Paint.Style.STROKE);
+ sPaint.setStrokeWidth(4f);
+ sPaint.setStrokeCap(Paint.Cap.SQUARE);
+ }
- @Override
- public int getOpacity() {
- return 0;
+ @Override
+ protected void onPause() {
+ if (mBackslash != null) {
+ mBackslash.stopAnimating();
}
+ mClicks = 0;
+ super.onPause();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ final float dp = getResources().getDisplayMetrics().density;
- layout = new FrameLayout(this);
- setContentView(layout);
+ getWindow().getDecorView().setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+ getWindow().setNavigationBarColor(0);
+ getWindow().setStatusBarColor(0);
- bg = new PBackground();
- layout.setBackground(bg);
+ getActionBar().hide();
- final ContentResolver cr = getContentResolver();
+ setContentView(R.layout.platlogo_layout);
- layout.setOnTouchListener(new View.OnTouchListener() {
- final String TOUCH_STATS = "touch.stats";
+ mBackslash = new BackslashDrawable((int) (50 * dp));
- final PointerCoords pc0 = new PointerCoords();
- final PointerCoords pc1 = new PointerCoords();
+ mOneView = findViewById(R.id.one);
+ mOneView.setImageDrawable(new OneDrawable());
+ mZeroView = findViewById(R.id.zero);
+ mZeroView.setImageDrawable(new ZeroDrawable());
- double pressure_min, pressure_max;
- int maxPointers;
- int tapCount;
+ final ViewGroup root = (ViewGroup) mOneView.getParent();
+ root.setClipChildren(false);
+ root.setBackground(mBackslash);
+ root.getBackground().setAlpha(0x20);
+ View.OnTouchListener tl = new View.OnTouchListener() {
+ float mOffsetX, mOffsetY;
+ long mClickTime;
+ ObjectAnimator mRotAnim;
@Override
public boolean onTouch(View v, MotionEvent event) {
- final float pressure = event.getPressure();
+ measureTouchPressure(event);
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
- pressure_min = pressure_max = pressure;
- // fall through
- case MotionEvent.ACTION_MOVE:
- if (pressure < pressure_min) pressure_min = pressure;
- if (pressure > pressure_max) pressure_max = pressure;
- final int pc = event.getPointerCount();
- if (pc > maxPointers) maxPointers = pc;
- if (pc > 1) {
- event.getPointerCoords(0, pc0);
- event.getPointerCoords(1, pc1);
- bg.setRadius((float) Math.hypot(pc0.x - pc1.x, pc0.y - pc1.y) / 2f);
+ v.animate().scaleX(1.1f).scaleY(1.1f);
+ v.getParent().bringChildToFront(v);
+ mOffsetX = event.getRawX() - v.getX();
+ mOffsetY = event.getRawY() - v.getY();
+ long now = System.currentTimeMillis();
+ if (now - mClickTime < 350) {
+ mRotAnim = ObjectAnimator.ofFloat(v, View.ROTATION,
+ v.getRotation(), v.getRotation() + 3600);
+ mRotAnim.setDuration(10000);
+ mRotAnim.start();
+ mClickTime = 0;
+ } else {
+ mClickTime = now;
}
break;
- case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_MOVE:
+ v.setX(event.getRawX() - mOffsetX);
+ v.setY(event.getRawY() - mOffsetY);
+ v.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE);
+ break;
case MotionEvent.ACTION_UP:
- try {
- final String touchDataJson = Settings.System.getString(cr, TOUCH_STATS);
- final JSONObject touchData = new JSONObject(
- touchDataJson != null ? touchDataJson : "{}");
- if (touchData.has("min")) {
- pressure_min = Math.min(pressure_min, touchData.getDouble("min"));
- }
- if (touchData.has("max")) {
- pressure_max = Math.max(pressure_max, touchData.getDouble("max"));
- }
- touchData.put("min", pressure_min);
- touchData.put("max", pressure_max);
- Settings.System.putString(cr, TOUCH_STATS, touchData.toString());
- } catch (Exception e) {
- Log.e("PlatLogoActivity", "Can't write touch settings", e);
- }
-
- if (maxPointers == 1) {
- tapCount ++;
- if (tapCount < 7) {
- bg.randomizePalette();
- } else {
- launchNextStage();
- }
- } else {
- tapCount = 0;
- }
- maxPointers = 0;
+ v.performClick();
+ // fall through
+ case MotionEvent.ACTION_CANCEL:
+ v.animate().scaleX(1f).scaleY(1f);
+ if (mRotAnim != null) mRotAnim.cancel();
+ testOverlap();
break;
}
return true;
}
- });
+ };
+
+ findViewById(R.id.one).setOnTouchListener(tl);
+ findViewById(R.id.zero).setOnTouchListener(tl);
+ findViewById(R.id.text).setOnTouchListener(tl);
+ }
+
+ private void testOverlap() {
+ final float width = mZeroView.getWidth();
+ final float targetX = mZeroView.getX() + width * .2f;
+ final float targetY = mZeroView.getY() + width * .3f;
+ if (Math.hypot(targetX - mOneView.getX(), targetY - mOneView.getY()) < width * .2f
+ && Math.abs(mOneView.getRotation() % 360 - 315) < 15) {
+ mOneView.animate().x(mZeroView.getX() + width * .2f);
+ mOneView.animate().y(mZeroView.getY() + width * .3f);
+ mOneView.setRotation(mOneView.getRotation() % 360);
+ mOneView.animate().rotation(315);
+ mOneView.performHapticFeedback(HapticFeedbackConstants.CONFIRM);
+
+ mBackslash.startAnimating();
+
+ mClicks++;
+ if (mClicks >= 7) {
+ launchNextStage();
+ }
+ } else {
+ mBackslash.stopAnimating();
+ }
}
private void launchNextStage() {
final ContentResolver cr = getContentResolver();
- if (Settings.System.getLong(cr, Settings.System.EGG_MODE, 0) == 0) {
+ if (Settings.System.getLong(cr, "egg_mode" /* Settings.System.EGG_MODE */, 0) == 0) {
// For posterity: the moment this user unlocked the easter egg
try {
Settings.System.putLong(cr,
- Settings.System.EGG_MODE,
+ "egg_mode", // Settings.System.EGG_MODE,
System.currentTimeMillis());
} catch (RuntimeException e) {
- Log.e("PlatLogoActivity", "Can't write settings", e);
+ Log.e("com.android.internal.app.PlatLogoActivity", "Can't write settings", e);
}
}
try {
@@ -270,36 +185,206 @@ public class PlatLogoActivity extends Activity {
| Intent.FLAG_ACTIVITY_CLEAR_TASK)
.addCategory("com.android.internal.category.PLATLOGO"));
} catch (ActivityNotFoundException ex) {
- Log.e("PlatLogoActivity", "No more eggs.");
+ Log.e("com.android.internal.app.PlatLogoActivity", "No more eggs.");
}
finish();
}
+ static final String TOUCH_STATS = "touch.stats";
+ double mPressureMin = 0, mPressureMax = -1;
+
+ private void measureTouchPressure(MotionEvent event) {
+ final float pressure = event.getPressure();
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ if (mPressureMax < 0) {
+ mPressureMin = mPressureMax = pressure;
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (pressure < mPressureMin) mPressureMin = pressure;
+ if (pressure > mPressureMax) mPressureMax = pressure;
+ break;
+ }
+ }
+
+ private void syncTouchPressure() {
+ try {
+ final String touchDataJson = Settings.System.getString(
+ getContentResolver(), TOUCH_STATS);
+ final JSONObject touchData = new JSONObject(
+ touchDataJson != null ? touchDataJson : "{}");
+ if (touchData.has("min")) {
+ mPressureMin = Math.min(mPressureMin, touchData.getDouble("min"));
+ }
+ if (touchData.has("max")) {
+ mPressureMax = Math.max(mPressureMax, touchData.getDouble("max"));
+ }
+ if (mPressureMax >= 0) {
+ touchData.put("min", mPressureMin);
+ touchData.put("max", mPressureMax);
+ Settings.System.putString(getContentResolver(), TOUCH_STATS, touchData.toString());
+ }
+ } catch (Exception e) {
+ Log.e("com.android.internal.app.PlatLogoActivity", "Can't write touch settings", e);
+ }
+ }
+
@Override
public void onStart() {
super.onStart();
+ syncTouchPressure();
+ }
- bg.randomizePalette();
+ @Override
+ public void onStop() {
+ syncTouchPressure();
+ super.onStop();
+ }
- anim = new TimeAnimator();
- anim.setTimeListener(
- new TimeAnimator.TimeListener() {
- @Override
- public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
- bg.setOffset((float) totalTime / 60000f);
- bg.invalidateSelf();
- }
- });
+ static class ZeroDrawable extends Drawable {
+ int mTintColor;
+
+ @Override
+ public void draw(Canvas canvas) {
+ sPaint.setColor(mTintColor | 0xFF000000);
+
+ canvas.save();
+ canvas.scale(canvas.getWidth() / 24f, canvas.getHeight() / 24f);
+
+ canvas.drawCircle(12f, 12f, 10f, sPaint);
+ canvas.restore();
+ }
- anim.start();
+ @Override
+ public void setAlpha(int alpha) { }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) { }
+
+ @Override
+ public void setTintList(ColorStateList tint) {
+ mTintColor = tint.getDefaultColor();
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
}
- @Override
- public void onStop() {
- if (anim != null) {
- anim.cancel();
- anim = null;
+ static class OneDrawable extends Drawable {
+ int mTintColor;
+
+ @Override
+ public void draw(Canvas canvas) {
+ sPaint.setColor(mTintColor | 0xFF000000);
+
+ canvas.save();
+ canvas.scale(canvas.getWidth() / 24f, canvas.getHeight() / 24f);
+
+ final Path p = new Path();
+ p.moveTo(12f, 21.83f);
+ p.rLineTo(0f, -19.67f);
+ p.rLineTo(-5f, 0f);
+ canvas.drawPath(p, sPaint);
+ canvas.restore();
+ }
+
+ @Override
+ public void setAlpha(int alpha) { }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) { }
+
+ @Override
+ public void setTintList(ColorStateList tint) {
+ mTintColor = tint.getDefaultColor();
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+ }
+
+ private static class BackslashDrawable extends Drawable implements TimeAnimator.TimeListener {
+ Bitmap mTile;
+ Paint mPaint = new Paint();
+ BitmapShader mShader;
+ TimeAnimator mAnimator = new TimeAnimator();
+ Matrix mMatrix = new Matrix();
+
+ public void draw(Canvas canvas) {
+ canvas.drawPaint(mPaint);
+ }
+
+ BackslashDrawable(int width) {
+ mTile = Bitmap.createBitmap(width, width, Bitmap.Config.ALPHA_8);
+ mAnimator.setTimeListener(this);
+
+ final Canvas tileCanvas = new Canvas(mTile);
+ final float w = tileCanvas.getWidth();
+ final float h = tileCanvas.getHeight();
+
+ final Path path = new Path();
+ path.moveTo(0, 0);
+ path.lineTo(w / 2, 0);
+ path.lineTo(w, h / 2);
+ path.lineTo(w, h);
+ path.close();
+
+ path.moveTo(0, h / 2);
+ path.lineTo(w / 2, h);
+ path.lineTo(0, h);
+ path.close();
+
+ final Paint slashPaint = new Paint();
+ slashPaint.setAntiAlias(true);
+ slashPaint.setStyle(Paint.Style.FILL);
+ slashPaint.setColor(0xFF000000);
+ tileCanvas.drawPath(path, slashPaint);
+
+ //mPaint.setColor(0xFF0000FF);
+ mShader = new BitmapShader(mTile, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
+ mPaint.setShader(mShader);
+ }
+
+ public void startAnimating() {
+ if (!mAnimator.isStarted()) {
+ mAnimator.start();
+ }
+ }
+
+ public void stopAnimating() {
+ if (mAnimator.isStarted()) {
+ mAnimator.cancel();
+ }
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mPaint.setAlpha(alpha);
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ mPaint.setColorFilter(colorFilter);
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
+ if (mShader != null) {
+ mMatrix.postTranslate(deltaTime / 4f, 0);
+ mShader.setLocalMatrix(mMatrix);
+ invalidateSelf();
+ }
}
- super.onStop();
}
}
+
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 4daddfbfb204..8dc47a401580 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -186,6 +186,89 @@ public final class SystemUiDeviceConfigFlags {
*/
public static final String BRIGHTLINE_FALSING_MANAGER_ENABLED =
"brightline_falsing_manager_enabled";
+ /**
+ * (float) Maximum fraction of the screen required to qualify as a real swipe.
+ */
+ public static final String BRIGHTLINE_FALSING_DISTANCE_SCREEN_FRACTION_MAX_DISTANCE =
+ "brightline_falsing_distance_screen_fraction_max_distance";
+
+ /**
+ * (float) Multiplier for swipe velocity to convert it to pixels for a fling.
+ */
+ public static final String BRIGHTLINE_FALSING_DISTANCE_VELOCITY_TO_DISTANCE =
+ "brightline_falsing_distance_velcoity_to_distance";
+
+ /**
+ * (float) How far, in inches, must a fling travel horizontally to qualify as intentional.
+ */
+ public static final String BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_FLING_THRESHOLD_IN =
+ "brightline_falsing_distance_horizontal_fling_threshold_in";
+
+ /**
+ * (float) Maximum fraction of the screen required to qualify as a real swipe.
+ */
+ public static final String BRIGHTLINE_FALSING_DISTANCE_VERTICAL_FLING_THRESHOLD_IN =
+ "brightline_falsing_distance_vertical_fling_threshold_in";
+
+ /**
+ * (float) How far, in inches, must a continuous swipe travel horizontally to be intentional.
+ */
+ public static final String BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_SWIPE_THRESHOLD_IN =
+ "brightline_falsing_distance_horizontal_swipe_threshold_in";
+
+ /**
+ * (float) How far, in inches, must a continuous swipe travel vertically to be intentional.
+ */
+ public static final String BRIGHTLINE_FALSING_DISTANCE_VERTICAL_SWIPE_THRESHOLD_IN =
+ "brightline_falsing_distance_horizontal_swipe_threshold_in";
+
+ /**
+ * (float) Percentage of swipe with the proximity sensor covered that triggers a higher
+ * swipe distance requirement.
+ */
+ public static final String BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD =
+ "brightline_falsing_proximity_percent_covered_threshold";
+
+ /**
+ * (float) Angle, in radians, that a swipe can vary from horizontal and sill be intentional.
+ */
+ public static final String BRIGHTLINE_FALSING_DIAGONAL_HORIZONTAL_ANGLE_RANGE =
+ "brightline_falsing_diagonal_horizontal_angle_range";
+
+ /**
+ * (float) Angle, in radians, that a swipe can vary from vertical and sill be intentional.
+ */
+ public static final String BRIGHTLINE_FALSING_DIAGONAL_VERTICAL_ANGLE_RANGE =
+ "brightline_falsing_diagonal_horizontal_angle_range";
+
+ /**
+ * (float) Distance, in inches, that a swipe is allowed to vary in the horizontal direction for
+ * horizontal swipes.
+ */
+ public static final String BRIGHTLINE_FALSING_ZIGZAG_X_PRIMARY_DEVIANCE =
+ "brightline_falsing_zigzag_x_primary_deviance";
+
+ /**
+ * (float) Distance, in inches, that a swipe is allowed to vary in the vertical direction for
+ * vertical swipes.
+ */
+ public static final String BRIGHTLINE_FALSING_ZIGZAG_Y_PRIMARY_DEVIANCE =
+ "brightline_falsing_zigzag_y_primary_deviance";
+
+ /**
+ * (float) Distance, in inches, that a swipe is allowed to vary in the horizontal direction for
+ * horizontal swipes.
+ */
+ public static final String BRIGHTLINE_FALSING_ZIGZAG_X_SECONDARY_DEVIANCE =
+ "brightline_falsing_zigzag_x_secondary_deviance";
+
+ /**
+ * (float) Distance, in inches, that a swipe is allowed to vary in the vertical direction for
+ * vertical swipes.
+ */
+ public static final String BRIGHTLINE_FALSING_ZIGZAG_Y_SECONDARY_DEVIANCE =
+ "brightline_falsing_zigzag_y_secondary_deviance";
+
private SystemUiDeviceConfigFlags() { }
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index fe66cf9aab7d..7c52a40d4494 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -983,13 +983,14 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
@Override
public void setBackgroundDrawable(Drawable background) {
-
// TODO: This should route through setWindowBackground, but late in the release to make this
// change.
if (mOriginalBackgroundDrawable != background) {
mOriginalBackgroundDrawable = background;
updateBackgroundDrawable();
- drawableChanged();
+ if (!View.sBrokenWindowBackground) {
+ drawableChanged();
+ }
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index fef4dcd3b9f1..02eed9a7bcf7 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4616,8 +4616,9 @@
android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.PlatLogoActivity"
- android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
+ android:theme="@style/Theme.DeviceDefault.DayNight"
android:configChanges="orientation|keyboardHidden"
+ android:icon="@drawable/platlogo"
android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.DisableCarModeActivity"
@@ -4939,6 +4940,7 @@
<service
android:name="com.android.server.autofill.AutofillCompatAccessibilityService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
+ android:visibleToInstantApps="true"
android:exported="true">
<meta-data
android:name="android.accessibilityservice"
diff --git a/core/res/res/drawable-nodpi/android_logotype.xml b/core/res/res/drawable-nodpi/android_logotype.xml
new file mode 100644
index 000000000000..bd298e48ef34
--- /dev/null
+++ b/core/res/res/drawable-nodpi/android_logotype.xml
@@ -0,0 +1,42 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="290dp"
+ android:height="64dp"
+ android:viewportWidth="290.0"
+ android:viewportHeight="64.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M21.81,28.91c-7.44,0,-12.45,5.85,-12.45,13.37c0,7.52,5.01,13.37,12.45,13.37s12.45,-5.85,12.45,-13.37 C34.26,34.76,29.24,28.91,21.81,28.91 M20.13,20.55c6.02,0,11.03,3.09,13.37,6.43v-5.6l9.19,0l0,41.78l-6.24,0 c-1.63,0,-2.95,-1.32,-2.95,-2.95v-2.65C31.17,60.91,26.15,64,20.14,64C8.69,64,0,54.23,0,42.28C0,30.33,8.69,20.55,20.13,20.55"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M53.13,21.39l9.19,0l0,5.68c2.5,-4.18,7.27,-6.52,12.7,-6.52c9.69,0,15.96,6.85,15.96,17.46l0,25.15l-6.24,0 c-1.63,0,-2.95,-1.32,-2.95,-2.95l0,-20.7c0,-6.6,-3.34,-10.61,-8.69,-10.61c-6.1,0,-10.78,4.76,-10.78,13.7l0,20.55l-6.25,0 c-1.63,0,-2.95,-1.32,-2.95,-2.95L53.13,21.39z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M120.06,28.91c-7.43,0,-12.45,5.85,-12.45,13.37c0,7.52,5.01,13.37,12.45,13.37c7.43,0,12.45,-5.85,12.45,-13.37 C132.51,34.76,127.5,28.91,120.06,28.91 M118.39,20.55c6.02,0,11.03,3.09,13.37,6.43l0,-26.49l9.19,0l0,62.66h-6.24 c-1.63,0,-2.95,-1.32,-2.95,-2.95v-2.65c-2.34,3.34,-7.35,6.43,-13.37,6.43c-11.45,0,-20.14,-9.77,-20.14,-21.72 C98.25,30.33,106.94,20.55,118.39,20.55"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M151.39,21.39l9.19,0v7.44c1.59,-4.76,6.27,-7.86,11.03,-7.86c1.17,0,2.34,0.08,3.59,0.34v9.44c-1.59,-0.5,-2.92,-0.75,-4.59,-0.75 c-5.26,0,-10.03,4.43,-10.03,12.78l0,20.39l-6.24,0c-1.63,0,-2.95,-1.32,-2.95,-2.95L151.39,21.39z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M199.98,55.48c7.35,0,12.53,-5.77,12.53,-13.2c0,-7.44,-5.18,-13.2,-12.53,-13.2c-7.44,0,-12.62,5.77,-12.62,13.2 C187.37,49.71,192.55,55.48,199.98,55.48 M199.98,64c-12.37,0,-21.89,-9.61,-21.89,-21.72c0,-12.12,9.52,-21.73,21.89,-21.73 c12.37,0,21.89,9.61,21.89,21.73C221.87,54.39,212.35,64,199.98,64"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M229.32,21.39l9.19,0l0,41.78l-6.24,0c-1.63,0,-2.95,-1.32,-2.95,-2.95L229.32,21.39z M233.92,12.28 c-3.34,0,-6.18,-2.76,-6.18,-6.18c0,-3.34,2.84,-6.1,6.18,-6.1c3.43,0,6.1,2.76,6.1,6.1C240.02,9.53,237.34,12.28,233.92,12.28"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M267.87,28.91c-7.43,0,-12.45,5.85,-12.45,13.37c0,7.52,5.01,13.37,12.45,13.37c7.44,0,12.45,-5.85,12.45,-13.37 C280.32,34.76,275.31,28.91,267.87,28.91 M266.2,20.55c6.02,0,11.03,3.09,13.37,6.43l0,-26.49l9.19,0l0,62.66l-6.24,0 c-1.63,0,-2.95,-1.32,-2.95,-2.95v-2.65c-2.34,3.34,-7.35,6.43,-13.37,6.43c-11.44,0,-20.14,-9.77,-20.14,-21.72S254.76,20.55,266.2,20.55"/>
+</vector>
diff --git a/core/res/res/drawable-nodpi/platlogo.xml b/core/res/res/drawable-nodpi/platlogo.xml
index f5bbadcce06b..19a296a0e46b 100644
--- a/core/res/res/drawable-nodpi/platlogo.xml
+++ b/core/res/res/drawable-nodpi/platlogo.xml
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 2018 The Android Open Source Project
+Copyright (C) 2015 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.
@@ -13,21 +13,15 @@ Copyright (C) 2018 The Android Open Source Project
See the License for the specific language governing permissions and
limitations under the License.
-->
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:name="vector"
- android:width="640dp"
- android:height="640dp"
- android:viewportWidth="64"
- android:viewportHeight="64">
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
<path
- android:name="bg"
- android:pathData="M 27 43 L 32 43 C 38.075 43 43 38.075 43 32 C 43 25.925 38.075 21 32 21 C 25.925 21 21 25.925 21 32 L 21 64"
- android:strokeColor="#6823a1"
- android:strokeWidth="16"/>
+ android:fillColor="#FF000000"
+ android:pathData="M19.45,22.89l-10.250001,-10.249999l-2.6599998,2.6599998l-1.77,-1.7600002l4.43,-4.4300003l12.0199995,12.0199995l-1.7699986,1.7600002z"/>
<path
- android:name="fg"
- android:pathData="M 29 43 L 32 43 C 38.075 43 43 38.075 43 32 C 43 25.925 38.075 21 32 21 C 25.925 21 21 25.925 21 32 L 21 64"
- android:strokeColor="#ff0000"
- android:strokeWidth="8"/>
+ android:fillColor="#FF000000"
+ android:pathData="M12,6a6,6 0,1 1,-6 6,6 6,0 0,1 6,-6m0,-2.5A8.5,8.5 0,1 0,20.5 12,8.51 8.51,0 0,0 12,3.5Z"/>
</vector>
diff --git a/core/res/res/layout/platlogo_layout.xml b/core/res/res/layout/platlogo_layout.xml
new file mode 100644
index 000000000000..4a4ad751e421
--- /dev/null
+++ b/core/res/res/layout/platlogo_layout.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:background="@android:color/transparent">
+ <ImageView
+ android:id="@+id/text"
+ android:layout_width="400dp"
+ android:layout_height="wrap_content"
+ android:translationY="-100dp"
+ android:adjustViewBounds="true"
+ android:layout_marginBottom="-80dp"
+ android:layout_centerInParent="true"
+ android:src="@drawable/android_logotype"
+ android:tint="?android:attr/textColorPrimary"
+ />
+ <ImageView
+ android:id="@+id/one"
+ android:layout_width="200dp"
+ android:layout_height="200dp"
+ android:layout_marginLeft="24dp"
+ android:layout_below="@id/text"
+ android:layout_alignLeft="@id/text"
+ android:tint="?android:attr/textColorPrimary"
+ />
+ <ImageView
+ android:id="@+id/zero"
+ android:layout_width="200dp"
+ android:layout_height="200dp"
+ android:layout_marginRight="34dp"
+ android:layout_below="@id/text"
+ android:layout_alignRight="@id/text"
+ android:tint="?android:attr/textColorPrimary"
+ />
+</RelativeLayout>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f92a58ad471e..eb09d3fa4356 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4162,6 +4162,10 @@
one bar higher than they actually are -->
<bool name="config_inflateSignalStrength">false</bool>
+ <!-- Contains a blacklist of apps that should not get pre-installed carrier app permission
+ grants, even if the UICC claims that the app should be privileged. See b/138150105 -->
+ <string-array name="config_restrictedPreinstalledCarrierApps" translatable="false"/>
+
<!-- Sharesheet: define a max number of targets per application for new shortcuts-based direct share introduced in Q -->
<integer name="config_maxShortcutTargetsPerApp">3</integer>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c10d32cf6807..646c4ce434d3 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3819,4 +3819,9 @@
<java-symbol type="string" name="config_defaultSupervisionProfileOwnerComponent" />
<java-symbol type="bool" name="config_inflateSignalStrength" />
+ <java-symbol type="array" name="config_restrictedPreinstalledCarrierApps" />
+
+ <java-symbol type="drawable" name="android_logotype" />
+ <java-symbol type="layout" name="platlogo_layout" />
+
</resources>
diff --git a/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java b/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java
index d5163e193510..eff4826040f4 100644
--- a/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java
+++ b/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java
@@ -64,7 +64,7 @@ public class RedactingFileDescriptorTest {
@Test
public void testSingleByte() throws Exception {
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY,
- new long[] { 10, 11 }).getFileDescriptor();
+ new long[] { 10, 11 }, new long[] {}).getFileDescriptor();
final byte[] buf = new byte[1_000];
assertEquals(buf.length, Os.read(fd, buf, 0, buf.length));
@@ -80,7 +80,7 @@ public class RedactingFileDescriptorTest {
@Test
public void testRanges() throws Exception {
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY,
- new long[] { 100, 200, 300, 400 }).getFileDescriptor();
+ new long[] { 100, 200, 300, 400 }, new long[] {}).getFileDescriptor();
final byte[] buf = new byte[10];
assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 90));
@@ -102,7 +102,7 @@ public class RedactingFileDescriptorTest {
@Test
public void testEntireFile() throws Exception {
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY,
- new long[] { 0, 5_000_000 }).getFileDescriptor();
+ new long[] { 0, 5_000_000 }, new long[] {}).getFileDescriptor();
try (FileInputStream in = new FileInputStream(fd)) {
int val;
@@ -115,7 +115,7 @@ public class RedactingFileDescriptorTest {
@Test
public void testReadWrite() throws Exception {
final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
- new long[] { 100, 200, 300, 400 }).getFileDescriptor();
+ new long[] { 100, 200, 300, 400 }, new long[] {}).getFileDescriptor();
// Redacted at first
final byte[] buf = new byte[10];
@@ -168,4 +168,76 @@ public class RedactingFileDescriptorTest {
assertArrayEquals(new long[] { 100, 200 },
removeRange(new long[] { 100, 200 }, 150, 150));
}
+
+ @Test
+ public void testFreeAtStart() throws Exception {
+ final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
+ new long[] { 1, 10 }, new long[] {1}).getFileDescriptor();
+
+ final byte[] buf = new byte[10];
+ assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
+ assertArrayEquals(
+ new byte[] { 64, (byte) 'f', (byte) 'r', (byte) 'e', (byte) 'e', 0, 0, 0, 0, 0 },
+ buf);
+ }
+
+ @Test
+ public void testFreeAtOffset() throws Exception {
+ final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
+ new long[] { 1, 10 }, new long[] {3}).getFileDescriptor();
+
+ final byte[] buf = new byte[10];
+ assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
+ assertArrayEquals(
+ new byte[] { 64, 0, 0, (byte) 'f', (byte) 'r', (byte) 'e', (byte) 'e', 0, 0, 0 },
+ buf);
+ }
+
+ @Test
+ public void testFreeAcrossRedactionStart() throws Exception {
+ final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
+ new long[] { 1, 10 }, new long[] {0}).getFileDescriptor();
+
+ final byte[] buf = new byte[10];
+ assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
+ assertArrayEquals(
+ new byte[] { 64, (byte) 'r', (byte) 'e', (byte) 'e', 0, 0, 0, 0, 0, 0 },
+ buf);
+ }
+
+ @Test
+ public void testFreeAcrossRedactionEnd() throws Exception {
+ final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
+ new long[] { 1, 3 }, new long[] {2}).getFileDescriptor();
+
+ final byte[] buf = new byte[10];
+ assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
+ assertArrayEquals(
+ new byte[] { 64, 0, (byte) 'f', 64, 64, 64, 64, 64, 64, 64 },
+ buf);
+ }
+
+ @Test
+ public void testFreeOutsideRedaction() throws Exception {
+ final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
+ new long[] { 1, 8 }, new long[] { 8 }).getFileDescriptor();
+
+ final byte[] buf = new byte[10];
+ assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
+ assertArrayEquals(
+ new byte[] { 64, 0, 0, 0, 0, 0, 0, 0, 64, 64 },
+ buf);
+ }
+
+ @Test
+ public void testFreeMultipleRedactions() throws Exception {
+ final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
+ new long[] { 1, 2, 3, 4 }, new long[] { 0 }).getFileDescriptor();
+
+ final byte[] buf = new byte[10];
+ assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
+ assertArrayEquals(
+ new byte[] { 64, (byte) 'r', 64, (byte) 'e', 64, 64, 64, 64, 64, 64 },
+ buf);
+ }
}
diff --git a/packages/EasterEgg/AndroidManifest.xml b/packages/EasterEgg/AndroidManifest.xml
index c7dd40d7afdb..7f76a4529963 100644
--- a/packages/EasterEgg/AndroidManifest.xml
+++ b/packages/EasterEgg/AndroidManifest.xml
@@ -1,40 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2018 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.
--->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.egg"
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="28" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application
- android:icon="@drawable/icon"
+ android:icon="@drawable/q_icon"
android:label="@string/app_name">
+ <activity android:name=".quares.QuaresActivity"
+ android:icon="@drawable/q_icon"
+ android:label="@string/q_egg_name"
+ android:theme="@style/QuaresTheme">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <!-- <category android:name="android.intent.category.LAUNCHER" /> -->
+ <category android:name="com.android.internal.category.PLATLOGO" />
+ </intent-filter>
+ </activity>
<activity
android:name=".paint.PaintActivity"
android:configChanges="orientation|keyboardHidden|screenSize|uiMode"
- android:label="@string/app_name"
+ android:icon="@drawable/p_icon"
+ android:label="@string/p_egg_name"
android:theme="@style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.DEFAULT" />
- <!--<category android:name="android.intent.category.LAUNCHER" />-->
- <category android:name="com.android.internal.category.PLATLOGO" />
+
+ <!-- <category android:name="android.intent.category.DEFAULT" /> -->
+ <!-- <category android:name="android.intent.category.LAUNCHER" /> -->
+ <!-- <category android:name="com.android.internal.category.PLATLOGO" /> -->
</intent-filter>
</activity>
</application>
diff --git a/packages/EasterEgg/res/drawable/icon_bg.xml b/packages/EasterEgg/res/drawable/icon_bg.xml
index c1553ce50946..659f98be4f43 100644
--- a/packages/EasterEgg/res/drawable/icon_bg.xml
+++ b/packages/EasterEgg/res/drawable/icon_bg.xml
@@ -15,4 +15,4 @@
limitations under the License.
-->
<color xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="#C5E1A5" /> \ No newline at end of file
+ android:color="@color/q_clue_text" />
diff --git a/packages/EasterEgg/res/drawable/icon.xml b/packages/EasterEgg/res/drawable/p_icon.xml
index 2306b7b554c5..2306b7b554c5 100644
--- a/packages/EasterEgg/res/drawable/icon.xml
+++ b/packages/EasterEgg/res/drawable/p_icon.xml
diff --git a/packages/EasterEgg/res/drawable/pixel_bg.xml b/packages/EasterEgg/res/drawable/pixel_bg.xml
new file mode 100644
index 000000000000..4d4a113cce53
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/pixel_bg.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:exitFadeDuration="100">
+ <item android:state_pressed="true">
+ <shape><solid android:color="@color/red"/></shape>
+ </item>
+ <item android:state_checked="true">
+ <shape><solid android:color="@color/pixel_on"/></shape>
+ </item>
+ <item>
+ <shape><solid android:color="@color/pixel_off"/></shape>
+ </item>
+</selector> \ No newline at end of file
diff --git a/packages/EasterEgg/res/drawable/q.xml b/packages/EasterEgg/res/drawable/q.xml
new file mode 100644
index 000000000000..75baa47e3aa6
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/q.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/q_icon_fg"
+ android:pathData="M19.45,22.89l-10.250001,-10.249999l-2.6599998,2.6599998l-1.77,-1.7600002l4.43,-4.4300003l12.0199995,12.0199995l-1.7699986,1.7600002z"/>
+ <path
+ android:fillColor="@color/q_icon_fg"
+ android:pathData="M12,6a6,6 0,1 1,-6 6,6 6,0 0,1 6,-6m0,-2.5A8.5,8.5 0,1 0,20.5 12,8.51 8.51,0 0,0 12,3.5Z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/q_icon.xml b/packages/EasterEgg/res/drawable/q_icon.xml
new file mode 100644
index 000000000000..ef4b0a362043
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/q_icon.xml
@@ -0,0 +1,19 @@
+<!--
+ 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.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/icon_bg"/>
+ <foreground android:drawable="@drawable/q_smaller"/>
+</adaptive-icon>
diff --git a/packages/EasterEgg/res/drawable/q_smaller.xml b/packages/EasterEgg/res/drawable/q_smaller.xml
new file mode 100644
index 000000000000..c71dff094235
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/q_smaller.xml
@@ -0,0 +1,23 @@
+<!--
+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.
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:insetBottom="5dp"
+ android:insetLeft="5dp"
+ android:insetRight="5dp"
+ android:insetTop="5dp"
+ android:drawable="@drawable/q" />
diff --git a/packages/EasterEgg/res/layout/activity_quares.xml b/packages/EasterEgg/res/layout/activity_quares.xml
new file mode 100644
index 000000000000..dcc90f6f77ae
--- /dev/null
+++ b/packages/EasterEgg/res/layout/activity_quares.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:animateLayoutChanges="true"
+ tools:context="com.android.egg.quares.QuaresActivity">
+
+ <GridLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:alignmentMode="alignBounds"
+ android:id="@+id/grid"
+ />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/label"
+ android:layout_gravity="center_horizontal|bottom"
+ android:gravity="center"
+ android:textSize="18dp"
+ android:visibility="gone"
+ android:drawablePadding="8dp"
+ android:padding="12dp"
+ android:backgroundTint="@color/q_clue_bg_correct"
+ android:textColor="@color/q_clue_text"
+ android:layout_marginBottom="48dp"
+ android:elevation="30dp"
+ />
+</FrameLayout>
diff --git a/packages/EasterEgg/res/values-night/q_colors.xml b/packages/EasterEgg/res/values-night/q_colors.xml
new file mode 100644
index 000000000000..191bd944b7dc
--- /dev/null
+++ b/packages/EasterEgg/res/values-night/q_colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 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.
+-->
+<resources>
+ <color name="pixel_off">#000000</color>
+ <color name="pixel_on">#FFFFFF</color>
+
+ <color name="q_clue_bg">@color/navy</color>
+ <color name="q_clue_text">@color/tan</color>
+</resources> \ No newline at end of file
diff --git a/packages/EasterEgg/res/values/q_colors.xml b/packages/EasterEgg/res/values/q_colors.xml
new file mode 100644
index 000000000000..5e92c84fd97d
--- /dev/null
+++ b/packages/EasterEgg/res/values/q_colors.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 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.
+-->
+<resources>
+ <color name="emerald">#3ddc84</color>
+ <color name="red">#f8c734</color>
+ <color name="navy">#073042</color>
+ <color name="vapor">#d7effe</color>
+ <color name="tan">#eff7cf</color>
+
+ <color name="pixel_off">#FFFFFF</color>
+ <color name="pixel_on">#000000</color>
+
+ <color name="q_clue_bg">@color/tan</color>
+ <color name="q_clue_text">@color/navy</color>
+ <color name="q_clue_bg_correct">@color/emerald</color>
+
+ <color name="q_icon_fg">@color/emerald</color>
+</resources>
diff --git a/packages/EasterEgg/res/values/q_puzzles.xml b/packages/EasterEgg/res/values/q_puzzles.xml
new file mode 100644
index 000000000000..7c2eff152ffe
--- /dev/null
+++ b/packages/EasterEgg/res/values/q_puzzles.xml
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string-array name="puzzles">
+
+ <item>q</item>
+ <item>q</item>
+ <item>q</item>
+ <item>q</item>
+ <item>q</item>
+
+ <item>android:drawable/ic_info</item>
+
+ <item>android:drawable/stat_sys_adb</item>
+ <item>android:drawable/stat_sys_battery</item>
+ <item>android:drawable/stat_sys_phone_call</item>
+ <item>android:drawable/stat_sys_certificate_info</item>
+ <item>android:drawable/stat_sys_data_bluetooth</item>
+ <item>android:drawable/stat_sys_data_usb</item>
+ <item>android:drawable/stat_sys_download</item>
+ <item>android:drawable/stat_sys_gps_on</item>
+ <item>android:drawable/stat_sys_phone_call</item>
+ <item>android:drawable/stat_sys_tether_wifi</item>
+ <item>android:drawable/stat_sys_throttled</item>
+ <item>android:drawable/stat_sys_upload</item>
+
+ <item>android:drawable/stat_notify_car_mode</item>
+ <item>android:drawable/stat_notify_chat</item>
+ <item>android:drawable/stat_notify_disk_full</item>
+ <item>android:drawable/stat_notify_email_generic</item>
+ <item>android:drawable/stat_notify_error</item>
+ <item>android:drawable/stat_notify_gmail</item>
+ <item>android:drawable/stat_notify_missed_call</item>
+ <item>android:drawable/stat_notify_mmcc_indication_icn</item>
+ <item>android:drawable/stat_notify_more</item>
+ <item>android:drawable/stat_notify_rssi_in_range</item>
+ <item>android:drawable/stat_notify_sdcard</item>
+ <item>android:drawable/stat_notify_sdcard_prepare</item>
+ <item>android:drawable/stat_notify_sdcard_usb</item>
+ <item>android:drawable/stat_notify_sim_toolkit</item>
+ <item>android:drawable/stat_notify_sync</item>
+ <item>android:drawable/stat_notify_sync_anim0</item>
+ <item>android:drawable/stat_notify_sync_error</item>
+ <item>android:drawable/stat_notify_voicemail</item>
+
+ <item>android:drawable/ic_audio_alarm</item>
+ <item>android:drawable/ic_audio_alarm_mute</item>
+ <item>android:drawable/ic_bluetooth_share_icon</item>
+ <item>android:drawable/ic_bt_headphones_a2dp</item>
+ <item>android:drawable/ic_bt_headset_hfp</item>
+ <item>android:drawable/ic_bt_hearing_aid</item>
+ <item>android:drawable/ic_bt_laptop</item>
+ <item>android:drawable/ic_bt_misc_hid</item>
+ <item>android:drawable/ic_bt_network_pan</item>
+ <item>android:drawable/ic_bt_pointing_hid</item>
+ <item>android:drawable/ic_corp_badge</item>
+ <item>android:drawable/ic_expand_more</item>
+ <item>android:drawable/ic_faster_emergency</item>
+ <item>android:drawable/ic_file_copy</item>
+ <item>android:drawable/ic_info_outline_24</item>
+ <item>android:drawable/ic_lock</item>
+ <item>android:drawable/ic_lock_bugreport</item>
+ <item>android:drawable/ic_lock_open</item>
+ <item>android:drawable/ic_lock_power_off</item>
+ <item>android:drawable/ic_lockscreen_ime</item>
+ <item>android:drawable/ic_mode_edit</item>
+ <item>android:drawable/ic_phone</item>
+ <item>android:drawable/ic_qs_airplane</item>
+ <item>android:drawable/ic_qs_auto_rotate</item>
+ <item>android:drawable/ic_qs_battery_saver</item>
+ <item>android:drawable/ic_qs_bluetooth</item>
+ <item>android:drawable/ic_qs_dnd</item>
+ <item>android:drawable/ic_qs_flashlight</item>
+ <item>android:drawable/ic_qs_night_display_on</item>
+ <item>android:drawable/ic_restart</item>
+ <item>android:drawable/ic_screenshot</item>
+ <item>android:drawable/ic_settings_bluetooth</item>
+ <item>android:drawable/ic_signal_cellular_0_4_bar</item>
+ <item>android:drawable/ic_signal_cellular_0_5_bar</item>
+ <item>android:drawable/ic_signal_cellular_1_4_bar</item>
+ <item>android:drawable/ic_signal_cellular_1_5_bar</item>
+ <item>android:drawable/ic_signal_cellular_2_4_bar</item>
+ <item>android:drawable/ic_signal_cellular_2_5_bar</item>
+ <item>android:drawable/ic_signal_cellular_3_4_bar</item>
+ <item>android:drawable/ic_signal_cellular_3_5_bar</item>
+ <item>android:drawable/ic_signal_cellular_4_4_bar</item>
+ <item>android:drawable/ic_signal_cellular_4_5_bar</item>
+ <item>android:drawable/ic_signal_cellular_5_5_bar</item>
+ <item>android:drawable/ic_signal_location</item>
+ <item>android:drawable/ic_wifi_signal_0</item>
+ <item>android:drawable/ic_wifi_signal_1</item>
+ <item>android:drawable/ic_wifi_signal_2</item>
+ <item>android:drawable/ic_wifi_signal_3</item>
+ <item>android:drawable/ic_wifi_signal_4</item>
+ <item>android:drawable/perm_group_activity_recognition</item>
+ <item>android:drawable/perm_group_calendar</item>
+ <item>android:drawable/perm_group_call_log</item>
+ <item>android:drawable/perm_group_camera</item>
+ <item>android:drawable/perm_group_contacts</item>
+ <item>android:drawable/perm_group_location</item>
+ <item>android:drawable/perm_group_microphone</item>
+ <item>android:drawable/perm_group_phone_calls</item>
+ <item>android:drawable/perm_group_sensors</item>
+ <item>android:drawable/perm_group_sms</item>
+ <item>android:drawable/perm_group_storage</item>
+ <item>android:drawable/perm_group_visual</item>
+
+ <item>com.android.settings:drawable/ic_add_24dp</item>
+ <item>com.android.settings:drawable/ic_airplanemode_active</item>
+ <item>com.android.settings:drawable/ic_android</item>
+ <item>com.android.settings:drawable/ic_apps</item>
+ <item>com.android.settings:drawable/ic_arrow_back</item>
+ <item>com.android.settings:drawable/ic_arrow_down_24dp</item>
+ <item>com.android.settings:drawable/ic_battery_charging_full</item>
+ <item>com.android.settings:drawable/ic_battery_status_bad_24dp</item>
+ <item>com.android.settings:drawable/ic_battery_status_good_24dp</item>
+ <item>com.android.settings:drawable/ic_battery_status_maybe_24dp</item>
+ <item>com.android.settings:drawable/ic_call_24dp</item>
+ <item>com.android.settings:drawable/ic_cancel</item>
+ <item>com.android.settings:drawable/ic_cast_24dp</item>
+ <item>com.android.settings:drawable/ic_chevron_right_24dp</item>
+ <item>com.android.settings:drawable/ic_data_saver</item>
+ <item>com.android.settings:drawable/ic_delete</item>
+ <item>com.android.settings:drawable/ic_devices_other</item>
+ <item>com.android.settings:drawable/ic_devices_other_opaque_black</item>
+ <item>com.android.settings:drawable/ic_do_not_disturb_on_24dp</item>
+ <item>com.android.settings:drawable/ic_eject_24dp</item>
+ <item>com.android.settings:drawable/ic_expand_less</item>
+ <item>com.android.settings:drawable/ic_expand_more_inverse</item>
+ <item>com.android.settings:drawable/ic_folder_vd_theme_24</item>
+ <item>com.android.settings:drawable/ic_friction_lock_closed</item>
+ <item>com.android.settings:drawable/ic_gray_scale_24dp</item>
+ <item>com.android.settings:drawable/ic_headset_24dp</item>
+ <item>com.android.settings:drawable/ic_help</item>
+ <item>com.android.settings:drawable/ic_local_movies</item>
+ <item>com.android.settings:drawable/ic_lock</item>
+ <item>com.android.settings:drawable/ic_media_stream</item>
+ <item>com.android.settings:drawable/ic_network_cell</item>
+ <item>com.android.settings:drawable/ic_notifications</item>
+ <item>com.android.settings:drawable/ic_notifications_off_24dp</item>
+ <item>com.android.settings:drawable/ic_phone_info</item>
+ <item>com.android.settings:drawable/ic_photo_library</item>
+ <item>com.android.settings:drawable/ic_settings_accessibility</item>
+ <item>com.android.settings:drawable/ic_settings_accounts</item>
+ <item>com.android.settings:drawable/ic_settings_backup</item>
+ <item>com.android.settings:drawable/ic_settings_battery_white</item>
+ <item>com.android.settings:drawable/ic_settings_data_usage</item>
+ <item>com.android.settings:drawable/ic_settings_date_time</item>
+ <item>com.android.settings:drawable/ic_settings_delete</item>
+ <item>com.android.settings:drawable/ic_settings_display_white</item>
+ <item>com.android.settings:drawable/ic_settings_home</item>
+ <item>com.android.settings:drawable/ic_settings_location</item>
+ <item>com.android.settings:drawable/ic_settings_night_display</item>
+ <item>com.android.settings:drawable/ic_settings_open</item>
+ <item>com.android.settings:drawable/ic_settings_print</item>
+ <item>com.android.settings:drawable/ic_settings_privacy</item>
+ <item>com.android.settings:drawable/ic_settings_security_white</item>
+ <item>com.android.settings:drawable/ic_settings_sim</item>
+ <item>com.android.settings:drawable/ic_settings_wireless</item>
+ <item>com.android.settings:drawable/ic_storage</item>
+ <item>com.android.settings:drawable/ic_storage_white</item>
+ <item>com.android.settings:drawable/ic_suggestion_night_display</item>
+ <item>com.android.settings:drawable/ic_sync</item>
+ <item>com.android.settings:drawable/ic_system_update</item>
+ <item>com.android.settings:drawable/ic_videogame_vd_theme_24</item>
+ <item>com.android.settings:drawable/ic_volume_ringer_vibrate</item>
+ <item>com.android.settings:drawable/ic_volume_up_24dp</item>
+ <item>com.android.settings:drawable/ic_vpn_key</item>
+ <item>com.android.settings:drawable/ic_wifi_tethering</item>
+
+ <item>com.android.systemui:drawable/ic_alarm</item>
+ <item>com.android.systemui:drawable/ic_alarm_dim</item>
+ <item>com.android.systemui:drawable/ic_arrow_back</item>
+ <item>com.android.systemui:drawable/ic_bluetooth_connected</item>
+ <item>com.android.systemui:drawable/ic_brightness_thumb</item>
+ <item>com.android.systemui:drawable/ic_camera</item>
+ <item>com.android.systemui:drawable/ic_cast</item>
+ <item>com.android.systemui:drawable/ic_cast_connected</item>
+ <item>com.android.systemui:drawable/ic_cast_connected_fill</item>
+ <item>com.android.systemui:drawable/ic_close_white</item>
+ <item>com.android.systemui:drawable/ic_data_saver</item>
+ <item>com.android.systemui:drawable/ic_data_saver_off</item>
+ <item>com.android.systemui:drawable/ic_drag_handle</item>
+ <item>com.android.systemui:drawable/ic_headset</item>
+ <item>com.android.systemui:drawable/ic_headset_mic</item>
+ <item>com.android.systemui:drawable/ic_hotspot</item>
+ <item>com.android.systemui:drawable/ic_invert_colors</item>
+ <item>com.android.systemui:drawable/ic_location</item>
+ <item>com.android.systemui:drawable/ic_lockscreen_ime</item>
+ <item>com.android.systemui:drawable/ic_notifications_alert</item>
+ <item>com.android.systemui:drawable/ic_notifications_silence</item>
+ <item>com.android.systemui:drawable/ic_power_low</item>
+ <item>com.android.systemui:drawable/ic_power_saver</item>
+ <item>com.android.systemui:drawable/ic_qs_bluetooth_connecting</item>
+ <item>com.android.systemui:drawable/ic_qs_bluetooth_on</item>
+ <item>com.android.systemui:drawable/ic_qs_cancel</item>
+ <item>com.android.systemui:drawable/ic_qs_no_sim</item>
+ <item>com.android.systemui:drawable/ic_screenshot_delete</item>
+ <item>com.android.systemui:drawable/ic_settings</item>
+ <item>com.android.systemui:drawable/ic_swap_vert</item>
+ <item>com.android.systemui:drawable/ic_volume_alarm</item>
+ <item>com.android.systemui:drawable/ic_volume_alarm_mute</item>
+ <item>com.android.systemui:drawable/ic_volume_media</item>
+ <item>com.android.systemui:drawable/ic_volume_media_mute</item>
+ <item>com.android.systemui:drawable/ic_volume_ringer</item>
+ <item>com.android.systemui:drawable/ic_volume_ringer_mute</item>
+ <item>com.android.systemui:drawable/ic_volume_ringer_vibrate</item>
+ <item>com.android.systemui:drawable/ic_volume_voice</item>
+ <item>com.android.systemui:drawable/stat_sys_camera</item>
+ <item>com.android.systemui:drawable/stat_sys_managed_profile_status</item>
+ <item>com.android.systemui:drawable/stat_sys_mic_none</item>
+ <item>com.android.systemui:drawable/stat_sys_vpn_ic</item>
+
+ </string-array>
+</resources>
diff --git a/packages/EasterEgg/res/values/strings.xml b/packages/EasterEgg/res/values/strings.xml
index 32dbc97a00fb..b95ec6be4c84 100644
--- a/packages/EasterEgg/res/values/strings.xml
+++ b/packages/EasterEgg/res/values/strings.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,5 +14,11 @@ Copyright (C) 2018 The Android Open Source Project
limitations under the License.
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <string name="app_name" translatable="false">PAINT.APK</string>
+ <string name="app_name" translatable="false">Android Q Easter Egg</string>
+
+ <!-- name of the Q easter egg, a nonogram-style icon puzzle -->
+ <string name="q_egg_name" translatable="false">Icon Quiz</string>
+
+ <!-- name of the P easter egg, a humble paint program -->
+ <string name="p_egg_name" translatable="false">PAINT.APK</string>
</resources>
diff --git a/packages/EasterEgg/res/values/styles.xml b/packages/EasterEgg/res/values/styles.xml
index 44e2ce52aab8..e576526f49b7 100644
--- a/packages/EasterEgg/res/values/styles.xml
+++ b/packages/EasterEgg/res/values/styles.xml
@@ -20,4 +20,16 @@
<item name="android:windowLightNavigationBar">true</item>
</style>
+ <style name="QuaresTheme" parent="@android:style/Theme.DeviceDefault.DayNight">
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:colorBackgroundCacheHint">@null</item>
+ <item name="android:windowShowWallpaper">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowFullscreen">true</item>
+ <item name="android:statusBarColor">@android:color/transparent</item>
+ <item name="android:navigationBarColor">@android:color/transparent</item>
+ </style>
+
</resources>
diff --git a/packages/EasterEgg/src/com/android/egg/quares/Quare.kt b/packages/EasterEgg/src/com/android/egg/quares/Quare.kt
new file mode 100644
index 000000000000..eb77362a0be2
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/quares/Quare.kt
@@ -0,0 +1,168 @@
+/*
+ * Copyright 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.egg.quares
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.Icon
+import android.os.Parcel
+import android.os.Parcelable
+import java.util.ArrayList
+import kotlin.math.abs
+import kotlin.math.round
+
+class Quare(val width: Int, val height: Int, val depth: Int) : Parcelable {
+ private val data: IntArray = IntArray(width * height)
+ private val user: IntArray = data.copyOf()
+
+ private fun loadAndQuantize(bitmap8bpp: Bitmap) {
+ bitmap8bpp.getPixels(data, 0, width, 0, 0, width, height)
+ if (depth == 8) return
+ val s = (255f / depth)
+ for (i in 0 until data.size) {
+ var f = (data[i] ushr 24).toFloat() / s
+ // f = f.pow(0.75f) // gamma adjust for bolder lines
+ f *= 1.25f // brightness adjust for bolder lines
+ f.coerceAtMost(1f)
+ data[i] = (round(f) * s).toInt() shl 24
+ }
+ }
+
+ fun isBlank(): Boolean {
+ return data.sum() == 0
+ }
+
+ fun load(drawable: Drawable) {
+ val resized = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8)
+ val canvas = Canvas(resized)
+ drawable.setBounds(0, 0, width, height)
+ drawable.setTint(0xFF000000.toInt())
+ drawable.draw(canvas)
+ loadAndQuantize(resized)
+ resized.recycle()
+ }
+
+ fun load(context: Context, icon: Icon) {
+ icon.loadDrawable(context)?.let {
+ load(it)
+ }
+ }
+
+ fun bitmap(): Bitmap {
+ return Bitmap.createBitmap(data, width, height, Bitmap.Config.ALPHA_8)
+ }
+
+ fun getUserMark(x: Int, y: Int): Int {
+ return user[y * width + x] ushr 24
+ }
+
+ fun setUserMark(x: Int, y: Int, v: Int) {
+ user[y * width + x] = v shl 24
+ }
+
+ fun getDataAt(x: Int, y: Int): Int {
+ return data[y * width + x] ushr 24
+ }
+
+ fun check(): Boolean {
+ return data.contentEquals(user)
+ }
+
+ fun check(xSel: Int, ySel: Int): Boolean {
+ val xStart = if (xSel < 0) 0 else xSel
+ val xEnd = if (xSel < 0) width - 1 else xSel
+ val yStart = if (ySel < 0) 0 else ySel
+ val yEnd = if (ySel < 0) height - 1 else ySel
+ for (y in yStart..yEnd)
+ for (x in xStart..xEnd)
+ if (getDataAt(x, y) != getUserMark(x, y)) return false
+ return true
+ }
+
+ fun errors(): IntArray {
+ return IntArray(width * height) {
+ abs(data[it] - user[it])
+ }
+ }
+
+ fun getRowClue(y: Int): IntArray {
+ return getClue(-1, y)
+ }
+ fun getColumnClue(x: Int): IntArray {
+ return getClue(x, -1)
+ }
+ fun getClue(xSel: Int, ySel: Int): IntArray {
+ val arr = ArrayList<Int>()
+ var len = 0
+ val xStart = if (xSel < 0) 0 else xSel
+ val xEnd = if (xSel < 0) width - 1 else xSel
+ val yStart = if (ySel < 0) 0 else ySel
+ val yEnd = if (ySel < 0) height - 1 else ySel
+ for (y in yStart..yEnd)
+ for (x in xStart..xEnd)
+ if (getDataAt(x, y) != 0) {
+ len++
+ } else if (len > 0) {
+ arr.add(len)
+ len = 0
+ }
+ if (len > 0) arr.add(len)
+ else if (arr.size == 0) arr.add(0)
+ return arr.toIntArray()
+ }
+
+ fun resetUserMarks() {
+ user.forEachIndexed { index, _ -> user[index] = 0 }
+ }
+
+ // Parcelable interface
+
+ override fun describeContents(): Int {
+ return 0
+ }
+
+ override fun writeToParcel(p: Parcel?, flags: Int) {
+ p?.let {
+ p.writeInt(width)
+ p.writeInt(height)
+ p.writeInt(depth)
+ p.writeIntArray(data)
+ p.writeIntArray(user)
+ }
+ }
+
+ companion object CREATOR : Parcelable.Creator<Quare> {
+ override fun createFromParcel(p: Parcel?): Quare {
+ return p!!.let {
+ Quare(
+ p.readInt(), // width
+ p.readInt(), // height
+ p.readInt() // depth
+ ).also {
+ p.readIntArray(it.data)
+ p.readIntArray(it.user)
+ }
+ }
+ }
+
+ override fun newArray(size: Int): Array<Quare?> {
+ return arrayOfNulls(size)
+ }
+ }
+}
diff --git a/packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt b/packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt
new file mode 100644
index 000000000000..ce439a9a663c
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt
@@ -0,0 +1,312 @@
+/*
+ * Copyright 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.egg.quares
+
+import android.app.Activity
+import android.content.Context
+import android.content.res.Configuration
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.graphics.Typeface
+import android.graphics.drawable.Icon
+import android.os.Bundle
+import android.text.StaticLayout
+import android.text.TextPaint
+import android.util.Log
+import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
+import android.widget.Button
+import android.widget.CompoundButton
+import android.widget.GridLayout
+
+import java.util.Random
+
+import com.android.egg.R
+
+const val TAG = "Quares"
+
+class QuaresActivity : Activity() {
+ private var q: Quare = Quare(16, 16, 1)
+ private var resId = 0
+ private var resName = ""
+ private var icon: Icon? = null
+
+ private lateinit var label: Button
+ private lateinit var grid: GridLayout
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ window.decorView.systemUiVisibility =
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+
+ actionBar?.hide()
+
+ setContentView(R.layout.activity_quares)
+
+ grid = findViewById(R.id.grid)
+ label = findViewById(R.id.label)
+
+ if (savedInstanceState != null) {
+ Log.v(TAG, "restoring puzzle from state")
+ q = savedInstanceState.getParcelable("q") ?: q
+ resId = savedInstanceState.getInt("resId")
+ resName = savedInstanceState.getString("resName", "")
+ loadPuzzle()
+ }
+
+ label.setOnClickListener { newPuzzle() }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ if (resId == 0) {
+ // lazy init from onCreate
+ newPuzzle()
+ }
+ checkVictory()
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+
+ outState.putParcelable("q", q)
+ outState.putInt("resId", resId)
+ outState.putString("resName", resName)
+ }
+
+ fun newPuzzle() {
+ Log.v(TAG, "new puzzle...")
+
+ q.resetUserMarks()
+ val oldResId = resId
+ resId = android.R.drawable.stat_sys_warning
+ try {
+ for (tries in 0..3) {
+ val ar = resources.obtainTypedArray(R.array.puzzles)
+ val newName = ar.getString(Random().nextInt(ar.length()))
+ if (newName == null) continue
+
+ Log.v(TAG, "Looking for icon " + newName)
+
+ val pkg = getPackageNameForResourceName(newName)
+ val newId = packageManager.getResourcesForApplication(pkg)
+ .getIdentifier(newName, "drawable", pkg)
+ if (newId == 0) {
+ Log.v(TAG, "oops, " + newName + " doesn't resolve from pkg " + pkg)
+ } else if (newId != oldResId) {
+ // got a good one
+ resId = newId
+ resName = newName
+ break
+ }
+ }
+ } catch (e: RuntimeException) {
+ Log.v(TAG, "problem loading puzzle, using fallback", e)
+ }
+ loadPuzzle()
+ }
+
+ fun getPackageNameForResourceName(name: String): String {
+ return if (name.contains(":") && !name.startsWith("android:")) {
+ name.substring(0, name.indexOf(":"))
+ } else {
+ packageName
+ }
+ }
+
+ fun checkVictory() {
+ if (q.check()) {
+ val dp = resources.displayMetrics.density
+
+ val label: Button = findViewById(R.id.label)
+ label.text = resName.replace(Regex("^.*/"), "")
+ val drawable = icon?.loadDrawable(this)?.also {
+ it.setBounds(0, 0, (32 * dp).toInt(), (32 * dp).toInt())
+ it.setTint(label.currentTextColor)
+ }
+ label.setCompoundDrawables(drawable, null, null, null)
+
+ label.visibility = VISIBLE
+ } else {
+ label.visibility = GONE
+ }
+ }
+
+ fun loadPuzzle() {
+ Log.v(TAG, "loading " + resName + " at " + q.width + "x" + q.height)
+
+ val dp = resources.displayMetrics.density
+
+ icon = Icon.createWithResource(getPackageNameForResourceName(resName), resId)
+ q.load(this, icon!!)
+
+ if (q.isBlank()) {
+ // this is a really boring puzzle, let's try again
+ resId = 0
+ resName = ""
+ recreate()
+ return
+ }
+
+ grid.removeAllViews()
+ grid.columnCount = q.width + 1
+ grid.rowCount = q.height + 1
+
+ label.visibility = GONE
+
+ val orientation = resources.configuration.orientation
+
+ // clean this up a bit
+ val minSide = resources.configuration.smallestScreenWidthDp - 25 // ish
+ val size = (minSide / (q.height + 0.5) * dp).toInt()
+
+ val sb = StringBuffer()
+
+ for (j in 0 until grid.rowCount) {
+ for (i in 0 until grid.columnCount) {
+ val tv: View
+ val params = GridLayout.LayoutParams().also {
+ it.width = size
+ it.height = size
+ it.setMargins(1, 1, 1, 1)
+ it.rowSpec = GridLayout.spec(GridLayout.UNDEFINED, GridLayout.TOP) // UGH
+ }
+ val x = i - 1
+ val y = j - 1
+ if (i > 0 && j > 0) {
+ if (i == 1 && j > 1) sb.append("\n")
+ sb.append(if (q.getDataAt(x, y) == 0) " " else "X")
+ tv = PixelButton(this)
+ tv.isChecked = q.getUserMark(x, y) != 0
+ tv.setOnClickListener {
+ q.setUserMark(x, y, if (tv.isChecked) 0xFF else 0)
+ val columnCorrect = (grid.getChildAt(i) as? ClueView)?.check(q) ?: false
+ val rowCorrect = (grid.getChildAt(j*(grid.columnCount)) as? ClueView)
+ ?.check(q) ?: false
+ if (columnCorrect && rowCorrect) {
+ checkVictory()
+ } else {
+ label.visibility = GONE
+ }
+ }
+ } else if (i == j) { // 0,0
+ tv = View(this)
+ tv.visibility = GONE
+ } else {
+ tv = ClueView(this)
+ if (j == 0) {
+ tv.textRotation = 90f
+ if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ params.height /= 2
+ tv.showText = false
+ } else {
+ params.height = (96 * dp).toInt()
+ }
+ if (x >= 0) {
+ tv.setColumn(q, x)
+ }
+ }
+ if (i == 0) {
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+ params.width /= 2
+ tv.showText = false
+ } else {
+ params.width = (96 * dp).toInt()
+ }
+ if (y >= 0) {
+ tv.setRow(q, y)
+ }
+ }
+ }
+ grid.addView(tv, params)
+ }
+ }
+
+ Log.v(TAG, "icon: \n" + sb)
+ }
+}
+
+class PixelButton(context: Context) : CompoundButton(context) {
+ init {
+ setBackgroundResource(R.drawable.pixel_bg)
+ isClickable = true
+ isEnabled = true
+ }
+}
+
+class ClueView(context: Context) : View(context) {
+ var row: Int = -1
+ var column: Int = -1
+ var textRotation: Float = 0f
+ var text: CharSequence = ""
+ var showText = true
+ val paint: TextPaint
+ val incorrectColor: Int
+ val correctColor: Int
+
+ init {
+ setBackgroundColor(0)
+ paint = TextPaint().also {
+ it.textSize = 14f * context.resources.displayMetrics.density
+ it.color = context.getColor(R.color.q_clue_text)
+ it.typeface = Typeface.DEFAULT_BOLD
+ it.textAlign = Paint.Align.CENTER
+ }
+ incorrectColor = context.getColor(R.color.q_clue_bg)
+ correctColor = context.getColor(R.color.q_clue_bg_correct)
+ }
+
+ fun setRow(q: Quare, row: Int): Boolean {
+ this.row = row
+ this.column = -1
+ this.textRotation = 0f
+ text = q.getRowClue(row).joinToString("-")
+ return check(q)
+ }
+ fun setColumn(q: Quare, column: Int): Boolean {
+ this.column = column
+ this.row = -1
+ this.textRotation = 90f
+ text = q.getColumnClue(column).joinToString("-")
+ return check(q)
+ }
+ fun check(q: Quare): Boolean {
+ val correct = q.check(column, row)
+ setBackgroundColor(if (correct) correctColor else incorrectColor)
+ return correct
+ }
+
+ override fun onDraw(canvas: Canvas?) {
+ super.onDraw(canvas)
+ if (!showText) return
+ canvas?.let {
+ val x = canvas.width / 2f
+ val y = canvas.height / 2f
+ var textWidth = canvas.width
+ if (textRotation != 0f) {
+ canvas.rotate(textRotation, x, y)
+ textWidth = canvas.height
+ }
+ val textLayout = StaticLayout.Builder.obtain(
+ text, 0, text.length, paint, textWidth).build()
+ canvas.translate(x, y - textLayout.height / 2)
+ textLayout.draw(canvas)
+ }
+ }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
index 28d5402bf707..52ec1f0bb330 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
@@ -30,7 +30,7 @@ import java.io.PrintWriter;
*/
@ProvidesInterface(version = FalsingManager.VERSION)
public interface FalsingManager {
- int VERSION = 1;
+ int VERSION = 2;
void onSucccessfulUnlock();
@@ -103,4 +103,6 @@ public interface FalsingManager {
void onTouchEvent(MotionEvent ev, int width, int height);
void dump(PrintWriter pw);
+
+ void cleanup();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index b1cba53c4bca..fee2c9b2505a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -540,6 +540,9 @@ public class KeyguardClockSwitch extends RelativeLayout {
@Override
public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
TransitionValues endValues) {
+ if (!sceneRoot.isShown()) {
+ return null;
+ }
final float cutoff = mCutoff;
final int startVisibility = View.INVISIBLE;
final int endVisibility = (int) endValues.values.get(PROPNAME_VISIBILITY);
@@ -552,6 +555,9 @@ public class KeyguardClockSwitch extends RelativeLayout {
@Override
public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
TransitionValues endValues) {
+ if (!sceneRoot.isShown()) {
+ return null;
+ }
final float cutoff = 1f - mCutoff;
final int startVisibility = View.VISIBLE;
final int endVisibility = (int) endValues.values.get(PROPNAME_VISIBILITY);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index e219e24a8944..af4e61b3f6bc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -89,6 +89,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
private final HashMap<View, PendingIntent> mClickActions;
private final ActivityStarter mActivityStarter;
private final ConfigurationController mConfigurationController;
+ private final LayoutTransition mLayoutTransition;
private Uri mKeyguardSliceUri;
@VisibleForTesting
TextView mTitle;
@@ -126,16 +127,16 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
mActivityStarter = activityStarter;
mConfigurationController = configurationController;
- LayoutTransition transition = new LayoutTransition();
- transition.setStagger(LayoutTransition.CHANGE_APPEARING, DEFAULT_ANIM_DURATION / 2);
- transition.setDuration(LayoutTransition.APPEARING, DEFAULT_ANIM_DURATION);
- transition.setDuration(LayoutTransition.DISAPPEARING, DEFAULT_ANIM_DURATION / 2);
- transition.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
- transition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
- transition.setInterpolator(LayoutTransition.APPEARING, Interpolators.FAST_OUT_SLOW_IN);
- transition.setInterpolator(LayoutTransition.DISAPPEARING, Interpolators.ALPHA_OUT);
- transition.setAnimateParentHierarchy(false);
- setLayoutTransition(transition);
+ mLayoutTransition = new LayoutTransition();
+ mLayoutTransition.setStagger(LayoutTransition.CHANGE_APPEARING, DEFAULT_ANIM_DURATION / 2);
+ mLayoutTransition.setDuration(LayoutTransition.APPEARING, DEFAULT_ANIM_DURATION);
+ mLayoutTransition.setDuration(LayoutTransition.DISAPPEARING, DEFAULT_ANIM_DURATION / 2);
+ mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
+ mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
+ mLayoutTransition.setInterpolator(LayoutTransition.APPEARING,
+ Interpolators.FAST_OUT_SLOW_IN);
+ mLayoutTransition.setInterpolator(LayoutTransition.DISAPPEARING, Interpolators.ALPHA_OUT);
+ mLayoutTransition.setAnimateParentHierarchy(false);
}
@Override
@@ -174,6 +175,12 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
mConfigurationController.removeCallback(this);
}
+ @Override
+ public void onVisibilityAggregated(boolean isVisible) {
+ super.onVisibilityAggregated(isVisible);
+ setLayoutTransition(isVisible ? mLayoutTransition : null);
+ }
+
/**
* Returns whether the current visible slice has a title/header.
*/
@@ -419,6 +426,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
* their desired positions.
*/
private final Animation.AnimationListener mKeepAwakeListener;
+ private LayoutTransition mLayoutTransition;
private float mDarkAmount;
public Row(Context context) {
@@ -440,33 +448,41 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
@Override
protected void onFinishInflate() {
- LayoutTransition transition = new LayoutTransition();
- transition.setDuration(DEFAULT_ANIM_DURATION);
+ mLayoutTransition = new LayoutTransition();
+ mLayoutTransition.setDuration(DEFAULT_ANIM_DURATION);
PropertyValuesHolder left = PropertyValuesHolder.ofInt("left", 0, 1);
PropertyValuesHolder right = PropertyValuesHolder.ofInt("right", 0, 1);
ObjectAnimator changeAnimator = ObjectAnimator.ofPropertyValuesHolder((Object) null,
left, right);
- transition.setAnimator(LayoutTransition.CHANGE_APPEARING, changeAnimator);
- transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeAnimator);
- transition.setInterpolator(LayoutTransition.CHANGE_APPEARING,
+ mLayoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, changeAnimator);
+ mLayoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeAnimator);
+ mLayoutTransition.setInterpolator(LayoutTransition.CHANGE_APPEARING,
Interpolators.ACCELERATE_DECELERATE);
- transition.setInterpolator(LayoutTransition.CHANGE_DISAPPEARING,
+ mLayoutTransition.setInterpolator(LayoutTransition.CHANGE_DISAPPEARING,
Interpolators.ACCELERATE_DECELERATE);
- transition.setStartDelay(LayoutTransition.CHANGE_APPEARING, DEFAULT_ANIM_DURATION);
- transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, DEFAULT_ANIM_DURATION);
+ mLayoutTransition.setStartDelay(LayoutTransition.CHANGE_APPEARING,
+ DEFAULT_ANIM_DURATION);
+ mLayoutTransition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING,
+ DEFAULT_ANIM_DURATION);
ObjectAnimator appearAnimator = ObjectAnimator.ofFloat(null, "alpha", 0f, 1f);
- transition.setAnimator(LayoutTransition.APPEARING, appearAnimator);
- transition.setInterpolator(LayoutTransition.APPEARING, Interpolators.ALPHA_IN);
+ mLayoutTransition.setAnimator(LayoutTransition.APPEARING, appearAnimator);
+ mLayoutTransition.setInterpolator(LayoutTransition.APPEARING, Interpolators.ALPHA_IN);
ObjectAnimator disappearAnimator = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f);
- transition.setInterpolator(LayoutTransition.DISAPPEARING, Interpolators.ALPHA_OUT);
- transition.setDuration(LayoutTransition.DISAPPEARING, DEFAULT_ANIM_DURATION / 4);
- transition.setAnimator(LayoutTransition.DISAPPEARING, disappearAnimator);
+ mLayoutTransition.setInterpolator(LayoutTransition.DISAPPEARING,
+ Interpolators.ALPHA_OUT);
+ mLayoutTransition.setDuration(LayoutTransition.DISAPPEARING, DEFAULT_ANIM_DURATION / 4);
+ mLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING, disappearAnimator);
- transition.setAnimateParentHierarchy(false);
- setLayoutTransition(transition);
+ mLayoutTransition.setAnimateParentHierarchy(false);
+ }
+
+ @Override
+ public void onVisibilityAggregated(boolean isVisible) {
+ super.onVisibilityAggregated(isVisible);
+ setLayoutTransition(isVisible ? mLayoutTransition : null);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 9a0e9fc92af6..bd91333100bd 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -46,6 +46,8 @@ public class ImageWallpaper extends WallpaperService {
// We delayed destroy render context that subsequent render requests have chance to cancel it.
// This is to avoid destroying then recreating render context in a very short time.
private static final int DELAY_FINISH_RENDERING = 1000;
+ private static final int INTERVAL_WAIT_FOR_RENDERING = 100;
+ private static final int PATIENCE_WAIT_FOR_RENDERING = 10;
private HandlerThread mWorker;
@Override
@@ -80,7 +82,10 @@ public class ImageWallpaper extends WallpaperService {
private StatusBarStateController mController;
private final Runnable mFinishRenderingTask = this::finishRendering;
private final boolean mNeedTransition;
+ private final Object mMonitor = new Object();
private boolean mNeedRedraw;
+ // This variable can only be accessed in synchronized block.
+ private boolean mWaitingForRendering;
GLEngine(Context context) {
mNeedTransition = ActivityManager.isHighEndGfx()
@@ -119,9 +124,30 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) {
- long duration = mNeedTransition || animationDuration != 0 ? animationDuration : 0;
+ if (!mNeedTransition) return;
mWorker.getThreadHandler().post(
- () -> mRenderer.updateAmbientMode(inAmbientMode, duration));
+ () -> mRenderer.updateAmbientMode(inAmbientMode, animationDuration));
+ if (inAmbientMode && animationDuration == 0) {
+ // This means that we are transiting from home to aod, to avoid
+ // race condition between window visibility and transition,
+ // we don't return until the transition is finished. See b/136643341.
+ waitForBackgroundRendering();
+ }
+ }
+
+ private void waitForBackgroundRendering() {
+ synchronized (mMonitor) {
+ try {
+ mWaitingForRendering = true;
+ for (int patience = 1; mWaitingForRendering; patience++) {
+ mMonitor.wait(INTERVAL_WAIT_FOR_RENDERING);
+ mWaitingForRendering &= patience < PATIENCE_WAIT_FOR_RENDERING;
+ }
+ } catch (InterruptedException ex) {
+ } finally {
+ mWaitingForRendering = false;
+ }
+ }
}
@Override
@@ -178,7 +204,8 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void preRender() {
- mWorker.getThreadHandler().post(this::preRenderInternal);
+ // This method should only be invoked from worker thread.
+ preRenderInternal();
}
private void preRenderInternal() {
@@ -212,7 +239,8 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void requestRender() {
- mWorker.getThreadHandler().post(this::requestRenderInternal);
+ // This method should only be invoked from worker thread.
+ requestRenderInternal();
}
private void requestRenderInternal() {
@@ -234,7 +262,21 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void postRender() {
- mWorker.getThreadHandler().post(this::scheduleFinishRendering);
+ // This method should only be invoked from worker thread.
+ notifyWaitingThread();
+ scheduleFinishRendering();
+ }
+
+ private void notifyWaitingThread() {
+ synchronized (mMonitor) {
+ if (mWaitingForRendering) {
+ try {
+ mWaitingForRendering = false;
+ mMonitor.notify();
+ } catch (IllegalMonitorStateException ex) {
+ }
+ }
+ }
}
private void cancelFinishRenderingTask() {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
index 6fb6467d07b2..382c5d5c5954 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
@@ -168,6 +168,7 @@ public class FalsingManagerImpl implements FalsingManager {
.append("enabled=").append(isEnabled() ? 1 : 0)
.append(" mScreenOn=").append(mScreenOn ? 1 : 0)
.append(" mState=").append(StatusBarState.toShortString(mState))
+ .append(" mShowingAod=").append(mShowingAod ? 1 : 0)
.toString()
);
}
@@ -550,6 +551,14 @@ public class FalsingManagerImpl implements FalsingManager {
pw.println();
}
+ @Override
+ public void cleanup() {
+ mSensorManager.unregisterListener(mSensorEventListener);
+ mContext.getContentResolver().unregisterContentObserver(mSettingsObserver);
+ Dependency.get(StatusBarStateController.class).removeCallback(mStatusBarStateListener);
+ KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mKeyguardUpdateCallback);
+ }
+
public Uri reportRejectedTouch() {
if (mDataCollector.isEnabled()) {
return mDataCollector.reportRejectedTouch();
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index 3cc8ec9afbb2..eb4edcc45c80 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -65,6 +65,7 @@ public class FalsingManagerProxy implements FalsingManager {
public void onPluginConnected(FalsingPlugin plugin, Context context) {
FalsingManager pluginFalsingManager = plugin.getFalsingManager(context);
if (pluginFalsingManager != null) {
+ mInternalFalsingManager.cleanup();
mInternalFalsingManager = pluginFalsingManager;
}
}
@@ -91,7 +92,10 @@ public class FalsingManagerProxy implements FalsingManager {
@VisibleForTesting
public void setupFalsingManager(Context context) {
boolean brightlineEnabled = DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_MANAGER_ENABLED, false);
+ DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_MANAGER_ENABLED, true);
+ if (mInternalFalsingManager != null) {
+ mInternalFalsingManager.cleanup();
+ }
if (!brightlineEnabled) {
mInternalFalsingManager = new FalsingManagerImpl(context);
} else {
@@ -290,4 +294,9 @@ public class FalsingManagerProxy implements FalsingManager {
public void dump(PrintWriter pw) {
mInternalFalsingManager.dump(pw);
}
+
+ @Override
+ public void cleanup() {
+ mInternalFalsingManager.cleanup();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
index 19c46e40f604..fbbba57381c6 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
@@ -44,6 +44,8 @@ public class BrightLineFalsingManager implements FalsingManager {
private final SensorManager mSensorManager;
private final FalsingDataProvider mDataProvider;
private boolean mSessionStarted;
+ private boolean mShowingAod;
+ private boolean mScreenOn;
private final ExecutorService mBackgroundExecutor = Executors.newSingleThreadExecutor();
@@ -98,10 +100,12 @@ public class BrightLineFalsingManager implements FalsingManager {
}
private void sessionStart() {
- logDebug("Starting Session");
- mSessionStarted = true;
- registerSensors();
- mClassifiers.forEach(FalsingClassifier::onSessionStarted);
+ if (!mSessionStarted && !mShowingAod && mScreenOn) {
+ logDebug("Starting Session");
+ mSessionStarted = true;
+ registerSensors();
+ mClassifiers.forEach(FalsingClassifier::onSessionStarted);
+ }
}
private void sessionEnd() {
@@ -157,6 +161,7 @@ public class BrightLineFalsingManager implements FalsingManager {
@Override
public void onSucccessfulUnlock() {
+ sessionEnd();
}
@Override
@@ -165,6 +170,7 @@ public class BrightLineFalsingManager implements FalsingManager {
@Override
public void setShowingAod(boolean showingAod) {
+ mShowingAod = showingAod;
if (showingAod) {
sessionEnd();
} else {
@@ -249,7 +255,7 @@ public class BrightLineFalsingManager implements FalsingManager {
@Override
public void onScreenOnFromTouch() {
- sessionStart();
+ onScreenTurningOn();
}
@Override
@@ -271,11 +277,13 @@ public class BrightLineFalsingManager implements FalsingManager {
@Override
public void onScreenTurningOn() {
+ mScreenOn = true;
sessionStart();
}
@Override
public void onScreenOff() {
+ mScreenOn = false;
sessionEnd();
}
@@ -309,6 +317,11 @@ public class BrightLineFalsingManager implements FalsingManager {
public void dump(PrintWriter printWriter) {
}
+ @Override
+ public void cleanup() {
+ unregisterSensors();
+ }
+
static void logDebug(String msg) {
logDebug(msg, null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java
index 730907e1fa9c..cc6645415fd8 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java
@@ -16,9 +16,13 @@
package com.android.systemui.classifier.brightline;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DIAGONAL_HORIZONTAL_ANGLE_RANGE;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DIAGONAL_VERTICAL_ANGLE_RANGE;
import static com.android.systemui.classifier.Classifier.LEFT_AFFORDANCE;
import static com.android.systemui.classifier.Classifier.RIGHT_AFFORDANCE;
+import android.provider.DeviceConfig;
+
/**
* False on swipes that are too close to 45 degrees.
*
@@ -35,8 +39,20 @@ class DiagonalClassifier extends FalsingClassifier {
private static final float ONE_HUNDRED_EIGHTY_DEG = (float) (Math.PI);
private static final float THREE_HUNDRED_SIXTY_DEG = (float) (2 * Math.PI);
+ private final float mHorizontalAngleRange;
+ private final float mVerticalAngleRange;
+
DiagonalClassifier(FalsingDataProvider dataProvider) {
super(dataProvider);
+
+ mHorizontalAngleRange = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ BRIGHTLINE_FALSING_DIAGONAL_HORIZONTAL_ANGLE_RANGE,
+ HORIZONTAL_ANGLE_RANGE);
+ mVerticalAngleRange = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ BRIGHTLINE_FALSING_DIAGONAL_VERTICAL_ANGLE_RANGE,
+ VERTICAL_ANGLE_RANGE);
}
@Override
@@ -52,11 +68,11 @@ class DiagonalClassifier extends FalsingClassifier {
return false;
}
- float minAngle = DIAGONAL - HORIZONTAL_ANGLE_RANGE;
- float maxAngle = DIAGONAL + HORIZONTAL_ANGLE_RANGE;
+ float minAngle = DIAGONAL - mHorizontalAngleRange;
+ float maxAngle = DIAGONAL + mHorizontalAngleRange;
if (isVertical()) {
- minAngle = DIAGONAL - VERTICAL_ANGLE_RANGE;
- maxAngle = DIAGONAL + VERTICAL_ANGLE_RANGE;
+ minAngle = DIAGONAL - mVerticalAngleRange;
+ maxAngle = DIAGONAL + mVerticalAngleRange;
}
return angleBetween(angle, minAngle, maxAngle)
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
index 005ee12c4f61..a6a617dc51de 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
@@ -16,6 +16,14 @@
package com.android.systemui.classifier.brightline;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_FLING_THRESHOLD_IN;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_SWIPE_THRESHOLD_IN;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_SCREEN_FRACTION_MAX_DISTANCE;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_VELOCITY_TO_DISTANCE;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_VERTICAL_FLING_THRESHOLD_IN;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_VERTICAL_SWIPE_THRESHOLD_IN;
+
+import android.provider.DeviceConfig;
import android.view.MotionEvent;
import android.view.VelocityTracker;
@@ -31,12 +39,13 @@ class DistanceClassifier extends FalsingClassifier {
private static final float HORIZONTAL_SWIPE_THRESHOLD_DISTANCE_IN = 3;
private static final float VERTICAL_SWIPE_THRESHOLD_DISTANCE_IN = 3;
private static final float VELOCITY_TO_DISTANCE = 80f;
- private static final float SCREEN_FRACTION_MIN_DISTANCE = 0.8f;
+ private static final float SCREEN_FRACTION_MAX_DISTANCE = 0.8f;
private final float mVerticalFlingThresholdPx;
private final float mHorizontalFlingThresholdPx;
private final float mVerticalSwipeThresholdPx;
private final float mHorizontalSwipeThresholdPx;
+ private final float mVelocityToDistanceMultiplier;
private boolean mDistanceDirty;
private DistanceVectors mCachedDistance;
@@ -44,18 +53,48 @@ class DistanceClassifier extends FalsingClassifier {
DistanceClassifier(FalsingDataProvider dataProvider) {
super(dataProvider);
+ mVelocityToDistanceMultiplier = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ BRIGHTLINE_FALSING_DISTANCE_VELOCITY_TO_DISTANCE,
+ VELOCITY_TO_DISTANCE);
+
+ float horizontalFlingThresholdIn = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_FLING_THRESHOLD_IN,
+ HORIZONTAL_FLING_THRESHOLD_DISTANCE_IN);
+
+ float verticalFlingThresholdIn = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ BRIGHTLINE_FALSING_DISTANCE_VERTICAL_FLING_THRESHOLD_IN,
+ VERTICAL_FLING_THRESHOLD_DISTANCE_IN);
+
+ float horizontalSwipeThresholdIn = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_SWIPE_THRESHOLD_IN,
+ HORIZONTAL_SWIPE_THRESHOLD_DISTANCE_IN);
+
+ float verticalSwipeThresholdIn = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ BRIGHTLINE_FALSING_DISTANCE_VERTICAL_SWIPE_THRESHOLD_IN,
+ VERTICAL_SWIPE_THRESHOLD_DISTANCE_IN);
+
+ float screenFractionMaxDistance = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ BRIGHTLINE_FALSING_DISTANCE_SCREEN_FRACTION_MAX_DISTANCE,
+ SCREEN_FRACTION_MAX_DISTANCE);
+
mHorizontalFlingThresholdPx = Math
- .min(getWidthPixels() * SCREEN_FRACTION_MIN_DISTANCE,
- HORIZONTAL_FLING_THRESHOLD_DISTANCE_IN * getXdpi());
+ .min(getWidthPixels() * screenFractionMaxDistance,
+ horizontalFlingThresholdIn * getXdpi());
mVerticalFlingThresholdPx = Math
- .min(getHeightPixels() * SCREEN_FRACTION_MIN_DISTANCE,
- VERTICAL_FLING_THRESHOLD_DISTANCE_IN * getYdpi());
+ .min(getHeightPixels() * screenFractionMaxDistance,
+ verticalFlingThresholdIn * getYdpi());
mHorizontalSwipeThresholdPx = Math
- .min(getWidthPixels() * SCREEN_FRACTION_MIN_DISTANCE,
- HORIZONTAL_SWIPE_THRESHOLD_DISTANCE_IN * getXdpi());
+ .min(getWidthPixels() * screenFractionMaxDistance,
+ horizontalSwipeThresholdIn * getXdpi());
mVerticalSwipeThresholdPx = Math
- .min(getHeightPixels() * SCREEN_FRACTION_MIN_DISTANCE,
- VERTICAL_SWIPE_THRESHOLD_DISTANCE_IN * getYdpi());
+ .min(getHeightPixels() * screenFractionMaxDistance,
+ verticalSwipeThresholdIn * getYdpi());
mDistanceDirty = true;
}
@@ -139,18 +178,18 @@ class DistanceClassifier extends FalsingClassifier {
}
boolean getPassedFlingThreshold() {
- float dX = this.mDx + this.mVx * VELOCITY_TO_DISTANCE;
- float dY = this.mDy + this.mVy * VELOCITY_TO_DISTANCE;
+ float dX = this.mDx + this.mVx * mVelocityToDistanceMultiplier;
+ float dY = this.mDy + this.mVy * mVelocityToDistanceMultiplier;
if (isHorizontal()) {
logDebug("Horizontal swipe and fling distance: " + this.mDx + ", "
- + this.mVx * VELOCITY_TO_DISTANCE);
+ + this.mVx * mVelocityToDistanceMultiplier);
logDebug("Threshold: " + mHorizontalFlingThresholdPx);
return Math.abs(dX) >= mHorizontalFlingThresholdPx;
}
logDebug("Vertical swipe and fling distance: " + this.mDy + ", "
- + this.mVy * VELOCITY_TO_DISTANCE);
+ + this.mVy * mVelocityToDistanceMultiplier);
logDebug("Threshold: " + mVerticalFlingThresholdPx);
return Math.abs(dY) >= mVerticalFlingThresholdPx;
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java
index 94a8ac85b724..2644bf9f26ce 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java
@@ -16,10 +16,12 @@
package com.android.systemui.classifier.brightline;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD;
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
+import android.provider.DeviceConfig;
import android.view.MotionEvent;
@@ -31,8 +33,9 @@ import android.view.MotionEvent;
*/
class ProximityClassifier extends FalsingClassifier {
- private static final double PERCENT_COVERED_THRESHOLD = 0.1;
+ private static final float PERCENT_COVERED_THRESHOLD = 0.1f;
private final DistanceClassifier mDistanceClassifier;
+ private final float mPercentCoveredThreshold;
private boolean mNear;
private long mGestureStartTimeNs;
@@ -44,6 +47,11 @@ class ProximityClassifier extends FalsingClassifier {
FalsingDataProvider dataProvider) {
super(dataProvider);
this.mDistanceClassifier = distanceClassifier;
+
+ mPercentCoveredThreshold = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD,
+ PERCENT_COVERED_THRESHOLD);
}
@Override
@@ -107,7 +115,7 @@ class ProximityClassifier extends FalsingClassifier {
logInfo("Percent of gesture in proximity: " + mPercentNear);
- if (mPercentNear > PERCENT_COVERED_THRESHOLD) {
+ if (mPercentNear > mPercentCoveredThreshold) {
return !mDistanceClassifier.isLongSwipe();
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
index a62574f26399..c58b7db451b0 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
@@ -16,7 +16,13 @@
package com.android.systemui.classifier.brightline;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_X_PRIMARY_DEVIANCE;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_X_SECONDARY_DEVIANCE;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_Y_PRIMARY_DEVIANCE;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_Y_SECONDARY_DEVIANCE;
+
import android.graphics.Point;
+import android.provider.DeviceConfig;
import android.view.MotionEvent;
import java.util.ArrayList;
@@ -37,8 +43,34 @@ class ZigZagClassifier extends FalsingClassifier {
private static final float MAX_X_SECONDARY_DEVIANCE = .3f;
private static final float MAX_Y_SECONDARY_DEVIANCE = .3f;
+ private final float mMaxXPrimaryDeviance;
+ private final float mMaxYPrimaryDeviance;
+ private final float mMaxXSecondaryDeviance;
+ private final float mMaxYSecondaryDeviance;
+
ZigZagClassifier(FalsingDataProvider dataProvider) {
super(dataProvider);
+
+ mMaxXPrimaryDeviance = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ BRIGHTLINE_FALSING_ZIGZAG_X_PRIMARY_DEVIANCE,
+ MAX_X_PRIMARY_DEVIANCE);
+
+ mMaxYPrimaryDeviance = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ BRIGHTLINE_FALSING_ZIGZAG_Y_PRIMARY_DEVIANCE,
+ MAX_Y_PRIMARY_DEVIANCE);
+
+ mMaxXSecondaryDeviance = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ BRIGHTLINE_FALSING_ZIGZAG_X_SECONDARY_DEVIANCE,
+ MAX_X_SECONDARY_DEVIANCE);
+
+ mMaxYSecondaryDeviance = DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ BRIGHTLINE_FALSING_ZIGZAG_Y_SECONDARY_DEVIANCE,
+ MAX_Y_SECONDARY_DEVIANCE);
+
}
@Override
@@ -98,11 +130,11 @@ class ZigZagClassifier extends FalsingClassifier {
float maxXDeviance;
float maxYDeviance;
if (actualDx > actualDy) {
- maxXDeviance = MAX_X_PRIMARY_DEVIANCE * totalDistanceIn * getXdpi();
- maxYDeviance = MAX_Y_SECONDARY_DEVIANCE * totalDistanceIn * getYdpi();
+ maxXDeviance = mMaxXPrimaryDeviance * totalDistanceIn * getXdpi();
+ maxYDeviance = mMaxYSecondaryDeviance * totalDistanceIn * getYdpi();
} else {
- maxXDeviance = MAX_X_SECONDARY_DEVIANCE * totalDistanceIn * getXdpi();
- maxYDeviance = MAX_Y_PRIMARY_DEVIANCE * totalDistanceIn * getYdpi();
+ maxXDeviance = mMaxXSecondaryDeviance * totalDistanceIn * getXdpi();
+ maxYDeviance = mMaxYPrimaryDeviance * totalDistanceIn * getYdpi();
}
logDebug("Straightness Deviance: (" + devianceX + "," + devianceY + ") vs "
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 8694d2ad607c..9c2adb36e1ae 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -30,6 +30,7 @@ import com.android.systemui.R;
import com.android.systemui.SystemUIApplication;
import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.dock.DockManager;
+import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.AsyncSensorManager;
import com.android.systemui.util.wakelock.DelayedWakeLock;
@@ -70,7 +71,7 @@ public class DozeFactory {
new DozeScreenState(wrappedService, handler, params, wakeLock),
createDozeScreenBrightness(context, wrappedService, sensorManager, host, params,
handler),
- new DozeWallpaperState(context),
+ new DozeWallpaperState(context, getBiometricUnlockController(dozeService)),
new DozeDockHandler(context, machine, host, config, handler, dockManager)
});
@@ -107,4 +108,10 @@ public class DozeFactory {
final SystemUIApplication app = (SystemUIApplication) appCandidate;
return app.getComponent(DozeHost.class);
}
+
+ public static BiometricUnlockController getBiometricUnlockController(DozeService service) {
+ Application appCandidate = service.getApplication();
+ final SystemUIApplication app = (SystemUIApplication) appCandidate;
+ return app.getComponent(BiometricUnlockController.class);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 5f52486b2bc6..a882309c06d4 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -43,6 +43,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.systemui.R;
import com.android.systemui.plugins.SensorManagerPlugin;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.AlarmTimeout;
@@ -255,12 +256,21 @@ public class DozeSensors {
long mLastNear;
final AlarmTimeout mCooldownTimer;
final AlwaysOnDisplayPolicy mPolicy;
-
+ final Sensor mSensor;
public ProxSensor(AlwaysOnDisplayPolicy policy) {
mPolicy = policy;
mCooldownTimer = new AlarmTimeout(mAlarmManager, this::updateRegistered,
"prox_cooldown", mHandler);
+
+ // The default prox sensor can be noisy, so let's use a prox gated brightness sensor
+ // if available.
+ Sensor sensor = DozeSensors.findSensorWithType(mSensorManager,
+ mContext.getString(R.string.doze_brightness_sensor_type));
+ if (sensor == null) {
+ sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+ }
+ mSensor = sensor;
}
void setRequested(boolean requested) {
@@ -324,8 +334,9 @@ public class DozeSensors {
@Override
public String toString() {
- return String.format("{registered=%s, requested=%s, coolingDown=%s, currentlyFar=%s}",
- mRegistered, mRequested, mCooldownTimer.isScheduled(), mCurrentlyFar);
+ return String.format("{registered=%s, requested=%s, coolingDown=%s, currentlyFar=%s,"
+ + " sensor=%s}", mRegistered, mRequested, mCooldownTimer.isScheduled(),
+ mCurrentlyFar, mSensor);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
index 1b3cd881b949..35c8b741381c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
@@ -24,6 +24,7 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.DozeParameters;
import java.io.PrintWriter;
@@ -38,18 +39,22 @@ public class DozeWallpaperState implements DozeMachine.Part {
private final IWallpaperManager mWallpaperManagerService;
private final DozeParameters mDozeParameters;
+ private final BiometricUnlockController mBiometricUnlockController;
private boolean mIsAmbientMode;
- public DozeWallpaperState(Context context) {
+ public DozeWallpaperState(Context context,
+ BiometricUnlockController biometricUnlockController) {
this(IWallpaperManager.Stub.asInterface(
ServiceManager.getService(Context.WALLPAPER_SERVICE)),
+ biometricUnlockController,
DozeParameters.getInstance(context));
}
@VisibleForTesting
DozeWallpaperState(IWallpaperManager wallpaperManagerService,
- DozeParameters parameters) {
+ BiometricUnlockController biometricUnlockController, DozeParameters parameters) {
mWallpaperManagerService = wallpaperManagerService;
+ mBiometricUnlockController = biometricUnlockController;
mDozeParameters = parameters;
}
@@ -76,7 +81,9 @@ public class DozeWallpaperState implements DozeMachine.Part {
} else {
boolean wakingUpFromPulse = oldState == DozeMachine.State.DOZE_PULSING
&& newState == DozeMachine.State.FINISH;
- animated = !mDozeParameters.getDisplayNeedsBlanking() || wakingUpFromPulse;
+ boolean fastDisplay = !mDozeParameters.getDisplayNeedsBlanking();
+ animated = (fastDisplay && !mBiometricUnlockController.unlockedByWakeAndUnlock())
+ || wakingUpFromPulse;
}
if (isAmbientMode != mIsAmbientMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
index 6a1f24afe620..b154e66a846e 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
@@ -65,7 +65,7 @@ class ImageRevealHelper {
@Override
public void onAnimationStart(Animator animation) {
if (mRevealListener != null) {
- mRevealListener.onRevealStart();
+ mRevealListener.onRevealStart(true /* animate */);
}
}
});
@@ -73,7 +73,7 @@ class ImageRevealHelper {
private void animate() {
mAnimator.cancel();
- mAnimator.setFloatValues(mReveal, !mAwake ? MIN_REVEAL : MAX_REVEAL);
+ mAnimator.setFloatValues(mReveal, mAwake ? MAX_REVEAL : MIN_REVEAL);
mAnimator.start();
}
@@ -84,7 +84,16 @@ class ImageRevealHelper {
void updateAwake(boolean awake, long duration) {
mAwake = awake;
mAnimator.setDuration(duration);
- animate();
+ if (duration == 0) {
+ // We are transiting from home to aod or aod to home directly,
+ // we don't need to do transition in these cases.
+ mReveal = mAwake ? MAX_REVEAL : MIN_REVEAL;
+ mRevealListener.onRevealStart(false /* animate */);
+ mRevealListener.onRevealStateChanged();
+ mRevealListener.onRevealEnd();
+ } else {
+ animate();
+ }
}
/**
@@ -100,7 +109,7 @@ class ImageRevealHelper {
/**
* Called back while reveal starts.
*/
- void onRevealStart();
+ void onRevealStart(boolean animate);
/**
* Called back while reveal ends.
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
index 93d8dd6146a6..7b22a49fc88a 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -24,6 +24,7 @@ import static android.opengl.GLES20.glViewport;
import android.app.WallpaperManager;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.util.Log;
@@ -70,7 +71,14 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
DisplayInfo displayInfo = new DisplayInfo();
WindowManager wm = context.getSystemService(WindowManager.class);
wm.getDefaultDisplay().getDisplayInfo(displayInfo);
- mScissor = new Rect(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
+
+ // We only do transition in portrait currently, b/137962047.
+ int orientation = context.getResources().getConfiguration().orientation;
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+ mScissor = new Rect(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
+ } else {
+ mScissor = new Rect(0, 0, displayInfo.logicalHeight, displayInfo.logicalWidth);
+ }
mProxy = proxy;
mProgram = new ImageGLProgram(context);
@@ -179,20 +187,24 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer,
}
@Override
- public void onRevealStart() {
- mScissorMode = true;
- // Use current display area of texture.
- mWallpaper.adjustTextureCoordinates(mSurfaceSize, mScissor, mXOffset, mYOffset);
+ public void onRevealStart(boolean animate) {
+ if (animate) {
+ 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();
+ if (mScissorMode) {
+ 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();
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 20477975a6dd..0687b7d8efce 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -52,6 +52,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -125,6 +126,7 @@ public class KeyguardSliceProvider extends SliceProvider implements
private CharSequence mMediaTitle;
private CharSequence mMediaArtist;
protected boolean mDozing;
+ private int mStatusBarState;
private boolean mMediaIsVisible;
/**
@@ -227,7 +229,10 @@ public class KeyguardSliceProvider extends SliceProvider implements
}
protected boolean needsMediaLocked() {
- return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && mDozing;
+ // Show header if music is playing and the status bar is in the shade state. This way, an
+ // animation isn't necessary when pressing power and transitioning to AOD.
+ boolean keepWhenShade = mStatusBarState == StatusBarState.SHADE && mMediaIsVisible;
+ return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && (mDozing || keepWhenShade);
}
protected void addMediaLocked(ListBuilder listBuilder) {
@@ -454,7 +459,7 @@ public class KeyguardSliceProvider extends SliceProvider implements
synchronized (this) {
boolean nextVisible = !mMediaInvisibleStates.contains(state);
mHandler.removeCallbacksAndMessages(mMediaToken);
- if (mMediaIsVisible && !nextVisible) {
+ if (mMediaIsVisible && !nextVisible && mStatusBarState != StatusBarState.SHADE) {
// We need to delay this event for a few millis when stopping to avoid jank in the
// animation. The media app might not send its update when buffering, and the slice
// would end up without a header for 0.5 second.
@@ -511,5 +516,14 @@ public class KeyguardSliceProvider extends SliceProvider implements
@Override
public void onStateChanged(int newState) {
+ final boolean notify;
+ synchronized (this) {
+ boolean needsMedia = needsMediaLocked();
+ mStatusBarState = newState;
+ notify = needsMedia != needsMediaLocked();
+ }
+ if (notify) {
+ notifyChange();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
index 0fe5f8a6af5a..4cc5b2144adc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
@@ -15,7 +15,6 @@
package com.android.systemui.statusbar;
import android.content.pm.UserInfo;
-import android.service.notification.StatusBarNotification;
import android.util.SparseArray;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -58,7 +57,7 @@ public interface NotificationLockscreenUserManager {
boolean shouldHideNotifications(int userId);
boolean shouldHideNotifications(String key);
- boolean shouldShowOnKeyguard(StatusBarNotification sbn);
+ boolean shouldShowOnKeyguard(NotificationEntry entry);
boolean isAnyProfilePublicMode();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 4ea1ed5b9451..e08a5ae07bd8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -33,7 +33,6 @@ import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
-import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -302,7 +301,7 @@ public class NotificationLockscreenUserManagerImpl implements
Notification.VISIBILITY_SECRET;
}
- public boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
+ public boolean shouldShowOnKeyguard(NotificationEntry entry) {
if (getEntryManager() == null) {
Log.wtf(TAG, "mEntryManager was null!", new Throwable());
return false;
@@ -310,10 +309,10 @@ public class NotificationLockscreenUserManagerImpl implements
boolean exceedsPriorityThreshold;
if (NotificationUtils.useNewInterruptionModel(mContext)
&& hideSilentNotificationsOnLockscreen()) {
- exceedsPriorityThreshold = getEntryManager().getNotificationData().isHighPriority(sbn);
+ exceedsPriorityThreshold = entry.isTopBucket();
} else {
exceedsPriorityThreshold =
- !getEntryManager().getNotificationData().isAmbient(sbn.getKey());
+ !getEntryManager().getNotificationData().isAmbient(entry.key);
}
return mShowLockscreenNotifications && exceedsPriorityThreshold;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 312ea473d9e6..165c64e7a6a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -512,7 +512,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
float viewEnd = row.getTranslationY() + row.getActualHeight();
boolean isPinned = (row.isPinned() || row.isHeadsUpAnimatingAway())
&& !mAmbientState.isDozingAndNotPulsing(row);
- boolean shouldClipOwnTop = row.showingAmbientPulsing()
+ boolean shouldClipOwnTop = row.showingAmbientPulsing() && !mAmbientState.isFullyDark()
|| (mAmbientState.isPulseExpanding() && childIndex == 0);
if (viewEnd > notificationClipEnd && !shouldClipOwnTop
&& (mAmbientState.isShadeExpanded() || !isPinned)) {
@@ -752,8 +752,9 @@ public class NotificationShelf extends ActivatableNotificationView implements
iconState.scaleY = 1.0f;
iconState.hidden = false;
}
- if (row.isAboveShelf() || (!row.isInShelf() && (isLastChild && row.areGutsExposed()
- || row.getTranslationZ() > mAmbientState.getBaseZHeight()))) {
+ if ((row.isAboveShelf() || (!row.isInShelf() && (isLastChild && row.areGutsExposed()
+ || row.getTranslationZ() > mAmbientState.getBaseZHeight())))
+ && !mAmbientState.isFullyDark()) {
iconState.hidden = true;
}
int backgroundColor = getBackgroundColorWithoutTint();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 404920187351..9c3ee96fe25b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -394,15 +394,13 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
int userId = entry.notification.getUserId();
boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(
entry.notification) && !entry.isRowRemoved();
- boolean showOnKeyguard = mLockscreenUserManager.shouldShowOnKeyguard(entry
- .notification);
+ boolean showOnKeyguard = mLockscreenUserManager.shouldShowOnKeyguard(entry);
if (!showOnKeyguard) {
// min priority notifications should show if their summary is showing
if (mGroupManager.isChildInGroupWithSummary(entry.notification)) {
NotificationEntry summary = mGroupManager.getLogicalGroupSummary(
entry.notification);
- if (summary != null && mLockscreenUserManager.shouldShowOnKeyguard(
- summary.notification)) {
+ if (summary != null && mLockscreenUserManager.shouldShowOnKeyguard(summary)) {
showOnKeyguard = true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 0d9f4e7b909d..91d47077fc31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -153,6 +153,7 @@ public class ActivityLaunchAnimator {
if (primary == null) {
setAnimationPending(false);
invokeCallback(iRemoteAnimationFinishedCallback);
+ mNotificationPanel.collapse(false /* delayed */, 1.0f /* speedUpFactor */);
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
index 64b2f048ce2e..13f8f1a6a548 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
@@ -25,7 +25,6 @@ import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
-import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
@@ -108,10 +107,19 @@ public class NotificationData {
boolean bSystemMax = bImportance >= NotificationManager.IMPORTANCE_HIGH
&& isSystemNotification(nb);
- boolean isHeadsUp = a.getRow().isHeadsUp();
- if (isHeadsUp != b.getRow().isHeadsUp()) {
- return isHeadsUp ? -1 : 1;
- } else if (isHeadsUp) {
+
+ boolean aHeadsUp = a.getRow().isHeadsUp();
+ boolean bHeadsUp = b.getRow().isHeadsUp();
+
+ // HACK: This should really go elsewhere, but it's currently not straightforward to
+ // extract the comparison code and we're guaranteed to touch every element, so this is
+ // the best place to set the buckets for the moment.
+ a.setIsTopBucket(aHeadsUp || aMedia || aSystemMax || a.isHighPriority());
+ b.setIsTopBucket(bHeadsUp || bMedia || bSystemMax || b.isHighPriority());
+
+ if (aHeadsUp != bHeadsUp) {
+ return aHeadsUp ? -1 : 1;
+ } else if (aHeadsUp) {
// Provide consistent ranking with headsUpManager
return mHeadsUpManager.compare(a, b);
} else if (a.getRow().showingAmbientPulsing() != b.getRow().showingAmbientPulsing()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 92c261c4cad7..d157f06c03e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -173,6 +173,8 @@ public final class NotificationEntry {
*/
private boolean mHighPriority;
+ private boolean mIsTopBucket;
+
public NotificationEntry(StatusBarNotification n) {
this(n, null);
}
@@ -220,6 +222,18 @@ public final class NotificationEntry {
this.mHighPriority = highPriority;
}
+ /**
+ * @return True if the notif should appear in the "top" or "important" section of notifications
+ * (as opposed to the "bottom" or "silent" section). This is usually the same as
+ * {@link #isHighPriority()}, but there are certain exceptions, such as media notifs.
+ */
+ public boolean isTopBucket() {
+ return mIsTopBucket;
+ }
+ public void setIsTopBucket(boolean isTopBucket) {
+ mIsTopBucket = isTopBucket;
+ }
+
public boolean isBubble() {
return (notification.getNotification().flags & FLAG_BUBBLE) != 0;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
index 170a4d570688..d119fb79e4c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
@@ -133,7 +133,7 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide
if (child instanceof ExpandableNotificationRow
&& child.getVisibility() != View.GONE) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- if (!row.getEntry().isHighPriority()) {
+ if (!row.getEntry().isTopBucket()) {
firstGentleNotifIndex = i;
mFirstGentleNotif = row;
break;
@@ -248,7 +248,7 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide
View child = mParent.getChildAt(i);
if (child.getVisibility() != View.GONE && child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- if (!row.getEntry().isHighPriority()) {
+ if (!row.getEntry().isTopBucket()) {
break;
} else {
lastChildBeforeGap = row;
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 8fe34180203f..237825e44b97 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
@@ -1355,7 +1355,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
mIsClipped = clipped;
}
- if (!mAmbientPulseManager.hasNotifications() && mAmbientState.isFullyDark()) {
+ if (!mPulsing && mAmbientState.isFullyDark()) {
setClipBounds(null);
} else if (mAmbientState.isDarkAtAll()) {
clipToOutline = true;
@@ -2516,12 +2516,20 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
return;
}
- int minTopPosition = 0;
+ int minTopPosition;
NotificationSection lastSection = getLastVisibleSection();
if (mStatusBarState != StatusBarState.KEYGUARD) {
minTopPosition = (int) (mTopPadding + mStackTranslation);
} else if (lastSection == null) {
minTopPosition = mTopPadding;
+ } else {
+ // The first sections could be empty while there could still be elements in later
+ // sections. The position of these first few sections is determined by the position of
+ // the first visible section.
+ NotificationSection firstVisibleSection = getFirstVisibleSection();
+ firstVisibleSection.updateBounds(0 /* minTopPosition*/, 0 /* minBottomPosition */,
+ false /* shiftPulsingWithFirst */);
+ minTopPosition = firstVisibleSection.getBounds().top;
}
boolean shiftPulsingWithFirst = mAmbientPulseManager.getAllEntries().count() <= 1;
for (NotificationSection section : mSections) {
@@ -5161,6 +5169,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
return;
}
mPulsing = pulsing;
+ updateClipping();
mAmbientState.setPulsing(pulsing);
mSwipeHelper.setPulsing(pulsing);
updateNotificationAnimationStates();
@@ -5768,7 +5777,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
currentIndex++;
boolean beforeSpeedBump;
if (mHighPriorityBeforeSpeedBump) {
- beforeSpeedBump = row.getEntry().isHighPriority();
+ beforeSpeedBump = row.getEntry().isTopBucket();
} else {
beforeSpeedBump = !row.getEntry().ambient;
}
@@ -5826,9 +5835,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
case ROWS_ALL:
return true;
case ROWS_HIGH_PRIORITY:
- return row.getEntry().isHighPriority();
+ return row.getEntry().isTopBucket();
case ROWS_GENTLE:
- return !row.getEntry().isHighPriority();
+ return !row.getEntry().isTopBucket();
default:
throw new IllegalArgumentException("Unknown selection: " + selection);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 60061c6a9ad2..d9f8c88e0d13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -501,7 +501,8 @@ public class StackScrollAlgorithm {
continue;
}
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- if (!row.showingAmbientPulsing() || (i == 0 && ambientState.isPulseExpanding())) {
+ if (!row.showingAmbientPulsing() || ambientState.isFullyDark()
+ || (i == 0 && ambientState.isPulseExpanding())) {
continue;
}
ExpandableViewState viewState = row.getViewState();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 4d4818d51414..eccd70b4a597 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -132,6 +132,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
private BiometricSourceType mPendingAuthenticatedBioSourceType = null;
private boolean mPendingShowBouncer;
private boolean mHasScreenTurnedOnSinceAuthenticating;
+ private boolean mFadedAwayAfterWakeAndUnlock;
private final TunerService.Tunable mFaceDismissedKeyguardTunable = new TunerService.Tunable() {
@Override
@@ -360,6 +361,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
@Override
public void onStartedGoingToSleep(int why) {
resetMode();
+ mFadedAwayAfterWakeAndUnlock = false;
mPendingAuthenticatedUserId = -1;
mPendingAuthenticatedBioSourceType = null;
}
@@ -454,6 +456,9 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
}
public void finishKeyguardFadingAway() {
+ if (isWakeAndUnlock()) {
+ mFadedAwayAfterWakeAndUnlock = true;
+ }
resetMode();
}
@@ -504,6 +509,14 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
}
/**
+ * Successful authentication with fingerprint, face, or iris that wakes up the device.
+ * This will return {@code true} even after the keyguard fades away.
+ */
+ public boolean unlockedByWakeAndUnlock() {
+ return isWakeAndUnlock() || mFadedAwayAfterWakeAndUnlock;
+ }
+
+ /**
* Successful authentication with fingerprint, face, or iris when the screen was either
* on or off.
*/
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 a0cda693822f..595c1acaf56d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
+import android.graphics.Region;
import android.util.Log;
import android.util.Pools;
import android.view.DisplayCutout;
@@ -76,7 +77,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
private int[] mTmpTwoArray = new int[2];
private boolean mHeadsUpGoingAway;
private int mStatusBarState;
- private Rect mTouchableRegion = new Rect();
+ private Region mTouchableRegion = new Region();
private AnimationStateHandler mAnimationStateHandler;
@@ -299,12 +300,16 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
info.touchableRegion.set(calculateTouchableRegion());
}
- public Rect calculateTouchableRegion() {
- if (!hasPinnedHeadsUp()) {
+ public Region calculateTouchableRegion() {
+ NotificationEntry topEntry = getTopEntry();
+ // This call could be made in an inconsistent state while the pinnedMode hasn't been
+ // updated yet, but callbacks leading out of the headsUp manager, querying it. Let's
+ // therefore also check if the topEntry is null.
+ if (!hasPinnedHeadsUp() || topEntry == null) {
mTouchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
updateRegionForNotch(mTouchableRegion);
+
} else {
- NotificationEntry topEntry = getTopEntry();
if (topEntry.isChildInGroup()) {
final NotificationEntry groupSummary =
mGroupManager.getGroupSummary(topEntry.notification);
@@ -322,7 +327,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
return mTouchableRegion;
}
- private void updateRegionForNotch(Rect region) {
+ private void updateRegionForNotch(Region region) {
DisplayCutout cutout = mStatusBarWindowView.getRootWindowInsets().getDisplayCutout();
if (cutout == null) {
return;
@@ -390,6 +395,8 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
super.dumpInternal(fd, pw, args);
pw.print(" mBarState=");
pw.println(mStatusBarState);
+ pw.print(" mTouchableRegion=");
+ pw.println(mTouchableRegion);
}
///////////////////////////////////////////////////////////////////////////////////////////////
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 1027046b0c28..bc205d676914 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -38,6 +38,7 @@ import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
+import android.graphics.Region;
import android.os.PowerManager;
import android.util.AttributeSet;
import android.util.Log;
@@ -620,9 +621,10 @@ public class NotificationPanelView extends PanelView implements
private Rect calculateGestureExclusionRect() {
Rect exclusionRect = null;
- if (isFullyCollapsed()) {
+ Region touchableRegion = mHeadsUpManager.calculateTouchableRegion();
+ if (isFullyCollapsed() && touchableRegion != null) {
// Note: The heads up manager also calculates the non-pinned touchable region
- exclusionRect = mHeadsUpManager.calculateTouchableRegion();
+ exclusionRect = touchableRegion.getBounds();
}
return exclusionRect != null
? exclusionRect
@@ -732,8 +734,7 @@ public class NotificationPanelView extends PanelView implements
if (suppressedSummary) {
continue;
}
- if (!mLockscreenUserManager.shouldShowOnKeyguard(
- row.getStatusBarNotification())) {
+ if (!mLockscreenUserManager.shouldShowOnKeyguard(row.getEntry())) {
continue;
}
if (row.isRemoved()) {
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 1aa8bd79af35..c6de829e49be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -482,9 +482,12 @@ public class StatusBar extends SystemUI implements DemoMode,
WallpaperInfo info = wallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT);
final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_dozeSupportsAodWallpaper);
+ final boolean imageWallpaperInAmbient =
+ !DozeParameters.getInstance(mContext).getDisplayNeedsBlanking();
// If WallpaperInfo is null, it must be ImageWallpaper.
final boolean supportsAmbientMode = deviceSupportsAodWallpaper
- && (info == null || info.supportsAmbientMode());
+ && ((info == null && imageWallpaperInAmbient)
+ || (info != null && info.supportsAmbientMode()));
mStatusBarWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
@@ -1213,6 +1216,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mDozeScrimController, keyguardViewMediator,
mScrimController, this, UnlockMethodCache.getInstance(mContext),
new Handler(), mKeyguardUpdateMonitor, Dependency.get(TunerService.class));
+ putComponent(BiometricUnlockController.class, mBiometricUnlockController);
mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
getBouncerContainer(), mNotificationPanel, mBiometricUnlockController,
mStatusBarWindow.findViewById(R.id.lock_icon_container));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
index 329ef1c19a2b..7ea6493da83d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
@@ -56,6 +56,9 @@ public class FalsingManagerProxyTest extends SysuiTestCase {
mHandler = new Handler(mTestableLooper.getLooper());
mDefaultConfigValue = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
BRIGHTLINE_FALSING_MANAGER_ENABLED, false);
+ // In case it runs on a device where it's been set to true, set it to false by hand.
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ BRIGHTLINE_FALSING_MANAGER_ENABLED, "false", false);
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
index 87ae85f6d302..f07edf331f13 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
@@ -18,6 +18,7 @@ package com.android.systemui.doze;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -29,6 +30,7 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.DozeParameters;
import org.junit.Before;
@@ -44,12 +46,14 @@ public class DozeWallpaperStateTest extends SysuiTestCase {
private DozeWallpaperState mDozeWallpaperState;
@Mock IWallpaperManager mIWallpaperManager;
+ @Mock BiometricUnlockController mBiometricUnlockController;
@Mock DozeParameters mDozeParameters;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mDozeWallpaperState = new DozeWallpaperState(mIWallpaperManager, mDozeParameters);
+ mDozeWallpaperState = new DozeWallpaperState(mIWallpaperManager, mBiometricUnlockController,
+ mDozeParameters);
}
@Test
@@ -102,6 +106,20 @@ public class DozeWallpaperStateTest extends SysuiTestCase {
}
@Test
+ public void testDoesNotAnimate_whenWakeAndUnlock() throws RemoteException {
+ // Pre-conditions
+ when(mDozeParameters.getAlwaysOn()).thenReturn(true);
+ when(mBiometricUnlockController.unlockedByWakeAndUnlock()).thenReturn(true);
+
+ mDozeWallpaperState.transitionTo(DozeMachine.State.UNINITIALIZED,
+ DozeMachine.State.DOZE_AOD);
+ clearInvocations(mIWallpaperManager);
+
+ mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_AOD, DozeMachine.State.FINISH);
+ verify(mIWallpaperManager).setInAmbientMode(eq(false), eq(0L));
+ }
+
+ @Test
public void testTransitionTo_requestPulseIsAmbientMode() throws RemoteException {
mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE,
DozeMachine.State.DOZE_REQUEST_PULSE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index 44191147f914..a83c4b653ce7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -48,6 +48,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.wakelock.SettableWakeLock;
@@ -177,6 +178,7 @@ public class KeyguardSliceProviderTest extends SysuiTestCase {
@Test
public void onMetadataChanged_updatesSlice() {
+ mProvider.onStateChanged(StatusBarState.KEYGUARD);
mProvider.onDozingChanged(true);
reset(mContentResolver);
mProvider.onMetadataOrStateChanged(mock(MediaMetadata.class), PlaybackState.STATE_PLAYING);
@@ -190,6 +192,7 @@ public class KeyguardSliceProviderTest extends SysuiTestCase {
@Test
public void onDozingChanged_updatesSliceIfMedia() {
+ mProvider.onStateChanged(StatusBarState.KEYGUARD);
mProvider.onMetadataOrStateChanged(mock(MediaMetadata.class), PlaybackState.STATE_PLAYING);
reset(mContentResolver);
// Show media when dozing
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 49a263a8d781..57dd8c94c790 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -38,7 +38,6 @@ import android.os.Handler;
import android.os.Looper;
import android.os.UserManager;
import android.provider.Settings;
-import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -48,6 +47,7 @@ import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -166,7 +166,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1);
when(mNotificationData.isHighPriority(any())).thenReturn(false);
- assertTrue(mLockscreenUserManager.shouldShowOnKeyguard(mock(StatusBarNotification.class)));
+ assertTrue(mLockscreenUserManager.shouldShowOnKeyguard(mock(NotificationEntry.class)));
}
@Test
@@ -179,7 +179,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 0);
when(mNotificationData.isHighPriority(any())).thenReturn(false);
- assertFalse(mLockscreenUserManager.shouldShowOnKeyguard(mock(StatusBarNotification.class)));
+ assertFalse(mLockscreenUserManager.shouldShowOnKeyguard(mock(NotificationEntry.class)));
}
private class TestNotificationLockscreenUserManager
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
index 73abda9a5da7..59d0f912d38e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
@@ -263,6 +263,8 @@ public class NotificationSectionsManagerTest extends SysuiTestCase {
when(notifRow.getVisibility()).thenReturn(View.VISIBLE);
when(notifRow.getEntry().isHighPriority())
.thenReturn(children[i] == ChildType.HIPRI);
+ when(notifRow.getEntry().isTopBucket())
+ .thenReturn(children[i] == ChildType.HIPRI);
when(notifRow.getParent()).thenReturn(mNssl);
child = notifRow;
break;
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index bc7da3fe2edc..30a356325ada 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -413,15 +413,15 @@ final class UiModeManagerService extends SystemService {
try {
synchronized (mLock) {
if (mNightMode != mode) {
- if (UserManager.get(getContext()).isPrimaryUser()) {
- SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME,
- Integer.toString(mode));
- }
-
// Only persist setting if not in car mode
if (!mCarModeEnabled) {
Secure.putIntForUser(getContext().getContentResolver(),
Secure.UI_NIGHT_MODE, mode, user);
+
+ if (UserManager.get(getContext()).isPrimaryUser()) {
+ SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME,
+ Integer.toString(mode));
+ }
}
mNightMode = mode;
diff --git a/services/core/java/com/android/server/locksettings/PasswordSlotManager.java b/services/core/java/com/android/server/locksettings/PasswordSlotManager.java
index 5cbd237a0722..4ef63c05325c 100644
--- a/services/core/java/com/android/server/locksettings/PasswordSlotManager.java
+++ b/services/core/java/com/android/server/locksettings/PasswordSlotManager.java
@@ -122,7 +122,7 @@ public class PasswordSlotManager {
*/
public void markSlotDeleted(int slot) throws RuntimeException {
ensureSlotMapLoaded();
- if (mSlotMap.containsKey(slot) && mSlotMap.get(slot) != getMode()) {
+ if (mSlotMap.containsKey(slot) && !mSlotMap.get(slot).equals(getMode())) {
throw new RuntimeException("password slot " + slot + " cannot be deleted");
}
mSlotMap.remove(slot);
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 6f28675d051b..934511bf88d1 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -296,22 +296,12 @@ final class OverlayManagerServiceImpl {
*/
private void updateAndRefreshOverlaysForTarget(@NonNull final String targetPackageName,
final int userId, final int flags) {
- final List<OverlayInfo> ois = new ArrayList<>();
-
- // Framework overlays added first because order matters when resolving a resource
- if (!"android".equals(targetPackageName)) {
- ois.addAll(mSettings.getOverlaysForTarget("android", userId));
- }
-
- // Then add the targeted, non-framework overlays which have higher priority
- ois.addAll(mSettings.getOverlaysForTarget(targetPackageName, userId));
-
- final List<String> enabledBaseCodePaths = new ArrayList<>(ois.size());
+ final List<OverlayInfo> targetOverlays = mSettings.getOverlaysForTarget(targetPackageName,
+ userId);
+ // Update the state for any overlay that targets this package.
boolean modified = false;
- final int n = ois.size();
- for (int i = 0; i < n; i++) {
- final OverlayInfo oi = ois.get(i);
+ for (final OverlayInfo oi : targetOverlays) {
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(oi.packageName,
userId);
if (overlayPackage == null) {
@@ -324,25 +314,39 @@ final class OverlayManagerServiceImpl {
Slog.e(TAG, "failed to update settings", e);
modified |= mSettings.remove(oi.packageName, userId);
}
-
- if (oi.isEnabled() && overlayPackage.applicationInfo != null) {
- enabledBaseCodePaths.add(overlayPackage.applicationInfo.getBaseCodePath());
- }
}
}
if (!modified) {
+ // Update the overlay paths of the target within package manager if necessary.
+ final List<String> enabledOverlayPaths = new ArrayList<>(targetOverlays.size());
+
+ // Framework overlays are first in the overlay paths of a package within PackageManager.
+ for (final OverlayInfo oi : mSettings.getOverlaysForTarget("android", userId)) {
+ if (oi.isEnabled()) {
+ enabledOverlayPaths.add(oi.baseCodePath);
+ }
+ }
+
+ for (final OverlayInfo oi : targetOverlays) {
+ if (oi.isEnabled()) {
+ enabledOverlayPaths.add(oi.baseCodePath);
+ }
+ }
+
+ // TODO(): Use getEnabledOverlayPaths(userId, targetPackageName) instead of
+ // resourceDirs if in the future resourceDirs contains APKs other than overlays
PackageInfo packageInfo = mPackageManager.getPackageInfo(targetPackageName, userId);
ApplicationInfo appInfo = packageInfo == null ? null : packageInfo.applicationInfo;
String[] resourceDirs = appInfo == null ? null : appInfo.resourceDirs;
// If the lists aren't the same length, the enabled overlays have changed
- if (ArrayUtils.size(resourceDirs) != enabledBaseCodePaths.size()) {
+ if (ArrayUtils.size(resourceDirs) != enabledOverlayPaths.size()) {
modified = true;
} else if (resourceDirs != null) {
// If any element isn't equal, an overlay or the order of overlays has changed
for (int index = 0; index < resourceDirs.length; index++) {
- if (!resourceDirs[index].equals(enabledBaseCodePaths.get(index))) {
+ if (!resourceDirs[index].equals(enabledOverlayPaths.get(index))) {
modified = true;
break;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 24a0c885223b..94d262b896a7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -318,6 +318,7 @@ import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.permission.PermissionManagerServiceInternal.PermissionCallback;
import com.android.server.pm.permission.PermissionsState;
+import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.security.VerityUtils;
import com.android.server.storage.DeviceStorageMonitorInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -11032,14 +11033,15 @@ public class PackageManagerService extends IPackageManager.Stub
final String realPkgName = request.realPkgName;
final List<String> changedAbiCodePath = result.changedAbiCodePath;
final PackageSetting pkgSetting;
+ if (request.pkgSetting != null && request.pkgSetting.sharedUser != null
+ && request.pkgSetting.sharedUser != result.pkgSetting.sharedUser) {
+ // shared user changed, remove from old shared user
+ request.pkgSetting.sharedUser.removePackage(request.pkgSetting);
+ }
if (result.existingSettingCopied) {
pkgSetting = request.pkgSetting;
pkgSetting.updateFrom(result.pkgSetting);
pkg.mExtras = pkgSetting;
- if (pkgSetting.sharedUser != null
- && pkgSetting.sharedUser.removePackage(result.pkgSetting)) {
- pkgSetting.sharedUser.addPackage(pkgSetting);
- }
} else {
pkgSetting = result.pkgSetting;
if (originalPkgSetting != null) {
@@ -11049,6 +11051,9 @@ public class PackageManagerService extends IPackageManager.Stub
mTransferedPackages.add(originalPkgSetting.name);
}
}
+ if (pkgSetting.sharedUser != null) {
+ pkgSetting.sharedUser.addPackage(pkgSetting);
+ }
// TODO(toddke): Consider a method specifically for modifying the Package object
// post scan; or, moving this stuff out of the Package object since it has nothing
// to do with the package on disk.
@@ -16591,13 +16596,13 @@ public class PackageManagerService extends IPackageManager.Stub
&& compareSignatures(sharedUserSignatures,
pkg.mSigningDetails.signatures)
!= PackageManager.SIGNATURE_MATCH) {
- if (SystemProperties.getInt("ro.product.first_api_level", 0) <= 28) {
+ if (SystemProperties.getInt("ro.product.first_api_level", 0) <= 29) {
// Mismatched signatures is an error and silently skipping system
// packages will likely break the device in unforeseen ways.
- // However,
- // we allow the device to boot anyway because, prior to P,
- // vendors were
- // not expecting the platform to crash in this situation.
+ // However, we allow the device to boot anyway because, prior to Q,
+ // vendors were not expecting the platform to crash in this
+ // situation.
+ // This WILL be a hard failure on any new API levels after Q.
throw new ReconcileFailure(
INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
"Signature mismatch for shared user: "
@@ -21634,6 +21639,17 @@ public class PackageManagerService extends IPackageManager.Stub
mPermissionManager.updateAllPermissions(
StorageManager.UUID_PRIVATE_INTERNAL, false, mPackages.values(),
mPermissionCallback);
+
+ final PermissionPolicyInternal permissionPolicyInternal =
+ LocalServices.getService(PermissionPolicyInternal.class);
+ permissionPolicyInternal.setOnInitializedCallback(userId -> {
+ // The SDK updated case is already handled when we run during the ctor.
+ synchronized (mPackages) {
+ mPermissionManager.updateAllPermissions(
+ StorageManager.UUID_PRIVATE_INTERNAL, false /*sdkUpdated*/,
+ mPackages.values(), mPermissionCallback);
+ }
+ });
}
// Watch for external volumes that come and go over time
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index f8c4f6b2cdba..4550446f88c5 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1170,6 +1170,11 @@ public final class DefaultPermissionGrantPolicy {
final int flags = mContext.getPackageManager().getPermissionFlags(
permission, pkg.packageName, user);
+ // If we are trying to grant as system fixed and already system fixed
+ // then the system can change the system fixed grant state.
+ final boolean changingGrantForSystemFixed = systemFixed
+ && (flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0;
+
// Certain flags imply that the permission's current state by the system or
// device/profile owner or the user. In these cases we do not want to clobber the
// current state.
@@ -1177,7 +1182,8 @@ public final class DefaultPermissionGrantPolicy {
// Unless the caller wants to override user choices. The override is
// to make sure we can grant the needed permission to the default
// sms and phone apps after the user chooses this in the UI.
- if (!isFixedOrUserSet(flags) || ignoreSystemPackage) {
+ if (!isFixedOrUserSet(flags) || ignoreSystemPackage
+ || changingGrantForSystemFixed) {
// Never clobber policy fixed permissions.
// We must allow the grant of a system-fixed permission because
// system-fixed is sticky, but the permission itself may be revoked.
@@ -1196,6 +1202,14 @@ public final class DefaultPermissionGrantPolicy {
PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT, user);
}
+ // If the system tries to change a system fixed permission from one fixed
+ // state to another we need to drop the fixed flag to allow the grant.
+ if (changingGrantForSystemFixed) {
+ mContext.getPackageManager().updatePermissionFlags(permission,
+ pkg.packageName, flags,
+ flags & ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, user);
+ }
+
if (pm.checkPermission(permission, pkg.packageName)
!= PackageManager.PERMISSION_GRANTED) {
mContext.getPackageManager()
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index d3e5df5d62d1..8884821c770e 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -97,6 +97,7 @@ import com.android.server.pm.SharedUserSetting;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal.PermissionCallback;
import com.android.server.pm.permission.PermissionsState.PermissionState;
+import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.policy.SoftRestrictedPermissionPolicy;
import libcore.util.EmptyArray;
@@ -197,6 +198,9 @@ public class PermissionManagerService {
@GuardedBy("mLock")
private boolean mSystemReady;
+ @GuardedBy("mLock")
+ private PermissionPolicyInternal mPermissionPolicyInternal;
+
/**
* For each foreground/background permission the mapping:
* Background permission -> foreground permissions
@@ -1080,6 +1084,13 @@ public class PermissionManagerService {
boolean softRestricted = bp.isSoftRestricted();
for (int userId : currentUserIds) {
+ // If permission policy is not ready we don't deal with restricted
+ // permissions as the policy may whitelist some permissions. Once
+ // the policy is initialized we would re-evaluate permissions.
+ final boolean permissionPolicyInitialized =
+ mPermissionPolicyInternal != null
+ && mPermissionPolicyInternal.isInitialized(userId);
+
PermissionState permState = origPermissions
.getRuntimePermissionState(perm, userId);
int flags = permState != null ? permState.getFlags() : 0;
@@ -1094,7 +1105,7 @@ public class PermissionManagerService {
if (appSupportsRuntimePermissions) {
// If hard restricted we don't allow holding it
- if (hardRestricted) {
+ if (permissionPolicyInitialized && hardRestricted) {
if (!restrictionExempt) {
if (permState != null && permState.isGranted()
&& permissionsState.revokeRuntimePermission(
@@ -1107,7 +1118,7 @@ public class PermissionManagerService {
}
}
// If soft restricted we allow holding in a restricted form
- } else if (softRestricted) {
+ } else if (permissionPolicyInitialized && softRestricted) {
// Regardless if granted set the restriction flag as it
// may affect app treatment based on this permission.
if (!restrictionExempt && !restrictionApplied) {
@@ -1126,7 +1137,8 @@ public class PermissionManagerService {
flags &= ~FLAG_PERMISSION_REVOKE_ON_UPGRADE;
wasChanged = true;
// Hard restricted permissions cannot be held.
- } else if (!hardRestricted || restrictionExempt) {
+ } else if (!permissionPolicyInitialized
+ || (!hardRestricted || restrictionExempt)) {
if (permState != null && permState.isGranted()) {
if (permissionsState.grantRuntimePermission(bp, userId)
== PERMISSION_OPERATION_FAILURE) {
@@ -1155,33 +1167,28 @@ public class PermissionManagerService {
// If legacy app always grant the permission but if restricted
// and not exempt take a note a restriction should be applied.
- if ((hardRestricted || softRestricted)
- && !restrictionExempt && !restrictionApplied) {
+ if (permissionPolicyInitialized
+ && (hardRestricted || softRestricted)
+ && !restrictionExempt && !restrictionApplied) {
flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
wasChanged = true;
}
}
// If unrestricted or restriction exempt, don't apply restriction.
- if (!(hardRestricted || softRestricted) || restrictionExempt) {
- if (restrictionApplied) {
- flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;
- // Dropping restriction on a legacy app requires a review.
- if (!appSupportsRuntimePermissions) {
- flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
+ if (permissionPolicyInitialized) {
+ if (!(hardRestricted || softRestricted) || restrictionExempt) {
+ if (restrictionApplied) {
+ flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;
+ // Dropping restriction on a legacy app implies a review
+ if (!appSupportsRuntimePermissions) {
+ flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
+ }
+ wasChanged = true;
}
- wasChanged = true;
}
}
- if (hardRestricted && !restrictionExempt
- && (flags & FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
- // Applying a hard restriction implies revoking it. This might
- // lead to a system-fixed, revoked permission.
- flags &= ~FLAG_PERMISSION_SYSTEM_FIXED;
- wasChanged = true;
- }
-
if (wasChanged) {
updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
}
@@ -1216,6 +1223,13 @@ public class PermissionManagerService {
boolean softRestricted = bp.isSoftRestricted();
for (int userId : currentUserIds) {
+ // If permission policy is not ready we don't deal with restricted
+ // permissions as the policy may whitelist some permissions. Once
+ // the policy is initialized we would re-evaluate permissions.
+ final boolean permissionPolicyInitialized =
+ mPermissionPolicyInternal != null
+ && mPermissionPolicyInternal.isInitialized(userId);
+
boolean wasChanged = false;
boolean restrictionExempt =
@@ -1226,7 +1240,7 @@ public class PermissionManagerService {
if (appSupportsRuntimePermissions) {
// If hard restricted we don't allow holding it
- if (hardRestricted) {
+ if (permissionPolicyInitialized && hardRestricted) {
if (!restrictionExempt) {
if (permState != null && permState.isGranted()
&& permissionsState.revokeRuntimePermission(
@@ -1239,7 +1253,7 @@ public class PermissionManagerService {
}
}
// If soft restricted we allow holding in a restricted form
- } else if (softRestricted) {
+ } else if (permissionPolicyInitialized && softRestricted) {
// Regardless if granted set the restriction flag as it
// may affect app treatment based on this permission.
if (!restrictionExempt && !restrictionApplied) {
@@ -1258,7 +1272,8 @@ public class PermissionManagerService {
flags &= ~FLAG_PERMISSION_REVOKE_ON_UPGRADE;
wasChanged = true;
// Hard restricted permissions cannot be held.
- } else if (!hardRestricted || restrictionExempt) {
+ } else if (!permissionPolicyInitialized ||
+ (!hardRestricted || restrictionExempt)) {
if (permissionsState.grantRuntimePermission(bp, userId) !=
PERMISSION_OPERATION_FAILURE) {
wasChanged = true;
@@ -1274,22 +1289,25 @@ public class PermissionManagerService {
// If legacy app always grant the permission but if restricted
// and not exempt take a note a restriction should be applied.
- if ((hardRestricted || softRestricted)
- && !restrictionExempt && !restrictionApplied) {
+ if (permissionPolicyInitialized
+ && (hardRestricted || softRestricted)
+ && !restrictionExempt && !restrictionApplied) {
flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
wasChanged = true;
}
}
// If unrestricted or restriction exempt, don't apply restriction.
- if (!(hardRestricted || softRestricted) || restrictionExempt) {
- if (restrictionApplied) {
- flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;
- // Dropping restriction on a legacy app requires a review.
- if (!appSupportsRuntimePermissions) {
- flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
+ if (permissionPolicyInitialized) {
+ if (!(hardRestricted || softRestricted) || restrictionExempt) {
+ if (restrictionApplied) {
+ flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;
+ // Dropping restriction on a legacy app implies a review
+ if (!appSupportsRuntimePermissions) {
+ flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
+ }
+ wasChanged = true;
}
- wasChanged = true;
}
}
@@ -2900,6 +2918,7 @@ public class PermissionManagerService {
}
mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class);
+ mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class);
}
private static String getVolumeUuidForPackage(PackageParser.Package pkg) {
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyInternal.java b/services/core/java/com/android/server/policy/PermissionPolicyInternal.java
index 7760c1edd9e6..6084c6718577 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyInternal.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyInternal.java
@@ -18,6 +18,7 @@ package com.android.server.policy;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.content.Intent;
/**
@@ -26,6 +27,19 @@ import android.content.Intent;
public abstract class PermissionPolicyInternal {
/**
+ * Callback for initializing the permission policy service.
+ */
+ public interface OnInitializedCallback {
+
+ /**
+ * Called when initialized for the given user.
+ *
+ * @param userId The initialized user.
+ */
+ void onInitialized(@UserIdInt int userId);
+ }
+
+ /**
* Check whether an activity should be started.
*
* @param intent the {@link Intent} for the activity start
@@ -36,4 +50,17 @@ public abstract class PermissionPolicyInternal {
*/
public abstract boolean checkStartActivity(@NonNull Intent intent, int callingUid,
@Nullable String callingPackage);
+
+ /**
+ * @return Whether the policy is initialized for a user.
+ */
+ public abstract boolean isInitialized(@UserIdInt int userId);
+
+ /**
+ * Set a callback for users being initialized. If the user is already
+ * initialized the callback will not be invoked.
+ *
+ * @param callback The callback to register.
+ */
+ public abstract void setOnInitializedCallback(@NonNull OnInitializedCallback callback);
}
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 037293f9536c..3d543c96aacc 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -66,6 +66,7 @@ import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
@@ -86,6 +87,10 @@ public final class PermissionPolicyService extends SystemService {
@GuardedBy("mLock")
private final SparseBooleanArray mIsStarted = new SparseBooleanArray();
+ /** Callbacks for when a user is initialized */
+ @GuardedBy("mLock")
+ private OnInitializedCallback mOnInitializedCallback;
+
/**
* Whether an async {@link #synchronizePackagePermissionsAndAppOpsForUser} is currently
* scheduled for a package/user.
@@ -240,12 +245,20 @@ public final class PermissionPolicyService extends SystemService {
grantOrUpgradeDefaultRuntimePermissionsIfNeeded(userId);
+ final OnInitializedCallback callback;
+
synchronized (mLock) {
mIsStarted.put(userId, true);
+ callback = mOnInitializedCallback;
}
// Force synchronization as permissions might have changed
synchronizePermissionsAndAppOpsForUser(userId);
+
+ // Tell observers we are initialized for this user.
+ if (callback != null) {
+ callback.onInitialized(userId);
+ }
}
@Override
@@ -798,7 +811,7 @@ public final class PermissionPolicyService extends SystemService {
@Override
public boolean checkStartActivity(@NonNull Intent intent, int callingUid,
@Nullable String callingPackage) {
- if (callingPackage != null && isActionRemovedForCallingPackage(intent.getAction(),
+ if (callingPackage != null && isActionRemovedForCallingPackage(intent, callingUid,
callingPackage)) {
Slog.w(LOG_TAG, "Action Removed: starting " + intent.toString() + " from "
+ callingPackage + " (uid=" + callingUid + ")");
@@ -807,12 +820,25 @@ public final class PermissionPolicyService extends SystemService {
return true;
}
+ @Override
+ public boolean isInitialized(int userId) {
+ return isStarted(userId);
+ }
+
+ @Override
+ public void setOnInitializedCallback(@NonNull OnInitializedCallback callback) {
+ synchronized (mLock) {
+ mOnInitializedCallback = callback;
+ }
+ }
+
/**
* Check if the intent action is removed for the calling package (often based on target SDK
* version). If the action is removed, we'll silently cancel the activity launch.
*/
- private boolean isActionRemovedForCallingPackage(@Nullable String action,
+ private boolean isActionRemovedForCallingPackage(@NonNull Intent intent, int callingUid,
@NonNull String callingPackage) {
+ String action = intent.getAction();
if (action == null) {
return false;
}
@@ -821,15 +847,19 @@ public final class PermissionPolicyService extends SystemService {
case Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT: {
ApplicationInfo applicationInfo;
try {
- applicationInfo = getContext().getPackageManager().getApplicationInfo(
- callingPackage, 0);
+ applicationInfo = getContext().getPackageManager().getApplicationInfoAsUser(
+ callingPackage, 0, UserHandle.getUserId(callingUid));
+ if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q) {
+ // Applications targeting Q or higher should use
+ // RoleManager.createRequestRoleIntent() instead.
+ return true;
+ }
} catch (PackageManager.NameNotFoundException e) {
Slog.i(LOG_TAG, "Cannot find application info for " + callingPackage);
- return false;
}
- // Applications targeting Q should use RoleManager.createRequestRoleIntent()
- // instead.
- return applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
+ // Make sure RequestRoleActivity can know the calling package if we allow it.
+ intent.putExtra(Intent.EXTRA_CALLING_PACKAGE, callingPackage);
+ return false;
}
default:
return false;
diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
index d53f6854dfdf..c1a6dbd8ae14 100644
--- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
+++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
@@ -28,11 +28,14 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_INST
import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
+import static java.lang.Integer.min;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.os.Build;
import android.os.UserHandle;
@@ -73,6 +76,41 @@ public abstract class SoftRestrictedPermissionPolicy {
};
/**
+ * TargetSDK is per package. To make sure two apps int the same shared UID do not fight over
+ * what to set, always compute the combined targetSDK.
+ *
+ * @param context A context
+ * @param appInfo The app that is changed
+ * @param user The user the app belongs to
+ *
+ * @return The minimum targetSDK of all apps sharing the uid of the app
+ */
+ private static int getMinimumTargetSDK(@NonNull Context context,
+ @NonNull ApplicationInfo appInfo, @NonNull UserHandle user) {
+ PackageManager pm = context.getPackageManager();
+
+ int minimumTargetSDK = appInfo.targetSdkVersion;
+
+ String[] uidPkgs = pm.getPackagesForUid(appInfo.uid);
+ if (uidPkgs != null) {
+ for (String uidPkg : uidPkgs) {
+ if (!uidPkg.equals(appInfo.packageName)) {
+ ApplicationInfo uidPkgInfo;
+ try {
+ uidPkgInfo = pm.getApplicationInfoAsUser(uidPkg, 0, user);
+ } catch (PackageManager.NameNotFoundException e) {
+ continue;
+ }
+
+ minimumTargetSDK = min(minimumTargetSDK, uidPkgInfo.targetSdkVersion);
+ }
+ }
+ }
+
+ return minimumTargetSDK;
+ }
+
+ /**
* Get the policy for a soft restricted permission.
*
* @param context A context to use
@@ -99,12 +137,36 @@ public abstract class SoftRestrictedPermissionPolicy {
final int targetSDK;
if (appInfo != null) {
- flags = context.getPackageManager().getPermissionFlags(permission,
- appInfo.packageName, user);
+ PackageManager pm = context.getPackageManager();
+ flags = pm.getPermissionFlags(permission, appInfo.packageName, user);
applyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
isWhiteListed = (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
- hasRequestedLegacyExternalStorage = appInfo.hasRequestedLegacyExternalStorage();
- targetSDK = appInfo.targetSdkVersion;
+ targetSDK = getMinimumTargetSDK(context, appInfo, user);
+
+ boolean hasAnyRequestedLegacyExternalStorage =
+ appInfo.hasRequestedLegacyExternalStorage();
+
+ // hasRequestedLegacyExternalStorage is per package. To make sure two apps in
+ // the same shared UID do not fight over what to set, always compute the
+ // combined hasRequestedLegacyExternalStorage
+ String[] uidPkgs = pm.getPackagesForUid(appInfo.uid);
+ if (uidPkgs != null) {
+ for (String uidPkg : uidPkgs) {
+ if (!uidPkg.equals(appInfo.packageName)) {
+ ApplicationInfo uidPkgInfo;
+ try {
+ uidPkgInfo = pm.getApplicationInfoAsUser(uidPkg, 0, user);
+ } catch (PackageManager.NameNotFoundException e) {
+ continue;
+ }
+
+ hasAnyRequestedLegacyExternalStorage |=
+ uidPkgInfo.hasRequestedLegacyExternalStorage();
+ }
+ }
+ }
+
+ hasRequestedLegacyExternalStorage = hasAnyRequestedLegacyExternalStorage;
} else {
flags = 0;
applyRestriction = false;
@@ -155,7 +217,7 @@ public abstract class SoftRestrictedPermissionPolicy {
final int flags = context.getPackageManager().getPermissionFlags(permission,
appInfo.packageName, user);
isWhiteListed = (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
- targetSDK = appInfo.targetSdkVersion;
+ targetSDK = getMinimumTargetSDK(context, appInfo, user);
} else {
isWhiteListed = false;
targetSDK = 0;
diff --git a/services/core/java/com/android/server/policy/TEST_MAPPING b/services/core/java/com/android/server/policy/TEST_MAPPING
index c7e241b35e9a..17392e0a67bb 100644
--- a/services/core/java/com/android/server/policy/TEST_MAPPING
+++ b/services/core/java/com/android/server/policy/TEST_MAPPING
@@ -33,6 +33,9 @@
"options": [
{
"include-filter": "android.permission2.cts.RestrictedPermissionsTest"
+ },
+ {
+ "include-filter": "android.permission2.cts.RestrictedStoragePermissionSharedUidTest"
}
]
},
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 03cae429904f..eab5e0dd270e 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -79,6 +79,7 @@ import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
import static com.android.server.wm.WindowManagerService.logWithStack;
import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
+import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
@@ -540,6 +541,18 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
// If the app was already visible, don't reset the waitingToShow state.
if (isHidden()) {
waitingToShow = true;
+
+ // Let's reset the draw state in order to prevent the starting window to be
+ // immediately dismissed when the app still has the surface.
+ forAllWindows(w -> {
+ if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
+ w.mWinAnimator.resetDrawState();
+
+ // Force add to mResizingWindows, so that we are guaranteed to get
+ // another reportDrawn callback.
+ w.resetLastContentInsets();
+ }
+ }, true /* traverseTopToBottom */);
}
}
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index b90d60227be4..c0942c908f3b 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -936,6 +936,7 @@ class ScreenRotationAnimation {
}
}
+ t.setEarlyWakeup();
setSnapshotTransform(t, mSnapshotFinalMatrix, mExitTransformation.getAlpha());
}
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 14585c531203..19fbfedfc251 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -292,6 +292,10 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
private int getPreferredLaunchDisplay(@Nullable TaskRecord task,
@Nullable ActivityOptions options, ActivityRecord source, LaunchParams currentParams) {
+ if (!mSupervisor.mService.mSupportsMultiDisplay) {
+ return DEFAULT_DISPLAY;
+ }
+
int displayId = INVALID_DISPLAY;
final int optionLaunchId = options != null ? options.getLaunchDisplayId() : INVALID_DISPLAY;
if (optionLaunchId != INVALID_DISPLAY) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index fb57d73c9a21..436a5c729b86 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7670,10 +7670,12 @@ public class WindowManagerService extends IWindowManager.Stub
isDown = motionEvent.getAction() == MotionEvent.ACTION_DOWN;
isUp = motionEvent.getAction() == MotionEvent.ACTION_UP;
}
+ final boolean isMouseEvent = ev.getSource() == InputDevice.SOURCE_MOUSE;
// For ACTION_DOWN, syncInputTransactions before injecting input.
+ // For all mouse events, also sync before injecting.
// For ACTION_UP, sync after injecting.
- if (isDown) {
+ if (isDown || isMouseEvent) {
syncInputTransactions();
}
final boolean result =
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 43ad091b08c0..703fe4ac867b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1623,7 +1623,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|| !mRelayoutCalled
|| (atoken == null && mToken.isHidden())
|| (atoken != null && atoken.hiddenRequested)
- || isParentWindowHidden()
+ || isParentWindowGoneForLayout()
|| (mAnimatingExit && !isAnimatingLw())
|| mDestroying;
}
@@ -3795,6 +3795,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return parent != null && parent.mHidden;
}
+ private boolean isParentWindowGoneForLayout() {
+ final WindowState parent = getParentWindow();
+ return parent != null && parent.isGoneForLayoutLw();
+ }
+
void setWillReplaceWindow(boolean animate) {
for (int i = mChildren.size() - 1; i >= 0; i--) {
final WindowState c = mChildren.get(i);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 6f7af3f49b57..656af982859e 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1974,6 +1974,11 @@ public final class SystemServer {
}
traceEnd();
+ // Permission policy service
+ traceBeginAndSlog("StartPermissionPolicyService");
+ mSystemServiceManager.startService(PermissionPolicyService.class);
+ traceEnd();
+
traceBeginAndSlog("MakePackageManagerServiceReady");
mPackageManagerService.systemReady();
traceEnd();
@@ -2008,11 +2013,6 @@ public final class SystemServer {
mSystemServiceManager.startBootPhase(SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);
traceEnd();
- // Permission policy service
- traceBeginAndSlog("StartPermissionPolicyService");
- mSystemServiceManager.startService(PermissionPolicyService.class);
- traceEnd();
-
// These are needed to propagate to the runnable below.
final NetworkManagementService networkManagementF = networkManagement;
final NetworkStatsService networkStatsF = networkStats;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index f918149e6781..58614c650363 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -1225,6 +1225,22 @@ public class TaskLaunchParamsModifierTests extends ActivityTestsBase {
assertEquals(startingBounds, adjustedBounds);
}
+ @Test
+ public void testNoMultiDisplaySupports() {
+ final boolean orgValue = mService.mSupportsMultiDisplay;
+ final TestActivityDisplay display = createNewActivityDisplay(WINDOWING_MODE_FULLSCREEN);
+ mCurrent.mPreferredDisplayId = display.mDisplayId;
+
+ try {
+ mService.mSupportsMultiDisplay = false;
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+ mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(DEFAULT_DISPLAY, mResult.mPreferredDisplayId);
+ } finally {
+ mService.mSupportsMultiDisplay = orgValue;
+ }
+ }
+
private TestActivityDisplay createNewActivityDisplay(int windowingMode) {
final TestActivityDisplay display = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
display.setWindowingMode(windowingMode);
diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
index a1bea4d417f9..d4ed9234569b 100644
--- a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
@@ -21,6 +21,7 @@ import android.content.ContentResolver;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.os.RemoteException;
import android.provider.Settings;
import android.telephony.TelephonyManager;
@@ -28,7 +29,9 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import com.android.server.SystemConfig;
import java.util.ArrayList;
@@ -140,9 +143,12 @@ public final class CarrierAppUtils {
try {
for (ApplicationInfo ai : candidates) {
String packageName = ai.packageName;
- boolean hasPrivileges = telephonyManager != null &&
- telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) ==
- TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+ String[] restrictedCarrierApps = Resources.getSystem().getStringArray(
+ R.array.config_restrictedPreinstalledCarrierApps);
+ boolean hasPrivileges = telephonyManager != null
+ && telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
+ && !ArrayUtils.contains(restrictedCarrierApps, packageName);
// add hiddenUntilInstalled flag for carrier apps and associated apps
packageManager.setSystemAppHiddenUntilInstalled(packageName, true);