Merge "Using the keyguard fading away duration for the scrim" into qt-r1-dev
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index f08be49..e7cce06 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -319,6 +319,8 @@
217 [(log_from_module) = "permissioncontroller"];
PermissionAppsFragmentViewed permission_apps_fragment_viewed =
218 [(log_from_module) = "permissioncontroller"];
+ ExclusionRectStateChanged exclusion_rect_state_changed = 223;
+ BackGesture back_gesture_reported_reported = 224;
}
// Pulled events will start at field 10000.
@@ -2500,6 +2502,41 @@
optional State state = 1;
}
+message BackGesture {
+ enum BackType {
+ DEFAULT_BACK_TYPE = 0;
+ COMPLETED = 1;
+ COMPLETED_REJECTED = 2; // successful because coming from rejected area
+ INCOMPLETE_EXCLUDED = 3; // would have been successful but in the exclusion area
+ INCOMPLETE = 4;
+ }
+ optional BackType type = 1;
+
+ optional int32 y_coordinate = 2; // y coordinate for ACTION_DOWN event
+ enum WindowHorizontalLocation {
+ DEFAULT_LOCATION = 0;
+ LEFT = 1;
+ RIGHT = 2;
+ }
+ optional WindowHorizontalLocation x_location = 3;
+}
+
+message ExclusionRectStateChanged {
+ optional string component_name = 1; // if not available, simply packageName
+ optional int32 requested_height = 2; // px
+ optional int32 rejected_height = 3; // px
+
+ enum WindowHorizontalLocation {
+ DEFAULT_LOCATION = 0;
+ LEFT = 1;
+ RIGHT = 2;
+ }
+ optional WindowHorizontalLocation x_location = 4;
+ optional bool landscape = 5;
+ optional bool splitscreen = 6;
+ optional int32 duration_millis = 7;
+}
+
message LauncherUIChanged {
optional android.stats.launcher.LauncherAction action = 1;
optional android.stats.launcher.LauncherState src_state = 2;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index dc52c52..f5b0b59 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1547,7 +1547,9 @@
* had previously been frozen by {@link #onSaveInstanceState}.
*
* <p>This method is called between {@link #onStart} and
- * {@link #onPostCreate}.
+ * {@link #onPostCreate}. This method is called only when recreating
+ * an activity; the method isn't invoked if {@link #onStart} is called for
+ * any other reason.</p>
*
* @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}.
*
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 8508c2c..1725db0 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -120,17 +120,6 @@
public abstract void setHasOverlayUi(int pid, boolean hasOverlayUi);
/**
- * Sets if the given pid is currently running a remote animation, which is taken a signal for
- * determining oom adjustment and scheduling behavior.
- *
- * @param pid The pid we are setting overlay UI for.
- * @param runningRemoteAnimation True if the process is running a remote animation, false
- * otherwise.
- * @see RemoteAnimationAdapter
- */
- public abstract void setRunningRemoteAnimation(int pid, boolean runningRemoteAnimation);
-
- /**
* Called after the network policy rules are updated by
* {@link com.android.server.net.NetworkPolicyManagerService} for a specific {@param uid} and
* {@param procStateSeq}.
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 81e1eb9..af3a16c 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -870,8 +870,8 @@
protected interface ContactOptionsColumns {
/**
* The number of times a contact has been contacted.
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field is obsolete. For
- * more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.</p>
* <P>Type: INTEGER</P>
@@ -885,8 +885,8 @@
/**
* The last time a contact was contacted.
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field is obsolete. For
- * more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.</p>
* <P>Type: INTEGER</P>
@@ -1691,10 +1691,10 @@
* TIMES_CONTACTED field is incremented by 1 and the LAST_TIME_CONTACTED
* field is populated with the current system time.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this method is obsolete. For
- * more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
- * page.
+ * page.</p>
*
* @param resolver the ContentResolver to use
* @param contactId the person who was contacted
@@ -1730,8 +1730,8 @@
* Frequent contacts are no longer included in the result as of
* Android version {@link android.os.Build.VERSION_CODES#Q}.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -1745,8 +1745,8 @@
* Android version {@link android.os.Build.VERSION_CODES#Q}.
* This URI always returns an empty cursor.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -1760,8 +1760,8 @@
* various parts of the contact name. The filter argument should be passed
* as an additional path segment after this URI.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -4292,10 +4292,10 @@
* Android version {@link android.os.Build.VERSION_CODES#Q}.
* This column always contains 0.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field is obsolete.
- * For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
- * page.
+ * page.</p>
*/
@Deprecated
public static final String LAST_TIME_USED = "last_time_used";
@@ -4306,10 +4306,10 @@
* Android version {@link android.os.Build.VERSION_CODES#Q}.
* This column always contains 0.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field is obsolete.
- * For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
- * page.
+ * page.</p>
*/
@Deprecated
public static final String TIMES_USED = "times_used";
@@ -5259,8 +5259,8 @@
/**
* The content:// style URI for this table.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*
@@ -5277,8 +5277,8 @@
/**
* <p>URI used for the "enterprise caller-id".</p>
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store, this
+ * field doesn't sort results based on contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*
@@ -6079,8 +6079,8 @@
* to display names as well as phone numbers. The filter argument should be passed
* as an additional path segment after this URI.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>This field deosn't sort results based on contacts
+ * frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -6092,8 +6092,9 @@
* same columns. This URI requires {@link ContactsContract#DIRECTORY_PARAM_KEY} in
* parameters, otherwise it will throw IllegalArgumentException.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -6360,8 +6361,9 @@
* as an additional path segment after this URI.
* </p>
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer sorts
- * results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.</p>
*
@@ -6383,8 +6385,9 @@
* same columns. This URI requires {@link ContactsContract#DIRECTORY_PARAM_KEY} in
* parameters, otherwise it will throw IllegalArgumentException.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -7602,8 +7605,8 @@
* <p>Similar to {@link Phone#CONTENT_FILTER_URI}, but allows users to filter callable
* data.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>This field no longer sorts results based on
+ * contacts frequency. For more information, see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -7615,8 +7618,9 @@
* callable data. This URI requires {@link ContactsContract#DIRECTORY_PARAM_KEY} in
* parameters, otherwise it will throw IllegalArgumentException.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.</p>
*/
@@ -7646,8 +7650,9 @@
* <p>The content:// style URI for these data items, which allows for a query parameter
* to be appended onto the end to filter for data items matching the query.
*
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this field no longer
- * sorts results based on contacts frequency. For more information, see the
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field doesn't sort results based on contacts frequency. For more information,
+ * see the
* <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
* page.
*/
@@ -8298,15 +8303,14 @@
}
/**
- * <p class="caution"><b>Caution: </b>As of January 7, 2019, this class is obsolete. For
- * more information, see the
- * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
- * page.
- * </p>
* <p>
* API allowing applications to send usage information for each {@link Data} row to the
* Contacts Provider. Applications can also clear all usage information.
* </p>
+ * <p class="caution"><b>Caution: </b>If you publish your app to the Google Play Store,
+ * this field is obsolete, regardless of Android version. For more information, see the
+ * <a href="/guide/topics/providers/contacts-provider#ObsoleteData">Contacts Provider</a>
+ * page.</p>
* <p>
* With the feedback, Contacts Provider may return more contextually appropriate results for
* Data listing, typically supplied with
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 1fd212d..ea50ae8 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -338,6 +338,20 @@
"system_gestures_excluded_by_pre_q_sticky_immersive";
/**
+ * The minimum duration between gesture exclusion logging for a given window in
+ * milliseconds.
+ *
+ * Events that happen in-between will be silently dropped.
+ *
+ * A non-positive value disables logging.
+ *
+ * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
+ * @hide
+ */
+ String KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS =
+ "system_gesture_exclusion_log_debounce_millis";
+
+ /**
* Key for controlling which packages are explicitly blocked from running at refresh rates
* higher than 60hz.
*
diff --git a/core/java/android/view/ISystemGestureExclusionListener.aidl b/core/java/android/view/ISystemGestureExclusionListener.aidl
index a032625..9c2f9a6 100644
--- a/core/java/android/view/ISystemGestureExclusionListener.aidl
+++ b/core/java/android/view/ISystemGestureExclusionListener.aidl
@@ -28,7 +28,14 @@
* Called when the system gesture exclusion for the given display changed.
* @param displayId the display whose system gesture exclusion changed
* @param systemGestureExclusion a {@code Region} where the app would like priority over the
- * system gestures, in display coordinates.
+ * system gestures, in display coordinates. Certain restrictions
+ * might be applied such that apps don't get all the exclusions
+ * they request.
+ * @param systemGestureExclusionUnrestricted a {@code Region} where the app would like priority
+ * over the system gestures, in display coordinates, without
+ * any restrictions applied. Null if no restrictions have been
+ * applied.
*/
- void onSystemGestureExclusionChanged(int displayId, in Region systemGestureExclusion);
+ void onSystemGestureExclusionChanged(int displayId, in Region systemGestureExclusion,
+ in Region systemGestureExclusionUnrestricted);
}
\ No newline at end of file
diff --git a/core/java/android/view/RemoteAnimationAdapter.java b/core/java/android/view/RemoteAnimationAdapter.java
index bc2fe54..c686440 100644
--- a/core/java/android/view/RemoteAnimationAdapter.java
+++ b/core/java/android/view/RemoteAnimationAdapter.java
@@ -55,6 +55,7 @@
/** @see #getCallingPid */
private int mCallingPid;
+ private int mCallingUid;
/**
* @param runner The interface that gets notified when we actually need to start the animation.
@@ -103,10 +104,11 @@
}
/**
- * To be called by system_server to keep track which pid is running this animation.
+ * To be called by system_server to keep track which pid and uid is running this animation.
*/
- public void setCallingPid(int pid) {
+ public void setCallingPidUid(int pid, int uid) {
mCallingPid = pid;
+ mCallingUid = uid;
}
/**
@@ -116,6 +118,13 @@
return mCallingPid;
}
+ /**
+ * @return The uid of the process running the animation.
+ */
+ public int getCallingUid() {
+ return mCallingUid;
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/view/RemoteAnimationDefinition.java b/core/java/android/view/RemoteAnimationDefinition.java
index 884cae4..da599ef 100644
--- a/core/java/android/view/RemoteAnimationDefinition.java
+++ b/core/java/android/view/RemoteAnimationDefinition.java
@@ -118,9 +118,9 @@
* To be called by system_server to keep track which pid is running the remote animations inside
* this definition.
*/
- public void setCallingPid(int pid) {
+ public void setCallingPidUid(int pid, int uid) {
for (int i = mTransitionAnimationMap.size() - 1; i >= 0; i--) {
- mTransitionAnimationMap.valueAt(i).adapter.setCallingPid(pid);
+ mTransitionAnimationMap.valueAt(i).adapter.setCallingPidUid(pid, uid);
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b2449d5..4e86e60 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -11085,6 +11085,13 @@
*
* <p>Do not modify the provided list after this method is called.</p>
*
+ * <p>Note: the system will put a limit of <code>200dp</code> on the vertical extent of the
+ * exclusions it takes into account. The limit does not apply while the navigation
+ * bar is {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY stickily} hidden, nor to the
+ * {@link android.inputmethodservice.InputMethodService input method} and
+ * {@link Intent#CATEGORY_HOME home activity}.
+ * </p>
+ *
* @param rects A list of precision gesture regions that this view needs to function correctly
*/
public void setSystemGestureExclusionRects(@NonNull List<Rect> rects) {
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 9340b71..bcc6a55 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -35,6 +35,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
+import android.content.Intent;
import android.graphics.Insets;
import android.graphics.Rect;
import android.util.SparseArray;
@@ -644,6 +645,14 @@
* {@link View#setSystemGestureExclusionRects} outside of the
* {@link #getMandatorySystemGestureInsets() mandatory system gesture insets}.
*
+ * <p>Note: the system will put a limit of <code>200dp</code> on the vertical extent of the
+ * exclusions it takes into account. The limit does not apply while the navigation
+ * bar is {@link View#SYSTEM_UI_FLAG_IMMERSIVE_STICKY stickily} hidden, nor to the
+ * {@link android.inputmethodservice.InputMethodService input method} and
+ * {@link Intent#CATEGORY_HOME home activity}.
+ * </p>
+ *
+ *
* <p>Simple taps are guaranteed to reach the window even within the system gesture insets,
* as long as they are outside the {@link #getTappableElementInsets() system window insets}.
*
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 50bb688..1db9123 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -91,6 +91,7 @@
@UnsupportedAppUsage
private float mDisabledAlpha;
+ private int mThumbExclusionMaxSize;
private int mScaledTouchSlop;
private float mTouchDownX;
@UnsupportedAppUsage
@@ -170,6 +171,8 @@
applyTickMarkTint();
mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ mThumbExclusionMaxSize = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.seekbar_thumb_exclusion_max_size);
}
/**
@@ -762,12 +765,30 @@
}
mGestureExclusionRects.clear();
thumb.copyBounds(mThumbRect);
+ mThumbRect.offset(mPaddingLeft - mThumbOffset, mPaddingTop);
+ growRectTo(mThumbRect, Math.min(getHeight(), mThumbExclusionMaxSize));
mGestureExclusionRects.add(mThumbRect);
mGestureExclusionRects.addAll(mUserGestureExclusionRects);
super.setSystemGestureExclusionRects(mGestureExclusionRects);
}
/**
+ * Grows {@code r} from its center such that each dimension is at least {@code minimumSize}.
+ */
+ private void growRectTo(Rect r, int minimumSize) {
+ int dy = (minimumSize - r.height()) / 2;
+ if (dy > 0) {
+ r.top -= dy;
+ r.bottom += dy;
+ }
+ int dx = (minimumSize - r.width()) / 2;
+ if (dx > 0) {
+ r.left -= dx;
+ r.right += dx;
+ }
+ }
+
+ /**
* @hide
*/
@Override
diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java
index e7d240a..9bb4501 100644
--- a/core/java/com/android/internal/widget/MediaNotificationView.java
+++ b/core/java/com/android/internal/widget/MediaNotificationView.java
@@ -26,6 +26,8 @@
import android.widget.ImageView;
import android.widget.RemoteViews;
+import java.util.ArrayList;
+
/**
* A TextView that can float around an image on the end.
*
@@ -42,6 +44,7 @@
private View mMainColumn;
private View mMediaContent;
private int mImagePushIn;
+ private ArrayList<VisibilityChangeListener> mListeners;
public MediaNotificationView(Context context) {
this(context, null);
@@ -168,4 +171,50 @@
mMainColumn = findViewById(com.android.internal.R.id.notification_main_column);
mMediaContent = findViewById(com.android.internal.R.id.notification_media_content);
}
+
+ @Override
+ public void onVisibilityAggregated(boolean isVisible) {
+ super.onVisibilityAggregated(isVisible);
+ if (mListeners != null) {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onAggregatedVisibilityChanged(isVisible);
+ }
+ }
+ }
+
+ /**
+ * Add a listener to receive updates on the visibility of this view
+ *
+ * @param listener The listener to add.
+ */
+ public void addVisibilityListener(VisibilityChangeListener listener) {
+ if (mListeners == null) {
+ mListeners = new ArrayList<>();
+ }
+ if (!mListeners.contains(listener)) {
+ mListeners.add(listener);
+ }
+ }
+
+ /**
+ * Remove the specified listener
+ *
+ * @param listener The listener to remove.
+ */
+ public void removeVisibilityListener(VisibilityChangeListener listener) {
+ if (mListeners != null) {
+ mListeners.remove(listener);
+ }
+ }
+
+ /**
+ * Interface for receiving updates when the view's visibility changes
+ */
+ public interface VisibilityChangeListener {
+ /**
+ * Method called when the visibility of this view has changed
+ * @param isVisible true if the view is now visible
+ */
+ void onAggregatedVisibilityChanged(boolean isVisible);
+ }
}
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 9084f62..d48034b 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -53,6 +53,12 @@
// to plot alongside the default one. Useful for testing and comparison purposes.
private static final String ALT_STRATEGY_PROPERY_KEY = "debug.velocitytracker.alt";
+ /**
+ * If set to a positive value between 1-255, shows an overlay with the approved (red) and
+ * rejected (blue) exclusions.
+ */
+ private static final String GESTURE_EXCLUSION_PROP = "debug.pointerlocation.showexclusion";
+
public static class PointerState {
// Trace of previous points.
private float[] mTraceX = new float[32];
@@ -138,8 +144,10 @@
private final PointerCoords mTempCoords = new PointerCoords();
private final Region mSystemGestureExclusion = new Region();
+ private final Region mSystemGestureExclusionRejected = new Region();
private final Path mSystemGestureExclusionPath = new Path();
private final Paint mSystemGestureExclusionPaint;
+ private final Paint mSystemGestureExclusionRejectedPaint;
private final VelocityTracker mVelocity;
private final VelocityTracker mAltVelocity;
@@ -190,6 +198,10 @@
mSystemGestureExclusionPaint.setARGB(25, 255, 0, 0);
mSystemGestureExclusionPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ mSystemGestureExclusionRejectedPaint = new Paint();
+ mSystemGestureExclusionRejectedPaint.setARGB(25, 0, 0, 255);
+ mSystemGestureExclusionRejectedPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+
PointerState ps = new PointerState();
mPointers.add(ps);
mActivePointerId = 0;
@@ -263,6 +275,12 @@
canvas.drawPath(mSystemGestureExclusionPath, mSystemGestureExclusionPaint);
}
+ if (!mSystemGestureExclusionRejected.isEmpty()) {
+ mSystemGestureExclusionPath.reset();
+ mSystemGestureExclusionRejected.getBoundaryPath(mSystemGestureExclusionPath);
+ canvas.drawPath(mSystemGestureExclusionPath, mSystemGestureExclusionRejectedPaint);
+ }
+
// Labels
if (mActivePointerId >= 0) {
final PointerState ps = mPointers.get(mActivePointerId);
@@ -754,6 +772,9 @@
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
+ final int alpha = systemGestureExclusionOpacity();
+ mSystemGestureExclusionPaint.setAlpha(alpha);
+ mSystemGestureExclusionRejectedPaint.setAlpha(alpha);
} else {
mSystemGestureExclusion.setEmpty();
}
@@ -805,7 +826,12 @@
}
private static boolean shouldShowSystemGestureExclusion() {
- return SystemProperties.getBoolean("debug.pointerlocation.showexclusion", false);
+ return systemGestureExclusionOpacity() > 0;
+ }
+
+ private static int systemGestureExclusionOpacity() {
+ int x = SystemProperties.getInt(GESTURE_EXCLUSION_PROP, 0);
+ return x >= 0 && x <= 255 ? x : 0;
}
// HACK
@@ -928,12 +954,19 @@
private ISystemGestureExclusionListener mSystemGestureExclusionListener =
new ISystemGestureExclusionListener.Stub() {
@Override
- public void onSystemGestureExclusionChanged(int displayId, Region systemGestureExclusion) {
+ public void onSystemGestureExclusionChanged(int displayId, Region systemGestureExclusion,
+ Region systemGestureExclusionUnrestricted) {
Region exclusion = Region.obtain(systemGestureExclusion);
+ Region rejected = Region.obtain();
+ if (systemGestureExclusionUnrestricted != null) {
+ rejected.set(systemGestureExclusionUnrestricted);
+ rejected.op(exclusion, Region.Op.DIFFERENCE);
+ }
Handler handler = getHandler();
if (handler != null) {
handler.post(() -> {
mSystemGestureExclusion.set(exclusion);
+ mSystemGestureExclusionRejected.set(rejected);
exclusion.recycle();
invalidate();
});
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index e50f32a..c53af2b 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -95,8 +95,7 @@
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"ভইচমেইলৰ বাৰ্তাসমূহ"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"ৱাই-ফাই কলিং"</string>
<string name="notification_channel_sim" msgid="4052095493875188564">"ছিমৰ স্থিতি"</string>
- <!-- no translation found for notification_channel_sim_high_prio (1787666807724243207) -->
- <skip />
+ <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"উচ্চ অগ্ৰাধিকাৰযুক্ত ছিমৰ স্থিতি"</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"নেটৱৰ্ক পীয়েৰে TTY ম\'ড FULLলৈ সলনি কৰিবলৈ অনুৰোধ কৰিছে"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"নেটৱৰ্ক পীয়েৰে TTY ম\'ড HCOলৈ সলনি কৰিবলৈ অনুৰোধ কৰিছে"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"নেটৱৰ্ক পীয়েৰে TTY ম\'ড VCO লৈ সলনি কৰিবলৈ অনুৰোধ কৰিছে"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index b7f4d67..3d834d5 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -95,8 +95,7 @@
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"ভয়েসমেল মেসেজ"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"ওয়াই-ফাই কলিং"</string>
<string name="notification_channel_sim" msgid="4052095493875188564">"সিম কার্ডের স্টাটাস"</string>
- <!-- no translation found for notification_channel_sim_high_prio (1787666807724243207) -->
- <skip />
+ <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"উচ্চ প্রায়রিটি সিম স্ট্যাটাস"</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"পির TTY মোড FULL অনুরোধ করেছে"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"পির TTY মোড HCO অনুরোধ করেছে"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"পির TTY মোড VCO অনুরোধ করেছে"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 46d17d3..f4b341c 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -573,9 +573,9 @@
<string name="face_acquired_recalibrate" msgid="8077949502893707539">"Torna a registrar la teva cara."</string>
<string name="face_acquired_too_different" msgid="7663983770123789694">"Ja no es reconeix la teva cara. Torna-ho a provar."</string>
<string name="face_acquired_too_similar" msgid="1508776858407646460">"És massa semblant; canvia de postura."</string>
- <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"Inclina el cap una mica menys."</string>
- <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Inclina el cap una mica menys."</string>
- <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"No inclinis tant el cap."</string>
+ <string name="face_acquired_pan_too_extreme" msgid="4581629343077288178">"No giris tant el cap."</string>
+ <string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"No inclinis tant el cap."</string>
+ <string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"No giris tant el cap."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Suprimeix qualsevol cosa que amagui la teva cara."</string>
<string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Neteja la part superior de la pantalla, inclosa la barra negra"</string>
<string-array name="face_acquired_vendor">
@@ -1483,7 +1483,7 @@
<string name="back_button_label" msgid="2300470004503343439">"Enrere"</string>
<string name="next_button_label" msgid="1080555104677992408">"Següent"</string>
<string name="skip_button_label" msgid="1275362299471631819">"Omet"</string>
- <string name="no_matches" msgid="8129421908915840737">"Cap coincidència"</string>
+ <string name="no_matches" msgid="8129421908915840737">"No s\'ha trobat cap coincidència"</string>
<string name="find_on_page" msgid="1946799233822820384">"Troba-ho a la pàgina"</string>
<plurals name="matches_found" formatted="false" msgid="1210884353962081884">
<item quantity="other"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 7b1d8a5..effa902 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -299,8 +299,8 @@
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"音声の録音"</string>
<string name="permgrouprequest_microphone" msgid="9167492350681916038">"音声の録音を「<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>」に許可しますか?"</string>
<string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"身体活動"</string>
- <string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"運動データにアクセス"</string>
- <string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"運動データへのアクセスを「<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>」に許可しますか?"</string>
+ <string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"身体活動にアクセス"</string>
+ <string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"身体活動へのアクセスを「<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>」に許可しますか?"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"カメラ"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"写真と動画の撮影"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"写真と動画の撮影を「<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>」に許可しますか?"</string>
@@ -429,8 +429,8 @@
<string name="permdesc_recordAudio" msgid="4245930455135321433">"このアプリは、いつでもマイクを使用して録音できます。"</string>
<string name="permlab_sim_communication" msgid="2935852302216852065">"SIMへのコマンド送信"</string>
<string name="permdesc_sim_communication" msgid="5725159654279639498">"SIMにコマンドを送信することをアプリに許可します。この許可は非常に危険です。"</string>
- <string name="permlab_activityRecognition" msgid="3634590230567608356">"運動の認識"</string>
- <string name="permdesc_activityRecognition" msgid="3143453925156552894">"このアプリで運動が認識されるようにします。"</string>
+ <string name="permlab_activityRecognition" msgid="3634590230567608356">"身体活動の認識"</string>
+ <string name="permdesc_activityRecognition" msgid="3143453925156552894">"このアプリで身体活動が認識されるようにします。"</string>
<string name="permlab_camera" msgid="3616391919559751192">"写真と動画の撮影"</string>
<string name="permdesc_camera" msgid="5392231870049240670">"このアプリは、いつでもカメラを使用して写真や動画を撮影できます。"</string>
<string name="permlab_vibrate" msgid="7696427026057705834">"バイブレーションの制御"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 0a7f6a0..8e5ea6a 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -95,8 +95,7 @@
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"ಧ್ವನಿಮೇಲ್ ಸಂದೇಶಗಳು"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"ವೈ-ಫೈ ಕರೆ ಮಾಡುವಿಕೆ"</string>
<string name="notification_channel_sim" msgid="4052095493875188564">"ಸಿಮ್ ಸ್ಥಿತಿ"</string>
- <!-- no translation found for notification_channel_sim_high_prio (1787666807724243207) -->
- <skip />
+ <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"ಹೆಚ್ಚಿನ ಆದ್ಯತೆಯ ಸಿಮ್ ಸ್ಥಿತಿ"</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"ಪೀರ್ ವಿನಂತಿಸಿಕೊಂಡ TTY ಮೋಡ್ ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"ಪೀರ್ ವಿನಂತಿಸಿಕೊಂಡ TTY ಮೋಡ್ HCO"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"ಪೀರ್ ವಿನಂತಿಸಿಕೊಂಡ TTY ಮೋಡ್ VCO"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 0026ddb..9ad8b13 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -95,8 +95,7 @@
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"വോയ്സ്മെയിൽ സന്ദേശങ്ങൾ"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"വൈഫൈ കോളിംഗ്"</string>
<string name="notification_channel_sim" msgid="4052095493875188564">"സിം നില"</string>
- <!-- no translation found for notification_channel_sim_high_prio (1787666807724243207) -->
- <skip />
+ <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"ഉയർന്ന മുൻഗണനയുള്ള സിം നില"</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"പിയർ അഭ്യർത്ഥിച്ച TTY മോഡ് \'ഫുൾ\'"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"പിയർ അഭ്യർത്ഥിച്ച TTY മോഡ് HCO"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"പിയർ അഭ്യർത്ഥിച്ച TTY മോഡ് VCO"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 084b950..faafeb7 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -95,8 +95,7 @@
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"व्हॉइसमेल मेसेज"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"वाय-फाय कॉलिंग"</string>
<string name="notification_channel_sim" msgid="4052095493875188564">"सिम स्थिती"</string>
- <!-- no translation found for notification_channel_sim_high_prio (1787666807724243207) -->
- <skip />
+ <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"उच्च प्राधान्य सिम स्थिती"</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"समवयस्क व्यक्तीने TTY मोड पूर्ण ची विनंती केली"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"समवयस्क व्यक्तीने TTY मोड HCO ची विनंती केली"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"समवयस्क व्यक्तीने TTY मोड VCO ची विनंती केली"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index ec80088..ad5aaca 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -95,7 +95,7 @@
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"အသံမေးလ် မက်ဆေ့ဂျ်များ"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"Wi-Fi ခေါ်ဆိုမှု"</string>
<string name="notification_channel_sim" msgid="4052095493875188564">"ဆင်းမ်ကဒ် အခြေအနေ"</string>
- <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"အရေးကြီး ဆင်းမ်ကတ်အခြေအနေ"</string>
+ <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"အထူးဦးစားပေး ဆင်းမ်ကတ်အခြေအနေ"</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"အခြားစက်မှ TTY မုဒ် FULL ပြုရန် တောင်းဆို၏"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"အခြားစက်မှ TTY မုဒ် HCO ပြုရန် တောင်းဆို၏"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"TTY မုဒ် VCO ပြုရန် အခြားစက်မှ တောင်းဆို၏"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index e554145..4739232 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -95,8 +95,7 @@
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"भ्वाइस मेल सन्देशहरू"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"Wi-Fi कल"</string>
<string name="notification_channel_sim" msgid="4052095493875188564">"SIM को स्थिति"</string>
- <!-- no translation found for notification_channel_sim_high_prio (1787666807724243207) -->
- <skip />
+ <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"उच्च प्राथमिकता रहेको SIM को स्थिति"</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"सहकर्मी अनुरोध गरियो। TTY मोड पूर्ण"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"सहकर्मी अनुरोध गरियो। TTY मोड HCO"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"सहकर्मी अनुरोध गरियो। TTY मोड VCO"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index e2d3176..ce40db3 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -95,8 +95,7 @@
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"ଭଏସମେଲ୍ ମେସେଜ୍"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"ୱାଇ-ଫାଇ କଲିଙ୍ଗ"</string>
<string name="notification_channel_sim" msgid="4052095493875188564">"SIM ଷ୍ଟାଟସ୍"</string>
- <!-- no translation found for notification_channel_sim_high_prio (1787666807724243207) -->
- <skip />
+ <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"ଉଚ୍ଚ ପ୍ରାଥମିକତା SIM ସ୍ଥିତି"</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"ପୀଆର୍ ଅନୁରୋଧ କରିଥିବା TTY ମୋଡ୍ FULL ଅଟେ"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"ପୀଅର୍ ଅନୁରୋଧ କରିଥିବା TTY ମୋଡ୍ HCO ଅଟେ"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"ପୀଅର୍ ଅନୁରୋଧ କରିଥିବା TTY ମୋଡ୍ VCO ଅଟେ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 370db7d7..591ba0a 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -95,8 +95,7 @@
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"ਵੌਇਸਮੇਲ ਸੁਨੇਹੇ"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"ਵਾਈ-ਫਾਈ ਕਾਲਿੰਗ"</string>
<string name="notification_channel_sim" msgid="4052095493875188564">"ਸਿਮ ਅਵਸਥਾ"</string>
- <!-- no translation found for notification_channel_sim_high_prio (1787666807724243207) -->
- <skip />
+ <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"ਉੱਚ ਤਰਜੀਹੀ ਸਿਮ ਸਥਿਤੀ"</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"ਪੀਅਰ ਨੇ TTY Mode FULL ਦੀ ਬੇਨਤੀ ਕੀਤੀ"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"ਪੀਅਰ ਨੇ TTY Mode HCO ਦੀ ਬੇਨਤੀ ਕੀਤੀ"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"ਪੀਅਰ ਨੇ TTY Mode VCO ਦੀ ਬੇਨਤੀ ਕੀਤੀ"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 50dae75..245864c 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -96,7 +96,7 @@
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"Mesaje din mesageria vocală"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"Apelare prin Wi-Fi"</string>
<string name="notification_channel_sim" msgid="4052095493875188564">"Starea cardului SIM"</string>
- <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"Stare SIM cu prioritate ridicată"</string>
+ <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"Notificări de la SIM cu prioritate ridicată"</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"Cealaltă persoană a solicitat modul TTY cu setarea COMPLET"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"Cealaltă persoană a solicitat modul TTY cu setarea HCO"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"Cealaltă persoană a solicitat modul TTY cu setarea VCO"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 8adc187..cded9f1 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -364,7 +364,7 @@
<string name="permlab_enableCarMode" msgid="5684504058192921098">"Wezesha mtindo wa gari"</string>
<string name="permdesc_enableCarMode" msgid="4853187425751419467">"Inaruhusu programu kuwawezesha mtindo wa gari."</string>
<string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"funga programu zingine"</string>
- <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Inaruhusu programu kukamilisha michakato ya usuli ya programu nyingine. Hii inaweza kusababisha programu nyingine kukoma kufanyakazi."</string>
+ <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Huruhusu programu kukamilisha michakato ya chinichini ya programu nyingine. Hii inaweza kusababisha programu nyingine kuacha kufanya kazi."</string>
<string name="permlab_systemAlertWindow" msgid="7238805243128138690">"Programu hii inaweza kuonekana juu ya programu zingine"</string>
<string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"Programu hii inaweza kuonekana juu ya programu zingine au sehemu zingine za skrini. Hii huenda ikaathiri matumizi ya kawaida ya programu na kubadilisha jinsi ambavyo programu zingine zinavyoonekana."</string>
<string name="permlab_runInBackground" msgid="7365290743781858803">"tumia chini chini"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 574e3cd..776d39e 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -95,8 +95,7 @@
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"వాయిస్ మెయిల్ సందేశాలు"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"Wi-Fi కాలింగ్"</string>
<string name="notification_channel_sim" msgid="4052095493875188564">"SIM స్థితి"</string>
- <!-- no translation found for notification_channel_sim_high_prio (1787666807724243207) -->
- <skip />
+ <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"అధిక ప్రాధాన్యత గల SIM స్థితి"</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"అవతలి వారు FULL TTY మోడ్ని అభ్యర్థించారు"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"అవతలి వారు HCO TTY మోడ్ని అభ్యర్థించారు"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"అవతలి వారు VCO TTY మోడ్ని అభ్యర్థించారు"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 37ff895..13c8929 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -97,7 +97,7 @@
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"Повідомлення голосової пошти"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"Дзвінки через Wi-Fi"</string>
<string name="notification_channel_sim" msgid="4052095493875188564">"Статус SIM-карти"</string>
- <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"Статус високопріоритетних сповіщень для SIM-карти"</string>
+ <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"Високопріоритетні сповіщення із SIM-карти"</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"Пристрій змінив режим TTY на FULL"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"Пристрій змінив режим TTY на HCO"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"Пристрій змінив режим TTY на VCO"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 70072d5..dba7f8f 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -95,8 +95,7 @@
<string name="notification_channel_voice_mail" msgid="3954099424160511919">"صوتی میل پیغامات"</string>
<string name="notification_channel_wfc" msgid="2130802501654254801">"Wi-Fi کالنگ"</string>
<string name="notification_channel_sim" msgid="4052095493875188564">"SIM کا اسٹیٹس"</string>
- <!-- no translation found for notification_channel_sim_high_prio (1787666807724243207) -->
- <skip />
+ <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"اعلی ترجیحی SIM کی صورتحال"</string>
<string name="peerTtyModeFull" msgid="6165351790010341421">"ہمسر نے TTY وضع مکمل کی درخواست کی"</string>
<string name="peerTtyModeHco" msgid="5728602160669216784">"ہمسر نے TTY وضع HCO کی درخواست کی"</string>
<string name="peerTtyModeVco" msgid="1742404978686538049">"ہمسر نے TTY وضع VCO کی درخواست کی"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4eee1db..df87981 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4241,6 +4241,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>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 6653879..609659b 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -748,6 +748,8 @@
<!-- Line spacing modifier for the message field of the harmful app dialog -->
<item name="harmful_app_message_line_spacing_modifier" type="dimen">1.22</item>
+ <dimen name="seekbar_thumb_exclusion_max_size">48dp</dimen>
+
<!-- chooser (sharesheet) spacing -->
<dimen name="chooser_corner_radius">8dp</dimen>
<dimen name="chooser_row_text_option_translate">25dp</dimen>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d275a37..92c5d2c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3817,6 +3817,7 @@
<java-symbol type="color" name="chooser_gradient_highlight" />
<java-symbol type="drawable" name="chooser_direct_share_label_placeholder" />
<java-symbol type="dimen" name="chooser_direct_share_label_placeholder_max_width" />
+ <java-symbol type="dimen" name="seekbar_thumb_exclusion_max_size" />
<java-symbol type="layout" name="chooser_az_label_row" />
<java-symbol type="string" name="chooser_all_apps_button_label" />
<java-symbol type="anim" name="resolver_launch_anim" />
@@ -3826,6 +3827,7 @@
<java-symbol type="string" name="config_defaultSupervisionProfileOwnerComponent" />
<java-symbol type="bool" name="config_inflateSignalStrength" />
+ <java-symbol type="array" name="config_restrictedPreinstalledCarrierApps" />
<java-symbol type="array" name="config_highRefreshRateBlacklist" />
diff --git a/core/tests/coretests/src/android/widget/AbsSeekBarTest.java b/core/tests/coretests/src/android/widget/AbsSeekBarTest.java
new file mode 100644
index 0000000..aec6096
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/AbsSeekBarTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import static android.view.View.MeasureSpec.EXACTLY;
+import static android.view.View.MeasureSpec.makeMeasureSpec;
+
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.RectShape;
+import android.platform.test.annotations.Presubmit;
+import android.view.View;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class AbsSeekBarTest {
+
+ private Context mContext;
+ private AbsSeekBar mBar;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ mBar = new SeekBar(mContext);
+ }
+
+ @Test
+ public void testExclusionForThumb_limitedTo48dp() {
+ mBar.setPadding(10, 10, 10, 10);
+ mBar.setThumb(newThumb(dpToPx(20)));
+ mBar.setMin(0);
+ mBar.setMax(100);
+ mBar.setProgress(50);
+ measureAndLayout(dpToPx(200), dpToPx(100));
+ List<Rect> exclusions = mBar.getSystemGestureExclusionRects();
+
+ assertEquals("exclusions should be size 1, but was " + exclusions, 1, exclusions.size());
+ assertEquals("exclusion should be centered on thumb",
+ center(mBar), center(exclusions.get(0)));
+ assertEquals("exclusion should be 48dp high", dpToPx(48), exclusions.get(0).height());
+ assertEquals("exclusion should be 48dp wide", dpToPx(48), exclusions.get(0).width());
+ }
+
+ @Test
+ public void testExclusionForThumb_limitedToHeight() {
+ mBar.setPadding(10, 10, 10, 10);
+ mBar.setThumb(newThumb(dpToPx(20)));
+ mBar.setMin(0);
+ mBar.setMax(100);
+ mBar.setProgress(50);
+ measureAndLayout(dpToPx(200), dpToPx(32));
+ List<Rect> exclusions = mBar.getSystemGestureExclusionRects();
+
+ assertEquals("exclusions should be size 1, but was " + exclusions, 1, exclusions.size());
+ assertEquals("exclusion should be centered on thumb",
+ center(mBar), center(exclusions.get(0)));
+ assertEquals("exclusion should be 32dp high", dpToPx(32), exclusions.get(0).height());
+ assertEquals("exclusion should be 32dp wide", dpToPx(32), exclusions.get(0).width());
+ }
+
+ @Test
+ public void testExclusionForThumb_passesThroughUserExclusions() {
+ mBar.setSystemGestureExclusionRects(Arrays.asList(new Rect(1, 2, 3, 4)));
+
+ mBar.setPadding(10, 10, 10, 10);
+ mBar.setThumb(newThumb(dpToPx(20)));
+ mBar.setMin(0);
+ mBar.setMax(100);
+ mBar.setProgress(50);
+ measureAndLayout(dpToPx(200), dpToPx(32));
+
+ assertThat(mBar.getSystemGestureExclusionRects(), hasItem(new Rect(1, 2, 3, 4)));
+ assertThat(mBar.getSystemGestureExclusionRects(), hasSize(2));
+
+ mBar.setSystemGestureExclusionRects(Arrays.asList(new Rect(3, 4, 5, 6)));
+ assertThat(mBar.getSystemGestureExclusionRects(), hasItem(new Rect(3, 4, 5, 6)));
+ assertThat(mBar.getSystemGestureExclusionRects(), hasSize(2));
+ }
+
+ private Point center(Rect rect) {
+ return new Point(rect.centerX(), rect.centerY());
+ }
+
+ private Point center(View view) {
+ return center(new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()));
+ }
+
+ private ShapeDrawable newThumb(int size) {
+ final ShapeDrawable thumb = new ShapeDrawable(new RectShape());
+ thumb.setIntrinsicWidth(size);
+ thumb.setIntrinsicHeight(size);
+ return thumb;
+ }
+
+ private void measureAndLayout(int wPx, int hPx) {
+ mBar.measure(makeMeasureSpec(wPx, EXACTLY), makeMeasureSpec(hPx, EXACTLY));
+ mBar.layout(0, 0, wPx, hPx);
+ }
+
+ private int dpToPx(int dp) {
+ return (int) (mContext.getResources().getDisplayMetrics().density * dp);
+ }
+}
diff --git a/packages/MtpDocumentsProvider/res/values-hi/strings.xml b/packages/MtpDocumentsProvider/res/values-hi/strings.xml
index bbd0ae7..e469fc0 100644
--- a/packages/MtpDocumentsProvider/res/values-hi/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values-hi/strings.xml
@@ -19,7 +19,7 @@
<string name="app_label" msgid="6271216747302322594">"MTP होस्ट"</string>
<string name="downloads_app_label" msgid="7120690641874849726">"डाउनलोड"</string>
<string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
- <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> से फ़ाइलें एक्सेस कर रहा है"</string>
+ <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> से फ़ाइलें ऐक्सेस कर रहा है"</string>
<string name="error_busy_device" msgid="3997316850357386589">"दूसरा डिवाइस व्यस्त है. आप उसके उपलब्ध हो जाने तक फ़ाइलें ट्रांसफ़र नहीं कर सकते."</string>
<string name="error_locked_device" msgid="7557872102188356147">"कोई फ़ाइल नहीं मिली. हो सकता है कि दूसरा डिवाइस लॉक हो. अगर ऐसा है, तो उसे अनलॉक करें और दोबारा कोशिश करें."</string>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml
index 7f39a19..d44bfbc 100644
--- a/packages/SystemUI/res-keyguard/values-de/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-de/strings.xml
@@ -152,6 +152,6 @@
<item quantity="one">Die SIM-Karte ist jetzt deaktiviert. Gib den PUK-Code ein, um fortzufahren. Du hast noch <xliff:g id="_NUMBER_0">%d</xliff:g> Versuch, bevor die SIM-Karte endgültig gesperrt wird. Weitere Informationen erhältst du von deinem Mobilfunkanbieter.</item>
</plurals>
<string name="clock_title_default" msgid="6645600990069154049">"Standard"</string>
- <string name="clock_title_bubble" msgid="1286365278681892114">"Blase"</string>
+ <string name="clock_title_bubble" msgid="1286365278681892114">"Bubble"</string>
<string name="clock_title_analog" msgid="4047401488577315053">"Analog"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 408254f..9b3974b 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -656,7 +656,7 @@
<string name="notification_silence_title" msgid="5763240612242137433">"Lautlos"</string>
<string name="notification_alert_title" msgid="8031196611815490340">"Benachrichtigen"</string>
<string name="notification_channel_summary_low" msgid="3387466082089715555">"Benachrichtigungen werden ohne Ton oder Vibration angekündigt, um deine Konzentration nicht zu stören."</string>
- <string name="notification_channel_summary_default" msgid="5994062840431965586">"Benachrichtigungen werden mit einem Ton oder einer Vibration angekündigt, um dich auf sie aufmerksam zu machen."</string>
+ <string name="notification_channel_summary_default" msgid="5994062840431965586">"Benachrichtigungen werden mit einem Ton oder einer Vibration angekündigt."</string>
<string name="notification_unblockable_desc" msgid="4556908766584964102">"Diese Benachrichtigungen können nicht geändert werden."</string>
<string name="notification_multichannel_desc" msgid="4695920306092240550">"Die Benachrichtigungsgruppe kann hier nicht konfiguriert werden"</string>
<string name="notification_delegate_header" msgid="2857691673814814270">"Weitergeleitete Benachrichtigung"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 37aae55..d6c8d09 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -553,7 +553,7 @@
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Ocultar"</string>
<string name="stream_voice_call" msgid="4410002696470423714">"Llamada"</string>
<string name="stream_system" msgid="7493299064422163147">"Sistema"</string>
- <string name="stream_ring" msgid="8213049469184048338">"Hacer sonar"</string>
+ <string name="stream_ring" msgid="8213049469184048338">"Timbre"</string>
<string name="stream_music" msgid="9086982948697544342">"Multimedia"</string>
<string name="stream_alarm" msgid="5209444229227197703">"Alarma"</string>
<string name="stream_notification" msgid="2563720670905665031">"Notificación"</string>
@@ -561,7 +561,7 @@
<string name="stream_dtmf" msgid="2447177903892477915">"Multifrecuencia de tono doble"</string>
<string name="stream_accessibility" msgid="301136219144385106">"Accesibilidad"</string>
<string name="ring_toggle_title" msgid="3281244519428819576">"Llamadas"</string>
- <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Hacer sonar"</string>
+ <string name="volume_ringer_status_normal" msgid="4273142424125855384">"Timbre"</string>
<string name="volume_ringer_status_vibrate" msgid="1825615171021346557">"Vibrar"</string>
<string name="volume_ringer_status_silent" msgid="6896394161022916369">"Silenciar"</string>
<string name="qs_status_phone_vibrate" msgid="204362991135761679">"Teléfono en vibración"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 83a7aaa..1f75490 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -544,7 +544,7 @@
<string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"Kjo e ruan në pamje deri sa ta heqësh nga gozhdimi. Prek dhe mbaj të shtypur \"Kreu\" për ta hequr nga gozhdimi."</string>
<string name="screen_pinning_toast" msgid="2266705122951934150">"Për të hequr gozhdimin e këtij ekrani, prek dhe mbaj butonat \"Prapa\" dhe \"Përmbledhja\"."</string>
<string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"Për të hequr gozhdimin e këtij ekrani, prek dhe mbaj butonat \"Prapa\" dhe \"Kreu\"."</string>
- <string name="screen_pinning_positive" msgid="3783985798366751226">"E kuptova!"</string>
+ <string name="screen_pinning_positive" msgid="3783985798366751226">"E kuptova"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Jo, faleminderit!"</string>
<string name="screen_pinning_start" msgid="1022122128489278317">"Ekrani u gozhdua"</string>
<string name="screen_pinning_exit" msgid="5187339744262325372">"Ekrani u hoq nga gozhdimi"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 182caa4..640bbda 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -416,7 +416,7 @@
<string name="keyguard_indication_charging_time_wireless" msgid="6959284458466962592">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji bila kutumia waya (imebakisha <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ili ijae)"</string>
<string name="keyguard_indication_charging_time" msgid="2056340799276374421">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji (Imebakisha <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ili ijae)"</string>
<string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji kwa kasi (Imebakisha <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ili ijae)"</string>
- <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji pole pole (Imebakisha <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ili ijae)"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji pole pole (Imebakisha <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ijae)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Badili mtumiaji"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Badili mtumiaji, mtumiaji wa sasa <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Mtumiaji wa sasa <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 9f8f45e..6e8b097 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -761,7 +761,7 @@
<item msgid="8175437057325747277">"ஏதுமில்லை"</item>
</string-array>
<string-array name="nav_bar_layouts">
- <item msgid="8077901629964902399">"இயல்பானது"</item>
+ <item msgid="8077901629964902399">"சராசரி"</item>
<item msgid="8256205964297588988">"சுருக்கமானது"</item>
<item msgid="8719936228094005878">"இடப்புறம் சாய்ந்தது"</item>
<item msgid="586019486955594690">"வலப்புறம் சாய்ந்தது"</item>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index affca3d..025efac 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -741,7 +741,7 @@
<string name="battery" msgid="7498329822413202973">"Pin"</string>
<string name="clock" msgid="7416090374234785905">"Đồng hồ"</string>
<string name="headset" msgid="4534219457597457353">"Tai nghe"</string>
- <string name="accessibility_long_click_tile" msgid="6687350750091842525">"Mở cài đặt"</string>
+ <string name="accessibility_long_click_tile" msgid="6687350750091842525">"Mở phần cài đặt"</string>
<string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"Đã kết nối tai nghe"</string>
<string name="accessibility_status_bar_headset" msgid="8666419213072449202">"Đã kết nối tai nghe"</string>
<string name="data_saver" msgid="5037565123367048522">"Trình tiết kiệm dữ liệu"</string>
@@ -817,7 +817,7 @@
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Ứng dụng không hỗ trợ chia đôi màn hình."</string>
<string name="forced_resizable_secondary_display" msgid="4230857851756391925">"Ứng dụng có thể không hoạt động trên màn hình phụ."</string>
<string name="activity_launch_on_secondary_display_failed_text" msgid="7793821742158306742">"Ứng dụng không hỗ trợ khởi chạy trên màn hình phụ."</string>
- <string name="accessibility_quick_settings_settings" msgid="6132460890024942157">"Mở cài đặt."</string>
+ <string name="accessibility_quick_settings_settings" msgid="6132460890024942157">"Mở phần cài đặt."</string>
<string name="accessibility_quick_settings_expand" msgid="2375165227880477530">"Mở cài đặt nhanh."</string>
<string name="accessibility_quick_settings_collapse" msgid="1792625797142648105">"Đóng cài đặt nhanh."</string>
<string name="accessibility_quick_settings_alarm_set" msgid="1863000242431528676">"Đã đặt báo thức."</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SystemGestureExclusionListenerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SystemGestureExclusionListenerCompat.java
index 9fdecfb..aeb0415 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SystemGestureExclusionListenerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SystemGestureExclusionListenerCompat.java
@@ -34,9 +34,11 @@
new ISystemGestureExclusionListener.Stub() {
@Override
public void onSystemGestureExclusionChanged(int displayId,
- Region systemGestureExclusion) {
+ Region systemGestureExclusion, Region unrestrictedOrNull) {
if (displayId == mDisplayId) {
- onExclusionChanged(systemGestureExclusion);
+ Region unrestricted = (unrestrictedOrNull == null)
+ ? systemGestureExclusion : unrestrictedOrNull;
+ onExclusionChanged(systemGestureExclusion, unrestricted);
}
}
};
@@ -47,11 +49,29 @@
}
/**
- * Called when the exclusion region has changed
+ * Called when the exclusion region has changed.
+ *
+ * TODO: remove, once all subclasses have migrated to
+ * {@link #onExclusionChanged(Region, Region)}.
*/
public abstract void onExclusionChanged(Region systemGestureExclusion);
/**
+ * Called when the exclusion region has changed.
+ *
+ * @param systemGestureExclusion the system gesture exclusion to be applied
+ * @param systemGestureExclusionUnrestricted what would be the system gesture exclusion, if
+ * there were no restrictions being applied. For logging purposes only.
+ *
+ */
+ public void onExclusionChanged(Region systemGestureExclusion,
+ Region systemGestureExclusionUnrestricted) {
+ // TODO: make abstract, once all subclasses have migrated away from
+ // onExclusionChanged(Region)
+ onExclusionChanged(systemGestureExclusion);
+ }
+
+ /**
* Registers the listener for getting exclusion rect changes.
*/
public void register() {
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 11d093f..10d132a 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -400,8 +400,11 @@
}
}
+ if (TextUtils.isEmpty(displayText)) displayText = joinNotEmpty(mSeparator, carrierNames);
+
displayText = updateCarrierTextWithSimIoError(displayText, carrierNames, subOrderBySlot,
allSimsMissing);
+
boolean airplaneMode = false;
// APM (airplane mode) != no carrier state. There are carrier services
// (e.g. WFC = Wi-Fi calling) which may operate in APM.
@@ -410,9 +413,6 @@
airplaneMode = true;
}
- if (TextUtils.isEmpty(displayText) && !airplaneMode) {
- displayText = joinNotEmpty(mSeparator, carrierNames);
- }
final CarrierTextCallbackInfo info = new CarrierTextCallbackInfo(
displayText,
carrierNames,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index fb3a586..69da990 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -123,7 +123,7 @@
msg = rez.getString(R.string.kg_sim_lock_esim_instructions, msg);
}
- if (mSecurityMessageDisplay != null) {
+ if (mSecurityMessageDisplay != null && getVisibility() == VISIBLE) {
mSecurityMessageDisplay.setMessage(msg);
}
mSimImageView.setImageTintList(ColorStateList.valueOf(color));
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 0b00b91..4a4fead 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -82,7 +82,7 @@
void processBundle(Bundle hints);
/**
- * Hides the UI.
+ * Hides any SysUI for the assistant, but _does not_ close the assistant itself.
*/
void hide();
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
index 662de3a..0c4f051 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
@@ -118,7 +118,6 @@
@Override // AssistManager.UiController
public void hide() {
- Dependency.get(AssistManager.class).hideAssist();
detach();
if (mInvocationAnimator.isRunning()) {
mInvocationAnimator.cancel();
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index 128cc61..ee79e6b 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -26,6 +26,7 @@
import android.view.MotionEvent;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.classifier.brightline.BrightLineFalsingManager;
import com.android.systemui.classifier.brightline.FalsingDataProvider;
@@ -102,7 +103,8 @@
} else {
mInternalFalsingManager = new BrightLineFalsingManager(
new FalsingDataProvider(context.getResources().getDisplayMetrics()),
- Dependency.get(AsyncSensorManager.class)
+ Dependency.get(AsyncSensorManager.class),
+ KeyguardUpdateMonitor.getInstance(context)
);
}
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 ce82bbf..9e0b702 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
@@ -23,11 +23,14 @@
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
+import android.hardware.biometrics.BiometricSourceType;
import android.net.Uri;
import android.util.Log;
import android.view.MotionEvent;
import com.android.internal.logging.MetricsLogger;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.plugins.FalsingManager;
@@ -47,11 +50,13 @@
private final SensorManager mSensorManager;
private final FalsingDataProvider mDataProvider;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private boolean mSessionStarted;
private MetricsLogger mMetricsLogger;
private int mIsFalseTouchCalls;
private boolean mShowingAod;
private boolean mScreenOn;
+ private boolean mJustUnlockedWithFace;
private final ExecutorService mBackgroundExecutor = Executors.newSingleThreadExecutor();
@@ -68,10 +73,27 @@
}
};
- public BrightLineFalsingManager(FalsingDataProvider falsingDataProvider,
- SensorManager sensorManager) {
+ private final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
+ new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onBiometricAuthenticated(int userId,
+ BiometricSourceType biometricSourceType) {
+ if (userId == KeyguardUpdateMonitor.getCurrentUser()
+ && biometricSourceType == BiometricSourceType.FACE) {
+ mJustUnlockedWithFace = true;
+ }
+ }
+ };
+
+ public BrightLineFalsingManager(
+ FalsingDataProvider falsingDataProvider,
+ SensorManager sensorManager,
+ KeyguardUpdateMonitor keyguardUpdateMonitor) {
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mDataProvider = falsingDataProvider;
mSensorManager = sensorManager;
+ mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
+
mMetricsLogger = new MetricsLogger();
mClassifiers = new ArrayList<>();
DistanceClassifier distanceClassifier = new DistanceClassifier(mDataProvider);
@@ -110,6 +132,7 @@
if (!mSessionStarted && !mShowingAod && mScreenOn) {
logDebug("Starting Session");
mSessionStarted = true;
+ mJustUnlockedWithFace = false;
registerSensors();
mClassifiers.forEach(FalsingClassifier::onSessionStarted);
}
@@ -141,7 +164,7 @@
@Override
public boolean isFalseTouch() {
- boolean r = mClassifiers.stream().anyMatch(falsingClassifier -> {
+ boolean r = !mJustUnlockedWithFace && mClassifiers.stream().anyMatch(falsingClassifier -> {
boolean result = falsingClassifier.isFalseTouch();
if (result) {
logInfo(falsingClassifier.getClass().getName() + ": true");
@@ -335,6 +358,7 @@
@Override
public void cleanup() {
unregisterSensors();
+ mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateCallback);
}
static void logDebug(String msg) {
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index fb8b6c7..75dc397 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -64,6 +64,8 @@
private static final int CHARGE_CYCLE_PERCENT_RESET = 45;
private static final long SIX_HOURS_MILLIS = Duration.ofHours(6).toMillis();
public static final int NO_ESTIMATE_AVAILABLE = -1;
+ private static final String BOOT_COUNT_KEY = "boot_count";
+ private static final String PREFS = "powerui_prefs";
private final Handler mHandler = new Handler();
@VisibleForTesting
@@ -118,7 +120,7 @@
// Check to see if we need to let the user know that the phone previously shut down due
// to the temperature being too high.
- showThermalShutdownDialog();
+ showWarnOnThermalShutdown();
// Register an observer to configure mEnableSkinTemperatureWarning and perform the
// registration of skin thermal event listener upon Settings change.
@@ -542,10 +544,23 @@
}
}
- private void showThermalShutdownDialog() {
- if (mPowerManager.getLastShutdownReason()
- == PowerManager.SHUTDOWN_REASON_THERMAL_SHUTDOWN) {
- mWarnings.showThermalShutdownWarning();
+ private void showWarnOnThermalShutdown() {
+ int bootCount = -1;
+ int lastReboot = mContext.getSharedPreferences(PREFS, 0).getInt(BOOT_COUNT_KEY, -1);
+ try {
+ bootCount = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.BOOT_COUNT);
+ } catch (Settings.SettingNotFoundException e) {
+ Slog.e(TAG, "Failed to read system boot count from Settings.Global.BOOT_COUNT");
+ }
+ // Only show the thermal shutdown warning when there is a thermal reboot.
+ if (bootCount > lastReboot) {
+ mContext.getSharedPreferences(PREFS, 0).edit().putInt(BOOT_COUNT_KEY,
+ bootCount).apply();
+ if (mPowerManager.getLastShutdownReason()
+ == PowerManager.SHUTDOWN_REASON_THERMAL_SHUTDOWN) {
+ mWarnings.showThermalShutdownWarning();
+ }
}
}
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 1ce4934..0009292 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
@@ -420,7 +420,14 @@
}
}
- Collections.sort(mSortedAndFiltered, mRankingComparator);
+ if (mSortedAndFiltered.size() == 1) {
+ // HACK: We need the comparator to run on all children in order to set the
+ // isHighPriority field. If there is only one child, then the comparison won't be run,
+ // so we have to trigger it manually. Get rid of this code as soon as possible.
+ mRankingComparator.compare(mSortedAndFiltered.get(0), mSortedAndFiltered.get(0));
+ } else {
+ Collections.sort(mSortedAndFiltered, mRankingComparator);
+ }
}
public void dump(PrintWriter pw, String indent) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index a8327f6..ea31be4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -1367,7 +1367,9 @@
if (isChildInGroup()) {
mTranslationWhenRemoved += getNotificationParent().getTranslationY();
}
- mPrivateLayout.setRemoved();
+ for (NotificationContentView l : mLayouts) {
+ l.setRemoved();
+ }
}
public boolean wasChildInGroupWhenRemoved() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 90f6324..0c5b27b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -1542,6 +1542,15 @@
if (mHeadsUpRemoteInput != null) {
mHeadsUpRemoteInput.setRemoved();
}
+ if (mExpandedWrapper != null) {
+ mExpandedWrapper.setRemoved();
+ }
+ if (mContractedWrapper != null) {
+ mContractedWrapper.setRemoved();
+ }
+ if (mHeadsUpWrapper != null) {
+ mHeadsUpWrapper.setRemoved();
+ }
}
public void setContentHeightAnimating(boolean animating) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index 20e8b73..1116106 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -39,6 +39,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.widget.MediaNotificationView;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.TransformableView;
@@ -67,6 +68,7 @@
private View mSeekBarView;
private Context mContext;
private MetricsLogger mMetricsLogger;
+ private boolean mIsViewVisible;
@VisibleForTesting
protected SeekBar.OnSeekBarChangeListener mSeekListener =
@@ -88,11 +90,46 @@
}
};
+ private MediaNotificationView.VisibilityChangeListener mVisibilityListener =
+ new MediaNotificationView.VisibilityChangeListener() {
+ @Override
+ public void onAggregatedVisibilityChanged(boolean isVisible) {
+ mIsViewVisible = isVisible;
+ if (isVisible && mMediaController != null) {
+ // Restart timer if we're currently playing and didn't already have one going
+ PlaybackState state = mMediaController.getPlaybackState();
+ if (state != null && state.getState() == PlaybackState.STATE_PLAYING
+ && mSeekBarTimer == null && mSeekBarView != null
+ && mSeekBarView.getVisibility() != View.GONE) {
+ startTimer();
+ }
+ } else {
+ clearTimer();
+ }
+ }
+ };
+
+ private View.OnAttachStateChangeListener mAttachStateListener =
+ new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ mIsViewVisible = false;
+ }
+ };
+
private MediaController.Callback mMediaCallback = new MediaController.Callback() {
@Override
public void onSessionDestroyed() {
clearTimer();
mMediaController.unregisterCallback(this);
+ if (mView instanceof MediaNotificationView) {
+ ((MediaNotificationView) mView).removeVisibilityListener(mVisibilityListener);
+ mView.removeOnAttachStateChangeListener(mAttachStateListener);
+ }
}
@Override
@@ -126,10 +163,17 @@
mContext = ctx;
mMediaManager = Dependency.get(NotificationMediaManager.class);
mMetricsLogger = Dependency.get(MetricsLogger.class);
+
+ if (mView instanceof MediaNotificationView) {
+ MediaNotificationView mediaView = (MediaNotificationView) mView;
+ mediaView.addVisibilityListener(mVisibilityListener);
+ mView.addOnAttachStateChangeListener(mAttachStateListener);
+ }
}
private void resolveViews() {
mActions = mView.findViewById(com.android.internal.R.id.media_actions);
+ mIsViewVisible = mView.isShown();
final MediaSession.Token token = mRow.getEntry().notification.getNotification().extras
.getParcelable(Notification.EXTRA_MEDIA_SESSION);
@@ -208,24 +252,37 @@
private void startTimer() {
clearTimer();
- mSeekBarTimer = new Timer(true /* isDaemon */);
- mSeekBarTimer.schedule(new TimerTask() {
- @Override
- public void run() {
- mHandler.post(mOnUpdateTimerTick);
- }
- }, 0, PROGRESS_UPDATE_INTERVAL);
+ if (mIsViewVisible) {
+ mSeekBarTimer = new Timer(true /* isDaemon */);
+ mSeekBarTimer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ mHandler.post(mOnUpdateTimerTick);
+ }
+ }, 0, PROGRESS_UPDATE_INTERVAL);
+ }
}
private void clearTimer() {
if (mSeekBarTimer != null) {
- // TODO: also trigger this when the notification panel is collapsed
mSeekBarTimer.cancel();
mSeekBarTimer.purge();
mSeekBarTimer = null;
}
}
+ @Override
+ public void setRemoved() {
+ clearTimer();
+ if (mMediaController != null) {
+ mMediaController.unregisterCallback(mMediaCallback);
+ }
+ if (mView instanceof MediaNotificationView) {
+ ((MediaNotificationView) mView).removeVisibilityListener(mVisibilityListener);
+ mView.removeOnAttachStateChangeListener(mAttachStateListener);
+ }
+ }
+
private boolean canSeekMedia(@Nullable PlaybackState state) {
if (state == null) {
return false;
@@ -261,7 +318,6 @@
public void run() {
if (mMediaController != null && mSeekBar != null) {
PlaybackState playbackState = mMediaController.getPlaybackState();
-
if (playbackState != null) {
updatePlaybackUi(playbackState);
} else {
@@ -274,6 +330,10 @@
};
private void updatePlaybackUi(PlaybackState state) {
+ if (mSeekBar == null || mSeekBarElapsedTime == null) {
+ return;
+ }
+
long position = state.getPosition();
mSeekBar.setProgress((int) position);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 47906a7..3950003 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -261,6 +261,12 @@
mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
}
+ /**
+ * Called to indicate this view is removed
+ */
+ public void setRemoved() {
+ }
+
public int getCustomBackgroundColor() {
// Parent notifications should always use the normal background color
return mRow.isSummaryWithChildren() ? 0 : mBackgroundColor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index f9cdde8..6a74779 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -31,6 +31,7 @@
import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.SystemProperties;
import android.util.Log;
import android.util.MathUtils;
import android.view.Gravity;
@@ -66,7 +67,8 @@
public class EdgeBackGestureHandler implements DisplayListener {
private static final String TAG = "EdgeBackGestureHandler";
- private static final int MAX_LONG_PRESS_TIMEOUT = 250;
+ private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
+ "gestures.back_timeout", 250);
private final IPinnedStackListener.Stub mImeChangedListener = new IPinnedStackListener.Stub() {
@Override
@@ -103,7 +105,7 @@
new ISystemGestureExclusionListener.Stub() {
@Override
public void onSystemGestureExclusionChanged(int displayId,
- Region systemGestureExclusion) {
+ Region systemGestureExclusion, Region unrestrictedOrNull) {
if (displayId == mDisplayId) {
mMainExecutor.execute(() -> mExcludeRegion.set(systemGestureExclusion));
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 6bfa048..f689a3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -619,6 +619,10 @@
// Always disable recents when alternate car mode UI is active and for secondary displays.
boolean disableRecent = isRecentsButtonDisabled();
+ // Disable the home handle if both hone and recents are disabled
+ boolean disableHomeHandle = disableRecent
+ && ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
+
boolean disableBack = !useAltBack && (isGesturalMode(mNavBarMode)
|| ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0));
@@ -649,6 +653,7 @@
getBackButton().setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
getHomeButton().setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
+ getHomeHandle().setVisibility(disableHomeHandle ? View.INVISIBLE : View.VISIBLE);
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index d28dadd..9fdd3b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -133,6 +133,12 @@
mBlankScreen = mDisplayRequiresBlanking;
mAnimationDuration = mWakeLockScreenSensorActive
? ScrimController.ANIMATION_DURATION_LONG : ScrimController.ANIMATION_DURATION;
+
+ // Wake sensor will show the wallpaper, let's fade from black. Otherwise it will
+ // feel like the screen is flashing if the wallpaper is light.
+ if (mWakeLockScreenSensorActive && previousState == AOD) {
+ updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
+ }
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index db45ad78..0044ca7 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -36,6 +36,7 @@
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.Handler;
+import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -65,6 +66,8 @@
public class CarrierTextControllerTest extends SysuiTestCase {
private static final CharSequence SEPARATOR = " \u2014 ";
+ private static final CharSequence INVALID_CARD_TEXT = "Invalid card";
+ private static final CharSequence AIRPLANE_MODE_TEXT = "Airplane mode";
private static final String TEST_CARRIER = "TEST_CARRIER";
private static final String TEST_CARRIER_2 = "TEST_CARRIER_2";
private static final String TEST_GROUP_UUID = "59b5c870-fc4c-47a4-a99e-9db826b48b24";
@@ -106,6 +109,10 @@
mContext.addMockSystemService(ConnectivityManager.class, mConnectivityManager);
mContext.addMockSystemService(TelephonyManager.class, mTelephonyManager);
mContext.addMockSystemService(SubscriptionManager.class, mSubscriptionManager);
+ mContext.getOrCreateTestableResources().addOverride(
+ R.string.keyguard_sim_error_message_short, INVALID_CARD_TEXT);
+ mContext.getOrCreateTestableResources().addOverride(
+ R.string.airplane_mode, AIRPLANE_MODE_TEXT);
mDependency.injectMockDependency(WakefulnessLifecycle.class);
mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
new Handler(mTestableLooper.getLooper()));
@@ -122,6 +129,53 @@
}
@Test
+ public void testAirplaneMode() {
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
+ reset(mCarrierTextCallback);
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+ when(mKeyguardUpdateMonitor.getSimState(0)).thenReturn(IccCardConstants.State.READY);
+ mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+ mCarrierTextController.updateCarrierText();
+
+ ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextController.CarrierTextCallbackInfo.class);
+
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+ assertEquals(AIRPLANE_MODE_TEXT, captor.getValue().carrierText);
+ }
+
+ @Test
+ public void testCardIOError() {
+ reset(mCarrierTextCallback);
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+ when(mKeyguardUpdateMonitor.getSimState(0)).thenReturn(IccCardConstants.State.READY);
+ when(mKeyguardUpdateMonitor.getSimState(1)).thenReturn(
+ IccCardConstants.State.CARD_IO_ERROR);
+ mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+ mCarrierTextController.mCallback.onSimStateChanged(3, 1,
+ IccCardConstants.State.CARD_IO_ERROR);
+
+ ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextController.CarrierTextCallbackInfo.class);
+
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+ assertEquals("TEST_CARRIER" + SEPARATOR + INVALID_CARD_TEXT, captor.getValue().carrierText);
+ // There's only one subscription in the list
+ assertEquals(1, captor.getValue().listOfCarriers.length);
+ assertEquals(TEST_CARRIER, captor.getValue().listOfCarriers[0]);
+ }
+
+ @Test
public void testWrongSlots() {
reset(mCarrierTextCallback);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
index 260555f..e2d8e56 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
@@ -23,6 +23,7 @@
import static android.app.Notification.CATEGORY_EVENT;
import static android.app.Notification.CATEGORY_MESSAGE;
import static android.app.Notification.CATEGORY_REMINDER;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
@@ -62,6 +63,8 @@
import android.testing.TestableLooper.RunWithLooper;
import android.util.ArraySet;
+import androidx.test.filters.SmallTest;
+
import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.InitController;
@@ -85,8 +88,6 @@
import java.util.List;
import java.util.Map;
-import androidx.test.filters.SmallTest;
-
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@@ -114,6 +115,7 @@
MockitoAnnotations.initMocks(this);
when(mMockStatusBarNotification.getUid()).thenReturn(UID_NORMAL);
when(mMockStatusBarNotification.cloneLight()).thenReturn(mMockStatusBarNotification);
+ when(mMockStatusBarNotification.getKey()).thenReturn("mock_key");
when(mMockPackageManager.checkUidPermission(
eq(Manifest.permission.NOTIFICATION_DURING_SETUP),
@@ -232,6 +234,7 @@
Notification n = mMockStatusBarNotification.getNotification();
n.flags = Notification.FLAG_FOREGROUND_SERVICE;
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
+ entry.setRow(mRow);
mNotificationData.add(entry);
Bundle override = new Bundle();
override.putInt(OVERRIDE_VIS_EFFECTS, 255);
@@ -250,6 +253,7 @@
n = nb.build();
when(mMockStatusBarNotification.getNotification()).thenReturn(n);
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
+ entry.setRow(mRow);
mNotificationData.add(entry);
Bundle override = new Bundle();
override.putInt(OVERRIDE_VIS_EFFECTS, 255);
@@ -263,6 +267,7 @@
public void testIsExemptFromDndVisualSuppression_system() {
initStatusBarNotification(false);
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
+ entry.setRow(mRow);
entry.mIsSystemNotification = true;
mNotificationData.add(entry);
Bundle override = new Bundle();
@@ -277,6 +282,7 @@
public void testIsNotExemptFromDndVisualSuppression_hiddenCategories() {
initStatusBarNotification(false);
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
+ entry.setRow(mRow);
entry.mIsSystemNotification = true;
Bundle override = new Bundle();
override.putInt(OVERRIDE_VIS_EFFECTS, NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT);
@@ -529,6 +535,62 @@
assertEquals(-1, mNotificationData.mRankingComparator.compare(a, b));
}
+ @Test
+ public void testSort_properlySetsIsTopBucket() {
+
+ Notification notification = new Notification.Builder(mContext, "test")
+ .build();
+ StatusBarNotification sbn = new StatusBarNotification(
+ "pkg",
+ "pkg",
+ 0,
+ "tag",
+ 0,
+ 0,
+ notification,
+ mContext.getUser(),
+ "",
+ 0);
+
+ Bundle override = new Bundle();
+ override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_DEFAULT);
+ mNotificationData.rankingOverrides.put(sbn.getKey(), override);
+
+ NotificationEntry entry = new NotificationEntry(sbn);
+ entry.setRow(mRow);
+ mNotificationData.add(entry);
+
+ assertTrue(entry.isTopBucket());
+ }
+
+ @Test
+ public void testSort_properlySetsIsNotTopBucket() {
+ Notification notification = new Notification.Builder(mContext, "test")
+ .build();
+ StatusBarNotification sbn = new StatusBarNotification(
+ "pkg",
+ "pkg",
+ 0,
+ "tag",
+ 0,
+ 0,
+ notification,
+ mContext.getUser(),
+ "",
+ 0);
+
+ Bundle override = new Bundle();
+ override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
+ mNotificationData.rankingOverrides.put(sbn.getKey(), override);
+
+ NotificationEntry entry = new NotificationEntry(sbn);
+ entry.setRow(mRow);
+
+ mNotificationData.add(entry);
+
+ assertFalse(entry.isTopBucket());
+ }
+
private void initStatusBarNotification(boolean allowDuringSetup) {
Bundle bundle = new Bundle();
bundle.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, allowDuringSetup);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 9ecb8d5..c851c91 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -137,7 +137,7 @@
mDependency.injectTestDependency(
NotificationBlockingHelperManager.class,
mBlockingHelperManager);
- mDependency.injectTestDependency(StatusBarStateController.class, mBarState);
+ mDependency.injectTestDependency(SysuiStatusBarStateController.class, mBarState);
mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
mDependency.injectTestDependency(NotificationRemoteInputManager.class,
mRemoteInputManager);
@@ -163,7 +163,7 @@
mock(DynamicPrivacyController.class),
mock(ConfigurationController.class),
mock(ActivityStarterDelegate.class),
- mock(StatusBarStateController.class),
+ mock(SysuiStatusBarStateController.class),
mHeadsUpManager,
mKeyguardBypassController);
mStackScroller = spy(mStackScrollerInternal);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 91ae156..2ddc7259 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8467,32 +8467,6 @@
}
}
- void setRunningRemoteAnimation(int pid, boolean runningRemoteAnimation) {
- if (pid == Process.myPid()) {
- Slog.wtf(TAG, "system can't run remote animation");
- return;
- }
- synchronized (ActivityManagerService.this) {
- final ProcessRecord pr;
- synchronized (mPidsSelfLocked) {
- pr = mPidsSelfLocked.get(pid);
- if (pr == null) {
- Slog.w(TAG, "setRunningRemoteAnimation called on unknown pid: " + pid);
- return;
- }
- }
- if (pr.runningRemoteAnimation == runningRemoteAnimation) {
- return;
- }
- pr.runningRemoteAnimation = runningRemoteAnimation;
- if (DEBUG_OOM_ADJ) {
- Slog.i(TAG, "Setting runningRemoteAnimation=" + pr.runningRemoteAnimation
- + " for pid=" + pid);
- }
- updateOomAdjLocked(pr, true, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
- }
- }
-
public final void enterSafeMode() {
synchronized(this) {
// It only makes sense to do this before the system is ready
@@ -17971,11 +17945,6 @@
}
@Override
- public void setRunningRemoteAnimation(int pid, boolean runningRemoteAnimation) {
- ActivityManagerService.this.setRunningRemoteAnimation(pid, runningRemoteAnimation);
- }
-
- @Override
public List<ProcessMemoryState> getMemoryStateForProcesses() {
List<ProcessMemoryState> processMemoryStates = new ArrayList<>();
synchronized (mPidsSelfLocked) {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 563b2f3..ea30842 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -20,6 +20,7 @@
import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityManagerService.MY_PID;
@@ -1348,6 +1349,25 @@
}
}
+ @Override
+ public void setRunningRemoteAnimation(boolean runningRemoteAnimation) {
+ if (pid == Process.myPid()) {
+ Slog.wtf(TAG, "system can't run remote animation");
+ return;
+ }
+ synchronized (mService) {
+ if (this.runningRemoteAnimation == runningRemoteAnimation) {
+ return;
+ }
+ this.runningRemoteAnimation = runningRemoteAnimation;
+ if (DEBUG_OOM_ADJ) {
+ Slog.i(TAG, "Setting runningRemoteAnimation=" + runningRemoteAnimation
+ + " for pid=" + pid);
+ }
+ mService.updateOomAdjLocked(this, true, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
+ }
+ }
+
public long getInputDispatchingTimeout() {
return mWindowProcessController.getInputDispatchingTimeout();
}
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 8de2595..b46f034 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -15,6 +15,7 @@
*/
package com.android.server.camera;
+import android.annotation.IntDef;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -44,6 +45,8 @@
import com.android.server.SystemService;
import com.android.server.wm.WindowManagerInternal;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -100,7 +103,26 @@
private static final String NFC_SERVICE_BINDER_NAME = "nfc";
private static final IBinder nfcInterfaceToken = new Binder();
- private final boolean mNotifyNfc;
+ // Valid values for NFC_NOTIFICATION_PROP
+ // Do not disable active NFC for any camera use
+ private static final int NFC_NOTIFY_NONE = 0;
+ // Always disable active NFC for any camera use
+ private static final int NFC_NOTIFY_ALL = 1;
+ // Disable active NFC only for back-facing cameras
+ private static final int NFC_NOTIFY_BACK = 2;
+ // Disable active NFC only for front-facing cameras
+ private static final int NFC_NOTIFY_FRONT = 3;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"NFC_"}, value =
+ {NFC_NOTIFY_NONE,
+ NFC_NOTIFY_ALL,
+ NFC_NOTIFY_BACK,
+ NFC_NOTIFY_FRONT})
+ private @interface NfcNotifyState {};
+
+ private final @NfcNotifyState int mNotifyNfc;
+ private boolean mLastNfcPollState = true;
/**
* Structure to track camera usage
@@ -202,8 +224,12 @@
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper(), this);
- mNotifyNfc = SystemProperties.getInt(NFC_NOTIFICATION_PROP, 0) > 0;
- if (DEBUG) Slog.v(TAG, "Notify NFC behavior is " + (mNotifyNfc ? "active" : "disabled"));
+ int notifyNfc = SystemProperties.getInt(NFC_NOTIFICATION_PROP, 0);
+ if (notifyNfc < NFC_NOTIFY_NONE || notifyNfc > NFC_NOTIFY_FRONT) {
+ notifyNfc = NFC_NOTIFY_NONE;
+ }
+ mNotifyNfc = notifyNfc;
+ if (DEBUG) Slog.v(TAG, "Notify NFC state is " + nfcNotifyToString(mNotifyNfc));
}
@Override
@@ -270,12 +296,10 @@
mCameraServiceRaw = null;
// All cameras reset to idle on camera service death
- boolean wasEmpty = mActiveCameraUsage.isEmpty();
mActiveCameraUsage.clear();
- if ( mNotifyNfc && !wasEmpty ) {
- notifyNfcService(/*enablePolling*/ true);
- }
+ // Ensure NFC is back on
+ notifyNfcService(/*enablePolling*/ true);
}
}
@@ -474,14 +498,32 @@
break;
}
- boolean isEmpty = mActiveCameraUsage.isEmpty();
- if ( mNotifyNfc && (wasEmpty != isEmpty) ) {
- notifyNfcService(isEmpty);
+ switch (mNotifyNfc) {
+ case NFC_NOTIFY_NONE:
+ break;
+ case NFC_NOTIFY_ALL:
+ notifyNfcService(mActiveCameraUsage.isEmpty());
+ break;
+ case NFC_NOTIFY_BACK:
+ case NFC_NOTIFY_FRONT:
+ boolean enablePolling = true;
+ int targetFacing = mNotifyNfc == NFC_NOTIFY_BACK
+ ? ICameraServiceProxy.CAMERA_FACING_BACK :
+ ICameraServiceProxy.CAMERA_FACING_FRONT;
+ for (int i = 0; i < mActiveCameraUsage.size(); i++) {
+ if (mActiveCameraUsage.valueAt(i).mCameraFacing == targetFacing) {
+ enablePolling = false;
+ break;
+ }
+ }
+ notifyNfcService(enablePolling);
+ break;
}
}
}
private void notifyNfcService(boolean enablePolling) {
+ if (enablePolling == mLastNfcPollState) return;
IBinder nfcServiceBinder = getBinderService(NFC_SERVICE_BINDER_NAME);
if (nfcServiceBinder == null) {
@@ -490,9 +532,14 @@
}
INfcAdapter nfcAdapterRaw = INfcAdapter.Stub.asInterface(nfcServiceBinder);
int flags = enablePolling ? ENABLE_POLLING_FLAGS : DISABLE_POLLING_FLAGS;
- if (DEBUG) Slog.v(TAG, "Setting NFC reader mode to flags " + flags);
+ if (DEBUG) {
+ Slog.v(TAG, "Setting NFC reader mode to flags " + flags
+ + " to turn polling " + enablePolling);
+ }
+
try {
nfcAdapterRaw.setReaderMode(nfcInterfaceToken, null, flags, null);
+ mLastNfcPollState = enablePolling;
} catch (RemoteException e) {
Slog.w(TAG, "Could not notify NFC service, remote exception: " + e);
}
@@ -529,4 +576,13 @@
return "CAMERA_FACING_UNKNOWN";
}
+ private static String nfcNotifyToString(@NfcNotifyState int nfcNotifyState) {
+ switch (nfcNotifyState) {
+ case NFC_NOTIFY_NONE: return "NFC_NOTIFY_NONE";
+ case NFC_NOTIFY_ALL: return "NFC_NOTIFY_ALL";
+ case NFC_NOTIFY_BACK: return "NFC_NOTIFY_BACK";
+ case NFC_NOTIFY_FRONT: return "NFC_NOTIFY_FRONT";
+ }
+ return "UNKNOWN_NFC_NOTIFY";
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 4957eed..73d160d 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -772,7 +772,6 @@
case WifiManager.WIFI_AP_STATE_FAILED:
default:
disableWifiIpServingLocked(ifname, curState);
- mEntitlementMgr.stopProvisioningIfNeeded(TETHERING_WIFI);
break;
}
}
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 78a48da..c45a314 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -728,6 +728,7 @@
private SensorManager mSensorManager;
private Sensor mLightSensor;
+ private LightSensorEventListener mLightSensorListener = new LightSensorEventListener();
// Take it as low brightness before valid sensor data comes
private float mAmbientLux = -1.0f;
private AmbientFilter mAmbientFilter;
@@ -907,19 +908,40 @@
mSensorManager.registerListener(mLightSensorListener,
mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
} else {
+ mLightSensorListener.removeCallbacks();
mSensorManager.unregisterListener(mLightSensorListener);
}
}
- private final SensorEventListener mLightSensorListener = new SensorEventListener() {
+ private final class LightSensorEventListener implements SensorEventListener {
+ final private static int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS;
+ private float mLastSensorData;
+
@Override
public void onSensorChanged(SensorEvent event) {
- long now = SystemClock.uptimeMillis();
- mAmbientFilter.addValue(now, event.values[0]);
- mAmbientLux = mAmbientFilter.getEstimate(now);
+ mLastSensorData = event.values[0];
+ if (DEBUG) {
+ Slog.d(TAG, "On sensor changed: " + mLastSensorData);
+ }
- synchronized (mLock) {
- onBrightnessChangedLocked();
+ boolean zoneChanged = isDifferentZone(mLastSensorData, mAmbientLux);
+ if (zoneChanged && mLastSensorData < mAmbientLux) {
+ // Easier to see flicker at lower brightness environment. Forget the history to
+ // get immediate response.
+ mAmbientFilter.clear();
+ }
+
+ long now = SystemClock.uptimeMillis();
+ mAmbientFilter.addValue(now, mLastSensorData);
+
+ mHandler.removeCallbacks(mInjectSensorEventRunnable);
+ processSensorData(now);
+
+ if (zoneChanged && mLastSensorData > mAmbientLux) {
+ // Sensor may not report new event if there is no brightness change.
+ // Need to keep querying the temporal filter for the latest estimation,
+ // until enter in higher lux zone or is interrupted by a new sensor event.
+ mHandler.postDelayed(mInjectSensorEventRunnable, INJECT_EVENTS_INTERVAL_MS);
}
}
@@ -927,6 +949,47 @@
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Not used.
}
+
+ public void removeCallbacks() {
+ mHandler.removeCallbacks(mInjectSensorEventRunnable);
+ }
+
+ private void processSensorData(long now) {
+ mAmbientLux = mAmbientFilter.getEstimate(now);
+
+ synchronized (mLock) {
+ onBrightnessChangedLocked();
+ }
+ }
+
+ private boolean isDifferentZone(float lux1, float lux2) {
+ for (int z = 0; z < mAmbientBrightnessThresholds.length; z++) {
+ final float boundary = mAmbientBrightnessThresholds[z];
+
+ // Test each boundary. See if the current value and the new value are at
+ // different sides.
+ if ((lux1 <= boundary && lux2 > boundary)
+ || (lux1 > boundary && lux2 <= boundary)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private Runnable mInjectSensorEventRunnable = new Runnable() {
+ @Override
+ public void run() {
+ long now = SystemClock.uptimeMillis();
+ // No need to really inject the last event into a temporal filter.
+ processSensorData(now);
+
+ // Inject next event if there is a possible zone change.
+ if (isDifferentZone(mLastSensorData, mAmbientLux)) {
+ mHandler.postDelayed(mInjectSensorEventRunnable, INJECT_EVENTS_INTERVAL_MS);
+ }
+ }
+ };
};
private final class ScreenStateReceiver extends BroadcastReceiver {
diff --git a/services/core/java/com/android/server/om/IdmapDaemon.java b/services/core/java/com/android/server/om/IdmapDaemon.java
new file mode 100644
index 0000000..91824c3
--- /dev/null
+++ b/services/core/java/com/android/server/om/IdmapDaemon.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.om;
+
+import static android.content.Context.IDMAP_SERVICE;
+
+import static com.android.server.om.OverlayManagerService.DEBUG;
+import static com.android.server.om.OverlayManagerService.TAG;
+
+import android.os.IBinder;
+import android.os.IIdmap2;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.util.Slog;
+
+import com.android.server.FgThread;
+
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * To prevent idmap2d from continuously running, the idmap daemon will terminate after 10
+ * seconds without a transaction.
+ **/
+class IdmapDaemon {
+ // The amount of time in milliseconds to wait after a transaction to the idmap service is made
+ // before stopping the service.
+ private static final int SERVICE_TIMEOUT_MS = 10000;
+
+ // The amount of time in milliseconds to wait when attempting to connect to idmap service.
+ private static final int SERVICE_CONNECT_TIMEOUT_MS = 5000;
+
+ private static final Object IDMAP_TOKEN = new Object();
+ private static final String IDMAP_DAEMON = "idmap2d";
+
+ private static IdmapDaemon sInstance;
+ private volatile IIdmap2 mService;
+ private final AtomicInteger mOpenedCount = new AtomicInteger();
+
+ /**
+ * An {@link AutoCloseable} connection to the idmap service. When the connection is closed or
+ * finalized, the idmap service will be stopped after a period of time unless another connection
+ * to the service is open.
+ **/
+ private class Connection implements AutoCloseable {
+ private boolean mOpened = true;
+
+ private Connection() {
+ synchronized (IDMAP_TOKEN) {
+ mOpenedCount.incrementAndGet();
+ }
+ }
+
+ @Override
+ public void close() {
+ synchronized (IDMAP_TOKEN) {
+ if (!mOpened) {
+ return;
+ }
+
+ mOpened = false;
+ if (mOpenedCount.decrementAndGet() != 0) {
+ // Only post the callback to stop the service if the service does not have an
+ // open connection.
+ return;
+ }
+
+ FgThread.getHandler().postDelayed(() -> {
+ synchronized (IDMAP_TOKEN) {
+ // Only stop the service if the service does not have an open connection.
+ if (mService == null || mOpenedCount.get() != 0) {
+ return;
+ }
+
+ stopIdmapService();
+ mService = null;
+ }
+ }, IDMAP_TOKEN, SERVICE_TIMEOUT_MS);
+ }
+ }
+ }
+
+ static IdmapDaemon getInstance() {
+ if (sInstance == null) {
+ sInstance = new IdmapDaemon();
+ }
+ return sInstance;
+ }
+
+ String createIdmap(String targetPath, String overlayPath, int policies, boolean enforce,
+ int userId) throws Exception {
+ try (Connection connection = connect()) {
+ return mService.createIdmap(targetPath, overlayPath, policies, enforce, userId);
+ }
+ }
+
+ boolean removeIdmap(String overlayPath, int userId) throws Exception {
+ try (Connection connection = connect()) {
+ return mService.removeIdmap(overlayPath, userId);
+ }
+ }
+
+ boolean verifyIdmap(String overlayPath, int policies, boolean enforce, int userId)
+ throws Exception {
+ try (Connection connection = connect()) {
+ return mService.verifyIdmap(overlayPath, policies, enforce, userId);
+ }
+ }
+
+ String getIdmapPath(String overlayPath, int userId) throws Exception {
+ try (Connection connection = connect()) {
+ return mService.getIdmapPath(overlayPath, userId);
+ }
+ }
+
+ static void startIdmapService() {
+ SystemProperties.set("ctl.start", IDMAP_DAEMON);
+ }
+
+ static void stopIdmapService() {
+ SystemProperties.set("ctl.stop", IDMAP_DAEMON);
+ }
+
+ private Connection connect() throws Exception {
+ synchronized (IDMAP_TOKEN) {
+ FgThread.getHandler().removeCallbacksAndMessages(IDMAP_TOKEN);
+ if (mService != null) {
+ // Not enough time has passed to stop the idmap service. Reuse the existing
+ // interface.
+ return new Connection();
+ }
+
+ // Start the idmap service if it is not currently running.
+ startIdmapService();
+
+ // Block until the service is found.
+ FutureTask<IBinder> bindIdmap = new FutureTask<>(() -> {
+ while (true) {
+ try {
+ IBinder binder = ServiceManager.getService(IDMAP_SERVICE);
+ if (binder != null) {
+ return binder;
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "service '" + IDMAP_SERVICE + "' not retrieved; "
+ + e.getMessage());
+ }
+ Thread.sleep(100);
+ }
+ });
+
+ IBinder binder;
+ try {
+ FgThread.getHandler().postAtFrontOfQueue(bindIdmap);
+ binder = bindIdmap.get(SERVICE_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (Exception rethrow) {
+ Slog.e(TAG, "service '" + IDMAP_SERVICE + "' not found;");
+ throw rethrow;
+ }
+
+ try {
+ binder.linkToDeath(() -> {
+ Slog.w(TAG, "service '" + IDMAP_SERVICE + "' died");
+ }, 0);
+ } catch (RemoteException rethrow) {
+ Slog.e(TAG, "service '" + IDMAP_SERVICE + "' failed to be bound");
+ throw rethrow;
+ }
+
+ mService = IIdmap2.Stub.asInterface(binder);
+ if (DEBUG) {
+ Slog.d(TAG, "service '" + IDMAP_SERVICE + "' connected");
+ }
+
+ return new Connection();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index b604aa8..9b6d986 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -16,9 +16,6 @@
package com.android.server.om;
-import static android.content.Context.IDMAP_SERVICE;
-import static android.text.format.DateUtils.SECOND_IN_MILLIS;
-
import static com.android.server.om.OverlayManagerService.DEBUG;
import static com.android.server.om.OverlayManagerService.TAG;
@@ -27,15 +24,11 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.os.Build.VERSION_CODES;
-import android.os.IBinder;
import android.os.IIdmap2;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.Slog;
-import com.android.internal.os.BackgroundThread;
import com.android.server.om.OverlayManagerServiceImpl.PackageManagerHelper;
import com.android.server.pm.Installer;
@@ -51,11 +44,6 @@
*/
class IdmapManager {
private static final boolean FEATURE_FLAG_IDMAP2 = true;
-
- private final Installer mInstaller;
- private final PackageManagerHelper mPackageManager;
- private IIdmap2 mIdmap2Service;
-
private static final boolean VENDOR_IS_Q_OR_LATER;
static {
final String value = SystemProperties.get("ro.vndk.version", "29");
@@ -70,12 +58,14 @@
VENDOR_IS_Q_OR_LATER = isQOrLater;
}
+ private final Installer mInstaller;
+ private final PackageManagerHelper mPackageManager;
+ private final IdmapDaemon mIdmapDaemon;
+
IdmapManager(final Installer installer, final PackageManagerHelper packageManager) {
mInstaller = installer;
mPackageManager = packageManager;
- if (FEATURE_FLAG_IDMAP2) {
- connectToIdmap2d();
- }
+ mIdmapDaemon = IdmapDaemon.getInstance();
}
boolean createIdmap(@NonNull final PackageInfo targetPackage,
@@ -91,11 +81,11 @@
if (FEATURE_FLAG_IDMAP2) {
int policies = calculateFulfilledPolicies(targetPackage, overlayPackage, userId);
boolean enforce = enforceOverlayable(overlayPackage);
- if (mIdmap2Service.verifyIdmap(overlayPath, policies, enforce, userId)) {
+ if (mIdmapDaemon.verifyIdmap(overlayPath, policies, enforce, userId)) {
return true;
}
- return mIdmap2Service.createIdmap(targetPath, overlayPath, policies, enforce,
- userId) != null;
+ return mIdmapDaemon.createIdmap(targetPath, overlayPath, policies,
+ enforce, userId) != null;
} else {
mInstaller.idmap(targetPath, overlayPath, sharedGid);
return true;
@@ -113,7 +103,7 @@
}
try {
if (FEATURE_FLAG_IDMAP2) {
- return mIdmap2Service.removeIdmap(oi.baseCodePath, userId);
+ return mIdmapDaemon.removeIdmap(oi.baseCodePath, userId);
} else {
mInstaller.removeIdmap(oi.baseCodePath);
return true;
@@ -137,7 +127,7 @@
final int userId) {
if (FEATURE_FLAG_IDMAP2) {
try {
- return mIdmap2Service.getIdmapPath(overlayPackagePath, userId);
+ return mIdmapDaemon.getIdmapPath(overlayPackagePath, userId);
} catch (Exception e) {
Slog.w(TAG, "failed to get idmap path for " + overlayPackagePath + ": "
+ e.getMessage());
@@ -151,35 +141,6 @@
}
}
- private void connectToIdmap2d() {
- IBinder binder = ServiceManager.getService(IDMAP_SERVICE);
- if (binder != null) {
- try {
- binder.linkToDeath(new IBinder.DeathRecipient() {
- @Override
- public void binderDied() {
- Slog.w(TAG, "service '" + IDMAP_SERVICE + "' died; reconnecting...");
- connectToIdmap2d();
- }
-
- }, 0);
- } catch (RemoteException e) {
- binder = null;
- }
- }
- if (binder != null) {
- mIdmap2Service = IIdmap2.Stub.asInterface(binder);
- if (DEBUG) {
- Slog.d(TAG, "service '" + IDMAP_SERVICE + "' connected");
- }
- } else {
- Slog.w(TAG, "service '" + IDMAP_SERVICE + "' not found; trying again...");
- BackgroundThread.getHandler().postDelayed(() -> {
- connectToIdmap2d();
- }, SECOND_IN_MILLIS);
- }
- }
-
/**
* Checks if overlayable and policies should be enforced on the specified overlay for backwards
* compatibility with pre-Q overlays.
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index da69986..ce95181 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -262,6 +262,7 @@
initIfNeeded();
onSwitchUser(UserHandle.USER_SYSTEM);
+ IdmapDaemon.stopIdmapService();
publishBinderService(Context.OVERLAY_SERVICE, mService);
publishLocalService(OverlayManagerService.class, this);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7cbf919..a7d436a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -320,7 +320,6 @@
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.policy.PermissionPolicyInternal.OnInitializedCallback;
import com.android.server.security.VerityUtils;
import com.android.server.storage.DeviceStorageMonitorInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -11033,14 +11032,15 @@
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) {
@@ -11050,6 +11050,9 @@
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.
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 8884821..899f802 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -2098,7 +2098,8 @@
final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
if (pkg == null || pkg.mExtras == null) {
- throw new IllegalArgumentException("Unknown package: " + packageName);
+ Log.e(TAG, "Unknown package: " + packageName);
+ return;
}
final BasePermission bp;
synchronized(mLock) {
@@ -2239,7 +2240,8 @@
final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
if (pkg == null || pkg.mExtras == null) {
- throw new IllegalArgumentException("Unknown package: " + packageName);
+ Log.e(TAG, "Unknown package: " + packageName);
+ return;
}
if (mPackageManagerInt.filterAppAccess(pkg, Binder.getCallingUid(), userId)) {
throw new IllegalArgumentException("Unknown package: " + packageName);
diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java
index 56d8396..4e9b724 100644
--- a/services/core/java/com/android/server/power/AttentionDetector.java
+++ b/services/core/java/com/android/server/power/AttentionDetector.java
@@ -161,7 +161,7 @@
context.getContentResolver().registerContentObserver(Settings.System.getUriFor(
Settings.System.ADAPTIVE_SLEEP),
- false, new ContentObserver(new Handler()) {
+ false, new ContentObserver(new Handler(context.getMainLooper())) {
@Override
public void onChange(boolean selfChange) {
updateEnabledFromSettings(context);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index cfd3ae6..aa49ba6 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -2724,6 +2724,14 @@
return true;
}
}
+
+ if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE
+ && mDisplayPowerRequest.dozeScreenState == Display.STATE_ON) {
+ // Although we are in DOZE and would normally allow the device to suspend,
+ // the doze service has explicitly requested the display to remain in the ON
+ // state which means we should hold the display suspend blocker.
+ return true;
+ }
if (mScreenBrightnessBoostInProgress) {
return true;
}
@@ -4858,7 +4866,8 @@
}
}
- private final class LocalService extends PowerManagerInternal {
+ @VisibleForTesting
+ final class LocalService extends PowerManagerInternal {
@Override
public void setScreenBrightnessOverrideFromWindowManager(int screenBrightness) {
if (screenBrightness < PowerManager.BRIGHTNESS_DEFAULT
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 8a9dfc7..747837b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1462,16 +1462,18 @@
@Nullable IRecentsAnimationRunner recentsAnimationRunner) {
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "startRecentsActivity()");
final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
final ComponentName recentsComponent = mRecentTasks.getRecentsComponent();
final int recentsUid = mRecentTasks.getRecentsComponentUid();
+ final WindowProcessController caller = getProcessController(callingPid, callingUid);
// Start a new recents animation
final RecentsAnimation anim = new RecentsAnimation(this, mStackSupervisor,
getActivityStartController(), mWindowManager, intent, recentsComponent,
- recentsUid, callingPid);
+ recentsUid, caller);
if (recentsAnimationRunner == null) {
anim.preloadRecentsActivity();
} else {
@@ -4650,7 +4652,7 @@
public void registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition) {
mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
"registerRemoteAnimations");
- definition.setCallingPid(Binder.getCallingPid());
+ definition.setCallingPidUid(Binder.getCallingPid(), Binder.getCallingUid());
synchronized (mGlobalLock) {
final ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r == null) {
@@ -4670,7 +4672,7 @@
RemoteAnimationAdapter adapter) {
mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
"registerRemoteAnimationForNextActivityStart");
- adapter.setCallingPid(Binder.getCallingPid());
+ adapter.setCallingPidUid(Binder.getCallingPid(), Binder.getCallingUid());
synchronized (mGlobalLock) {
final long origId = Binder.clearCallingIdentity();
try {
@@ -4687,7 +4689,7 @@
RemoteAnimationDefinition definition) {
mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
"registerRemoteAnimations");
- definition.setCallingPid(Binder.getCallingPid());
+ definition.setCallingPidUid(Binder.getCallingPid(), Binder.getCallingUid());
synchronized (mGlobalLock) {
final ActivityDisplay display = mRootActivityContainer.getActivityDisplay(displayId);
if (display == null) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 6c577e1..f1a9e60 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -206,6 +206,7 @@
boolean removed;
// Information about an application starting window if displayed.
+ // Note: these are de-referenced before the starting window animates away.
StartingData mStartingData;
WindowState startingWindow;
StartingSurface startingSurface;
@@ -1243,6 +1244,21 @@
return true;
}
+ /**
+ * @return {@code true} if starting window is in app's hierarchy.
+ */
+ boolean hasStartingWindow() {
+ if (startingDisplayed || mStartingData != null) {
+ return true;
+ }
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
void addWindow(WindowState w) {
super.addWindow(w);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index a1b8760..e099a4f 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -67,6 +67,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
@@ -137,6 +138,8 @@
import static com.android.server.wm.WindowManagerService.WINDOW_FREEZE_TIMEOUT_DURATION;
import static com.android.server.wm.WindowManagerService.dipToPixel;
import static com.android.server.wm.WindowManagerService.logSurface;
+import static com.android.server.wm.WindowState.EXCLUSION_LEFT;
+import static com.android.server.wm.WindowState.EXCLUSION_RIGHT;
import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
@@ -330,6 +333,8 @@
private final RemoteCallbackList<ISystemGestureExclusionListener>
mSystemGestureExclusionListeners = new RemoteCallbackList<>();
private final Region mSystemGestureExclusion = new Region();
+ private boolean mSystemGestureExclusionWasRestricted = false;
+ private final Region mSystemGestureExclusionUnrestricted = new Region();
private int mSystemGestureExclusionLimit;
/**
@@ -4845,9 +4850,13 @@
//
// In the case where we have no IME target we assign it where it's base layer would
// place it in the AboveAppWindowContainers.
- if (imeTarget != null && !(imeTarget.inSplitScreenWindowingMode()
- || imeTarget.mToken.isAppAnimating())
- && (imeTarget.getSurfaceControl() != null)) {
+ //
+ // Keep IME window in mAboveAppWindowsContainers as long as app's starting window exists
+ // so it get's layered above the starting window.
+ if (imeTarget != null
+ && !(imeTarget.mAppToken != null && imeTarget.mAppToken.hasStartingWindow())
+ && (!(imeTarget.inSplitScreenWindowingMode() || imeTarget.mToken.isAppAnimating())
+ && (imeTarget.getSurfaceControl() != null))) {
mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
// TODO: We need to use an extra level on the app surface to ensure
// this is always above SurfaceView but always below attached window.
@@ -5135,16 +5144,21 @@
return false;
}
- final Region systemGestureExclusion = calculateSystemGestureExclusion();
+ final Region systemGestureExclusion = Region.obtain();
+ mSystemGestureExclusionWasRestricted = calculateSystemGestureExclusion(
+ systemGestureExclusion, mSystemGestureExclusionUnrestricted);
try {
if (mSystemGestureExclusion.equals(systemGestureExclusion)) {
return false;
}
mSystemGestureExclusion.set(systemGestureExclusion);
+ final Region unrestrictedOrNull = mSystemGestureExclusionWasRestricted
+ ? mSystemGestureExclusionUnrestricted : null;
for (int i = mSystemGestureExclusionListeners.beginBroadcast() - 1; i >= 0; --i) {
try {
mSystemGestureExclusionListeners.getBroadcastItem(i)
- .onSystemGestureExclusionChanged(mDisplayId, systemGestureExclusion);
+ .onSystemGestureExclusionChanged(mDisplayId, systemGestureExclusion,
+ unrestrictedOrNull);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to notify SystemGestureExclusionListener", e);
}
@@ -5156,8 +5170,22 @@
}
}
+ /**
+ * Calculates the system gesture exclusion.
+ *
+ * @param outExclusion will be set to the gesture exclusion region
+ * @param outExclusionUnrestricted will be set to the gesture exclusion region without
+ * any restrictions applied.
+ * @return whether any restrictions were applied, i.e. outExclusion and outExclusionUnrestricted
+ * differ.
+ */
@VisibleForTesting
- Region calculateSystemGestureExclusion() {
+ boolean calculateSystemGestureExclusion(Region outExclusion, @Nullable
+ Region outExclusionUnrestricted) {
+ outExclusion.setEmpty();
+ if (outExclusionUnrestricted != null) {
+ outExclusionUnrestricted.setEmpty();
+ }
final Region unhandled = Region.obtain();
unhandled.set(0, 0, mDisplayFrames.mDisplayWidth, mDisplayFrames.mDisplayHeight);
@@ -5166,7 +5194,6 @@
final Rect rightEdge = mInsetsStateController.getSourceProvider(TYPE_RIGHT_GESTURES)
.getSource().getFrame();
- final Region global = Region.obtain();
final Region touchableRegion = Region.obtain();
final Region local = Region.obtain();
final int[] remainingLeftRight =
@@ -5204,28 +5231,39 @@
if (needsGestureExclusionRestrictions(w, mLastDispatchedSystemUiVisibility)) {
// Processes the region along the left edge.
- remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, global, leftEdge,
- remainingLeftRight[0]);
+ remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
+ remainingLeftRight[0], w, EXCLUSION_LEFT);
// Processes the region along the right edge.
- remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, global, rightEdge,
- remainingLeftRight[1]);
+ remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, outExclusion, rightEdge,
+ remainingLeftRight[1], w, EXCLUSION_RIGHT);
// Adds the middle (unrestricted area)
final Region middle = Region.obtain(local);
middle.op(leftEdge, Op.DIFFERENCE);
middle.op(rightEdge, Op.DIFFERENCE);
- global.op(middle, Op.UNION);
+ outExclusion.op(middle, Op.UNION);
middle.recycle();
} else {
- global.op(local, Op.UNION);
+ boolean loggable = needsGestureExclusionRestrictions(w, 0 /* lastSysUiVis */);
+ if (loggable) {
+ addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
+ Integer.MAX_VALUE, w, EXCLUSION_LEFT);
+ addToGlobalAndConsumeLimit(local, outExclusion, rightEdge,
+ Integer.MAX_VALUE, w, EXCLUSION_RIGHT);
+ }
+ outExclusion.op(local, Op.UNION);
+ }
+ if (outExclusionUnrestricted != null) {
+ outExclusionUnrestricted.op(local, Op.UNION);
}
unhandled.op(touchableRegion, Op.DIFFERENCE);
}, true /* topToBottom */);
local.recycle();
touchableRegion.recycle();
unhandled.recycle();
- return global;
+ return remainingLeftRight[0] < mSystemGestureExclusionLimit
+ || remainingLeftRight[1] < mSystemGestureExclusionLimit;
}
/**
@@ -5243,31 +5281,57 @@
}
/**
+ * @return Whether gesture exclusion area should be logged for the given window
+ */
+ static boolean logsGestureExclusionRestrictions(WindowState win) {
+ if (win.mWmService.mSystemGestureExclusionLogDebounceTimeoutMillis <= 0) {
+ return false;
+ }
+ final WindowManager.LayoutParams attrs = win.getAttrs();
+ final int type = attrs.type;
+ return type != TYPE_WALLPAPER
+ && type != TYPE_APPLICATION_STARTING
+ && type != TYPE_NAVIGATION_BAR
+ && (attrs.flags & FLAG_NOT_TOUCHABLE) == 0
+ && needsGestureExclusionRestrictions(win, 0 /* sysUiVisibility */)
+ && win.getDisplayContent().mDisplayPolicy.hasSideGestures();
+ }
+
+ /**
* Adds a local gesture exclusion area to the global area while applying a limit per edge.
*
* @param local The gesture exclusion area to add.
* @param global The destination.
* @param edge Only processes the part in that region.
* @param limit How much limit in pixels we have.
- * @return How much of the limit are remaining.
+ * @param win The WindowState that is being processed
+ * @param side The side that is being processed, either {@link WindowState#EXCLUSION_LEFT} or
+ * {@link WindowState#EXCLUSION_RIGHT}
+ * @return How much of the limit is remaining.
*/
private static int addToGlobalAndConsumeLimit(Region local, Region global, Rect edge,
- int limit) {
+ int limit, WindowState win, int side) {
final Region r = Region.obtain(local);
r.op(edge, Op.INTERSECT);
final int[] remaining = {limit};
+ final int[] requestedExclusion = {0};
forEachRectReverse(r, rect -> {
if (remaining[0] <= 0) {
return;
}
final int height = rect.height();
+ requestedExclusion[0] += height;
if (height > remaining[0]) {
rect.top = rect.bottom - remaining[0];
}
remaining[0] -= height;
global.op(rect, Op.UNION);
});
+
+ final int grantedExclusion = limit - remaining[0];
+ win.setLastExclusionHeights(side, requestedExclusion[0], grantedExclusion);
+
r.recycle();
return remaining[0];
}
@@ -5282,10 +5346,13 @@
}
if (!changed) {
+ final Region unrestrictedOrNull = mSystemGestureExclusionWasRestricted
+ ? mSystemGestureExclusionUnrestricted : null;
// If updateSystemGestureExclusion changed the exclusion, it will already have
// notified the listener. Otherwise, we'll do it here.
try {
- listener.onSystemGestureExclusionChanged(mDisplayId, mSystemGestureExclusion);
+ listener.onSystemGestureExclusionChanged(mDisplayId, mSystemGestureExclusion,
+ unrestrictedOrNull);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to notify SystemGestureExclusionListener during register", e);
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index cf87203..ed7dbd0 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -478,9 +478,10 @@
@Override
public void onSwipeFromRight() {
- final Region excludedRegion;
+ final Region excludedRegion = Region.obtain();
synchronized (mLock) {
- excludedRegion = mDisplayContent.calculateSystemGestureExclusion();
+ mDisplayContent.calculateSystemGestureExclusion(
+ excludedRegion, null /* outUnrestricted */);
}
final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
|| mNavigationBarPosition == NAV_BAR_RIGHT;
@@ -488,13 +489,15 @@
&& !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) {
requestTransientBars(mNavigationBar);
}
+ excludedRegion.recycle();
}
@Override
public void onSwipeFromLeft() {
- final Region excludedRegion;
+ final Region excludedRegion = Region.obtain();
synchronized (mLock) {
- excludedRegion = mDisplayContent.calculateSystemGestureExclusion();
+ mDisplayContent.calculateSystemGestureExclusion(
+ excludedRegion, null /* outUnrestricted */);
}
final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
|| mNavigationBarPosition == NAV_BAR_LEFT;
@@ -502,6 +505,7 @@
&& !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) {
requestTransientBars(mNavigationBar);
}
+ excludedRegion.recycle();
}
@Override
@@ -674,6 +678,10 @@
return mHasStatusBar;
}
+ boolean hasSideGestures() {
+ return mHasNavigationBar && mSideGestureInset > 0;
+ }
+
public boolean navigationBarCanMove() {
return mNavigationBarCanMove;
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 0a3e7a4..036bef7 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -33,6 +33,7 @@
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_TOP;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS;
+import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.content.ComponentName;
import android.content.Intent;
@@ -60,7 +61,7 @@
private final Intent mTargetIntent;
private final ComponentName mRecentsComponent;
private final int mRecentsUid;
- private final int mCallingPid;
+ private final @Nullable WindowProcessController mCaller;
private final int mUserId;
private final int mTargetActivityType;
@@ -76,7 +77,8 @@
RecentsAnimation(ActivityTaskManagerService atm, ActivityStackSupervisor stackSupervisor,
ActivityStartController activityStartController, WindowManagerService wm,
- Intent targetIntent, ComponentName recentsComponent, int recentsUid, int callingPid) {
+ Intent targetIntent, ComponentName recentsComponent, int recentsUid,
+ @Nullable WindowProcessController caller) {
mService = atm;
mStackSupervisor = stackSupervisor;
mDefaultDisplay = mService.mRootActivityContainer.getDefaultDisplay();
@@ -85,7 +87,7 @@
mTargetIntent = targetIntent;
mRecentsComponent = recentsComponent;
mRecentsUid = recentsUid;
- mCallingPid = callingPid;
+ mCaller = caller;
mUserId = atm.getCurrentUserId();
mTargetActivityType = targetIntent.getComponent() != null
&& recentsComponent.equals(targetIntent.getComponent())
@@ -190,7 +192,9 @@
mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(mTargetIntent);
- mService.mH.post(() -> mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, true));
+ if (mCaller != null) {
+ mCaller.setRunningRecentsAnimation(true);
+ }
mWindowManager.deferSurfaceLayout();
try {
@@ -286,8 +290,9 @@
mService.stopAppSwitches();
}
- mService.mH.post(
- () -> mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, false));
+ if (mCaller != null) {
+ mCaller.setRunningRecentsAnimation(false);
+ }
mWindowManager.inSurfaceTransaction(() -> {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER,
@@ -453,7 +458,7 @@
/**
* Called only when the animation should be canceled prior to starting.
*/
- private void notifyAnimationCancelBeforeStart(IRecentsAnimationRunner recentsAnimationRunner) {
+ static void notifyAnimationCancelBeforeStart(IRecentsAnimationRunner recentsAnimationRunner) {
try {
recentsAnimationRunner.onAnimationCanceled(false /* deferredWithScreenshot */);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index b4bfedd..a1bc406 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -129,7 +129,7 @@
writeStartDebugStatement();
}
});
- sendRunningRemoteAnimation(true);
+ setRunningRemoteAnimation(true);
}
void cancelAnimation(String reason) {
@@ -216,7 +216,7 @@
mService.closeSurfaceTransaction("RemoteAnimationController#finished");
}
}
- sendRunningRemoteAnimation(false);
+ setRunningRemoteAnimation(false);
if (DEBUG_REMOTE_ANIMATIONS) Slog.i(TAG, "Finishing remote animation");
}
@@ -235,12 +235,18 @@
}
}
- private void sendRunningRemoteAnimation(boolean running) {
+ private void setRunningRemoteAnimation(boolean running) {
final int pid = mRemoteAnimationAdapter.getCallingPid();
+ final int uid = mRemoteAnimationAdapter.getCallingUid();
if (pid == 0) {
throw new RuntimeException("Calling pid of remote animation was null");
}
- mService.sendSetRunningRemoteAnimation(pid, running);
+ final WindowProcessController wpc = mService.mAtmService.getProcessController(pid, uid);
+ if (wpc == null) {
+ Slog.w(TAG, "Unable to find process with pid=" + pid + " uid=" + uid);
+ return;
+ }
+ wpc.setRunningRemoteAnimation(running);
}
private void linkToDeathOfRunner() throws RemoteException {
@@ -417,7 +423,7 @@
mHandler.removeCallbacks(mTimeoutRunnable);
releaseFinishedCallback();
invokeAnimationCancelled();
- sendRunningRemoteAnimation(false);
+ setRunningRemoteAnimation(false);
}
}
diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java
index ac90283..a7b5368 100644
--- a/services/core/java/com/android/server/wm/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java
@@ -122,17 +122,20 @@
if (mOriginalOptions != null) {
checkPermissions(intent, aInfo, callerApp, supervisor, mOriginalOptions,
mOriginalCallingPid, mOriginalCallingUid);
- setCallingPidForRemoteAnimationAdapter(mOriginalOptions, mOriginalCallingPid);
+ setCallingPidUidForRemoteAnimationAdapter(mOriginalOptions, mOriginalCallingPid,
+ mOriginalCallingUid);
}
if (mCallerOptions != null) {
checkPermissions(intent, aInfo, callerApp, supervisor, mCallerOptions,
mRealCallingPid, mRealCallingUid);
- setCallingPidForRemoteAnimationAdapter(mCallerOptions, mRealCallingPid);
+ setCallingPidUidForRemoteAnimationAdapter(mCallerOptions, mRealCallingPid,
+ mRealCallingUid);
}
return mergeActivityOptions(mOriginalOptions, mCallerOptions);
}
- private void setCallingPidForRemoteAnimationAdapter(ActivityOptions options, int callingPid) {
+ private void setCallingPidUidForRemoteAnimationAdapter(ActivityOptions options,
+ int callingPid, int callingUid) {
final RemoteAnimationAdapter adapter = options.getRemoteAnimationAdapter();
if (adapter == null) {
return;
@@ -141,7 +144,7 @@
Slog.wtf(TAG, "Safe activity options constructed after clearing calling id");
return;
}
- adapter.setCallingPid(callingPid);
+ adapter.setCallingPidUid(callingPid, callingUid);
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 14585c5..19fbfed 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 @@
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 57f402c..c108752 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -34,6 +34,7 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE;
import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP;
+import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -847,6 +848,16 @@
int mSystemGestureExclusionLimitDp;
boolean mSystemGestureExcludedByPreQStickyImmersive;
+ /**
+ * The minimum duration between gesture exclusion logging for a given window in
+ * milliseconds.
+ *
+ * Events that happen in-between will be silently dropped.
+ *
+ * A non-positive value disables logging.
+ */
+ public long mSystemGestureExclusionLogDebounceTimeoutMillis;
+
public interface WindowChangeListener {
public void windowsChanged();
public void focusChanged();
@@ -1146,6 +1157,9 @@
mSystemGestureExclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
+ mSystemGestureExclusionLogDebounceTimeoutMillis =
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, 0);
mSystemGestureExcludedByPreQStickyImmersive =
DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, false);
@@ -1163,6 +1177,10 @@
mSystemGestureExcludedByPreQStickyImmersive = excludedByPreQSticky;
mRoot.forAllDisplays(DisplayContent::updateSystemGestureExclusionLimit);
}
+
+ mSystemGestureExclusionLogDebounceTimeoutMillis =
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, 0);
}
});
@@ -4556,7 +4574,6 @@
public static final int SEAMLESS_ROTATION_TIMEOUT = 54;
public static final int RESTORE_POINTER_ICON = 55;
public static final int SET_HAS_OVERLAY_UI = 58;
- public static final int SET_RUNNING_REMOTE_ANIMATION = 59;
public static final int ANIMATION_FAILSAFE = 60;
public static final int RECOMPUTE_FOCUS = 61;
public static final int ON_POINTER_DOWN_OUTSIDE_FOCUS = 62;
@@ -4935,10 +4952,6 @@
mAmInternal.setHasOverlayUi(msg.arg1, msg.arg2 == 1);
break;
}
- case SET_RUNNING_REMOTE_ANIMATION: {
- mAmInternal.setRunningRemoteAnimation(msg.arg1, msg.arg2 == 1);
- break;
- }
case ANIMATION_FAILSAFE: {
synchronized (mGlobalLock) {
if (mRecentsAnimationController != null) {
@@ -7625,11 +7638,6 @@
return mSurfaceBuilderFactory.make(s);
}
- void sendSetRunningRemoteAnimation(int pid, boolean runningRemoteAnimation) {
- mH.obtainMessage(H.SET_RUNNING_REMOTE_ANIMATION, pid, runningRemoteAnimation ? 1 : 0)
- .sendToTarget();
- }
-
void startSeamlessRotation() {
// We are careful to reset this in case a window was removed before it finished
// seamless rotation.
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index b6960f0..4cb546f 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -56,6 +56,7 @@
import android.util.Log;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
+import android.view.IRemoteAnimationRunner;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.HeavyWeightSwitcherActivity;
@@ -176,6 +177,12 @@
// Registered display id as a listener to override config change
private int mDisplayId;
+ /** Whether our process is currently running a {@link RecentsAnimation} */
+ private boolean mRunningRecentsAnimation;
+
+ /** Whether our process is currently running a {@link IRemoteAnimationRunner} */
+ private boolean mRunningRemoteAnimation;
+
public WindowProcessController(ActivityTaskManagerService atm, ApplicationInfo info,
String name, int uid, int userId, Object owner, WindowProcessListener listener) {
mInfo = info;
@@ -1079,6 +1086,30 @@
}
}
+ void setRunningRecentsAnimation(boolean running) {
+ if (mRunningRecentsAnimation == running) {
+ return;
+ }
+ mRunningRecentsAnimation = running;
+ updateRunningRemoteOrRecentsAnimation();
+ }
+
+ void setRunningRemoteAnimation(boolean running) {
+ if (mRunningRemoteAnimation == running) {
+ return;
+ }
+ mRunningRemoteAnimation = running;
+ updateRunningRemoteOrRecentsAnimation();
+ }
+
+ private void updateRunningRemoteOrRecentsAnimation() {
+
+ // Posting on handler so WM lock isn't held when we call into AM.
+ mAtm.mH.sendMessage(PooledLambda.obtainMessage(
+ WindowProcessListener::setRunningRemoteAnimation, mListener,
+ mRunningRecentsAnimation || mRunningRemoteAnimation));
+ }
+
@Override
public String toString() {
return mOwner != null ? mOwner.toString() : null;
diff --git a/services/core/java/com/android/server/wm/WindowProcessListener.java b/services/core/java/com/android/server/wm/WindowProcessListener.java
index 527d54a..23d7a6a 100644
--- a/services/core/java/com/android/server/wm/WindowProcessListener.java
+++ b/services/core/java/com/android/server/wm/WindowProcessListener.java
@@ -17,6 +17,8 @@
package com.android.server.wm;
import android.util.proto.ProtoOutputStream;
+import android.view.IRemoteAnimationRunner;
+import android.view.RemoteAnimationAdapter;
/**
* Interface used by the owner/creator of a process that owns windows to listen to changes from the
@@ -60,4 +62,14 @@
/** App died :(...oh well */
void appDied();
void writeToProto(ProtoOutputStream proto, long fieldId);
+
+ /**
+ * Sets if the process is currently running a remote animation, which is taken a signal for
+ * determining oom adjustment and scheduling behavior.
+ *
+ * @param runningRemoteAnimation True if the process is running a remote animation, false
+ * otherwise.
+ * @see RemoteAnimationAdapter
+ */
+ void setRunningRemoteAnimation(boolean runningRemoteAnimation);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f68d7c0..18cdc94 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -20,6 +20,8 @@
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.OP_NONE;
+import static android.app.WindowConfiguration.isSplitScreenWindowingMode;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.os.PowerManager.DRAW_WAKE_LOCK;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -80,6 +82,7 @@
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
import static com.android.server.wm.AnimationSpecProto.MOVE;
+import static com.android.server.wm.DisplayContent.logsGestureExclusionRestrictions;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
@@ -174,6 +177,7 @@
import android.util.DisplayMetrics;
import android.util.MergedConfiguration;
import android.util.Slog;
+import android.util.StatsLog;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
@@ -227,6 +231,9 @@
// to capture touch events in that area.
static final int RESIZE_HANDLE_WIDTH_IN_DP = 30;
+ static final int EXCLUSION_LEFT = 0;
+ static final int EXCLUSION_RIGHT = 1;
+
final WindowManagerPolicy mPolicy;
final Context mContext;
final Session mSession;
@@ -397,6 +404,13 @@
*/
private final List<Rect> mExclusionRects = new ArrayList<>();
+ // 0 = left, 1 = right
+ private final int[] mLastRequestedExclusionHeight = {0, 0};
+ private final int[] mLastGrantedExclusionHeight = {0, 0};
+ private final long[] mLastExclusionLogUptimeMillis = {0, 0};
+
+ private boolean mLastShownChangedReported;
+
// If a window showing a wallpaper: the requested offset for the
// wallpaper; if a wallpaper window: the currently applied offset.
float mWallpaperX = -1;
@@ -679,6 +693,20 @@
&& mAppToken != null && mAppToken.mTargetSdk < Build.VERSION_CODES.Q;
}
+ void setLastExclusionHeights(int side, int requested, int granted) {
+ boolean changed = mLastGrantedExclusionHeight[side] != granted
+ || mLastRequestedExclusionHeight[side] != requested;
+
+ if (changed) {
+ if (mLastShownChangedReported) {
+ logExclusionRestrictions(side);
+ }
+
+ mLastGrantedExclusionHeight[side] = granted;
+ mLastRequestedExclusionHeight[side] = requested;
+ }
+ }
+
interface PowerManagerWrapper {
void wakeUp(long time, @WakeReason int reason, String details);
@@ -2957,6 +2985,49 @@
mAnimatingExit = false;
}
+ void onSurfaceShownChanged(boolean shown) {
+ if (mLastShownChangedReported == shown) {
+ return;
+ }
+ mLastShownChangedReported = shown;
+
+ if (shown) {
+ initExclusionRestrictions();
+ } else {
+ logExclusionRestrictions(EXCLUSION_LEFT);
+ logExclusionRestrictions(EXCLUSION_RIGHT);
+ }
+ }
+
+ private void logExclusionRestrictions(int side) {
+ if (!logsGestureExclusionRestrictions(this)
+ || SystemClock.uptimeMillis() < mLastExclusionLogUptimeMillis[side]
+ + mWmService.mSystemGestureExclusionLogDebounceTimeoutMillis) {
+ // Drop the log if we have just logged; this is okay, because what we would have logged
+ // was true only for a short duration.
+ return;
+ }
+
+ final long now = SystemClock.uptimeMillis();
+ final long duration = now - mLastExclusionLogUptimeMillis[side];
+ mLastExclusionLogUptimeMillis[side] = now;
+
+ final int requested = mLastRequestedExclusionHeight[side];
+ final int granted = mLastGrantedExclusionHeight[side];
+
+ StatsLog.write(StatsLog.EXCLUSION_RECT_STATE_CHANGED,
+ mAttrs.packageName, requested, requested - granted /* rejected */,
+ side + 1 /* Sides are 1-indexed in atoms.proto */,
+ (getConfiguration().orientation == ORIENTATION_LANDSCAPE),
+ isSplitScreenWindowingMode(getWindowingMode()), (int) duration);
+ }
+
+ private void initExclusionRestrictions() {
+ final long now = SystemClock.uptimeMillis();
+ mLastExclusionLogUptimeMillis[EXCLUSION_LEFT] = now;
+ mLastExclusionLogUptimeMillis[EXCLUSION_RIGHT] = now;
+ }
+
@Override
public boolean isDefaultDisplay() {
final DisplayContent displayContent = getDisplayContent();
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index bef0f81..53bbd70 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -507,6 +507,8 @@
mService.updateNonSystemOverlayWindowsVisibilityIfNeeded(mAnimator.mWin, surfaceShown);
+ mAnimator.mWin.onSurfaceShownChanged(surfaceShown);
+
if (mWindowSession != null) {
mWindowSession.onWindowSurfaceVisibilityChanged(this, mSurfaceShown, mWindowType);
}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 1bda412..88de250 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -23,7 +23,10 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
@@ -59,6 +62,7 @@
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
+import android.view.Display;
import androidx.test.InstrumentationRegistry;
@@ -157,6 +161,10 @@
mResourcesSpy = spy(mContextSpy.getResources());
when(mContextSpy.getResources()).thenReturn(mResourcesSpy);
+ when(mDisplayManagerInternalMock.requestPowerState(any(), anyBoolean())).thenReturn(true);
+ }
+
+ private PowerManagerService createService() {
mService = new PowerManagerService(mContextSpy, new Injector() {
@Override
Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
@@ -166,7 +174,7 @@
@Override
SuspendBlocker createSuspendBlocker(PowerManagerService service, String name) {
- return mock(SuspendBlocker.class);
+ return super.createSuspendBlocker(service, name);
}
@Override
@@ -191,6 +199,7 @@
return mAmbientDisplayConfigurationMock;
}
});
+ return mService;
}
@After
@@ -262,6 +271,7 @@
@Test
public void testUpdatePowerScreenPolicy_UpdateDisplayPowerRequest() {
+ createService();
mService.updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
assertThat(mDisplayPowerRequest.lowPowerMode).isEqualTo(BATTERY_SAVER_ENABLED);
assertThat(mDisplayPowerRequest.screenLowPowerBrightnessFactor)
@@ -270,6 +280,7 @@
@Test
public void testGetLastShutdownReasonInternal() {
+ createService();
SystemProperties.set(TEST_LAST_REBOOT_PROPERTY, "shutdown,thermal");
int reason = mService.getLastShutdownReasonInternal(TEST_LAST_REBOOT_PROPERTY);
SystemProperties.set(TEST_LAST_REBOOT_PROPERTY, "");
@@ -278,6 +289,7 @@
@Test
public void testGetDesiredScreenPolicy_WithVR() throws Exception {
+ createService();
// Brighten up the screen
mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, PowerManager.WAKE_REASON_UNKNOWN, 0);
assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
@@ -307,11 +319,13 @@
@Test
public void testWakefulnessAwake_InitialValue() throws Exception {
+ createService();
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
}
@Test
public void testWakefulnessSleep_NoDozeSleepFlag() throws Exception {
+ createService();
// Start with AWAKE state
startSystem();
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
@@ -324,6 +338,7 @@
@Test
public void testWakefulnessAwake_AcquireCausesWakeup() throws Exception {
+ createService();
startSystem();
forceSleep();
@@ -355,6 +370,7 @@
@Test
public void testWakefulnessAwake_IPowerManagerWakeUp() throws Exception {
+ createService();
startSystem();
forceSleep();
mService.getBinderServiceInstance().wakeUp(SystemClock.uptimeMillis(),
@@ -369,6 +385,8 @@
@Test
public void testWakefulnessAwake_ShouldWakeUpWhenPluggedIn() throws Exception {
boolean powerState;
+
+ createService();
startSystem();
forceSleep();
@@ -444,6 +462,7 @@
@Test
public void testWakefulnessDoze_goToSleep() throws Exception {
+ createService();
// Start with AWAKE state
startSystem();
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
@@ -457,6 +476,7 @@
@Test
public void testWasDeviceIdleFor_true() {
int interval = 1000;
+ createService();
mService.onUserActivity();
SystemClock.sleep(interval + 1 /* just a little more */);
assertThat(mService.wasDeviceIdleForInternal(interval)).isTrue();
@@ -465,12 +485,14 @@
@Test
public void testWasDeviceIdleFor_false() {
int interval = 1000;
+ createService();
mService.onUserActivity();
assertThat(mService.wasDeviceIdleForInternal(interval)).isFalse();
}
@Test
public void testForceSuspend_putsDeviceToSleep() {
+ createService();
mService.systemReady(null);
mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
@@ -497,6 +519,8 @@
final int flags = PowerManager.PARTIAL_WAKE_LOCK;
final String pkg = mContextSpy.getOpPackageName();
+ createService();
+
// Set up the Notification mock to keep track of the wakelocks that are currently
// active or disabled. We'll use this to verify that wakelocks are disabled when
// they should be.
@@ -541,7 +565,54 @@
@Test
public void testForceSuspend_forceSuspendFailurePropogated() {
+ createService();
when(mNativeWrapperMock.nativeForceSuspend()).thenReturn(false);
assertThat(mService.getBinderServiceInstance().forceSuspend()).isFalse();
}
+
+ @Test
+ public void testSetDozeOverrideFromDreamManager_triggersSuspendBlocker() throws Exception {
+ final String suspendBlockerName = "PowerManagerService.Display";
+ final String tag = "acq_causes_wakeup";
+ final String packageName = "pkg.name";
+ final IBinder token = new Binder();
+
+ final boolean[] isAcquired = new boolean[1];
+ doAnswer(inv -> {
+ if (suspendBlockerName.equals(inv.getArguments()[0])) {
+ isAcquired[0] = false;
+ }
+ return null;
+ }).when(mNativeWrapperMock).nativeReleaseSuspendBlocker(any());
+
+ doAnswer(inv -> {
+ if (suspendBlockerName.equals(inv.getArguments()[0])) {
+ isAcquired[0] = true;
+ }
+ return null;
+ }).when(mNativeWrapperMock).nativeAcquireSuspendBlocker(any());
+
+ // Need to create the service after we stub the mocks for this test because some of the
+ // mocks are used during the constructor.
+ createService();
+
+ // Start with AWAKE state
+ startSystem();
+ assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
+ assertTrue(isAcquired[0]);
+
+ // Take a nap and verify we no longer hold the blocker
+ int flags = PowerManager.DOZE_WAKE_LOCK;
+ mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
+ null /* workSource */, null /* historyTag */);
+ mService.getBinderServiceInstance().goToSleep(SystemClock.uptimeMillis(),
+ PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0);
+ assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_DOZING);
+ assertFalse(isAcquired[0]);
+
+ // Override the display state by DreamManager and verify is reacquires the blocker.
+ mService.getLocalServiceInstance()
+ .setDozeOverrideFromDreamManager(Display.STATE_ON, PowerManager.BRIGHTNESS_DEFAULT);
+ assertTrue(isAcquired[0]);
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index f602418..d1dc382 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -207,7 +207,7 @@
final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
runner, 100, 50, true /* changeNeedsSnapshot */);
// RemoteAnimationController will tracking RemoteAnimationAdapter's caller with calling pid.
- adapter.setCallingPid(123);
+ adapter.setCallingPidUid(123, 456);
// Simulate activity finish flows to prepare app transition & set visibility,
// make sure transition is set as expected.
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 7f35dac..d9566a3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -504,6 +504,21 @@
assertEquals(stackBounds, mToken.getAnimationBounds(STACK_CLIP_BEFORE_ANIM));
}
+ @Test
+ public void testHasStartingWindow() {
+ final WindowManager.LayoutParams attrs =
+ new WindowManager.LayoutParams(TYPE_APPLICATION_STARTING);
+ final WindowTestUtils.TestWindowState startingWindow = createWindowState(attrs, mToken);
+ mToken.startingDisplayed = true;
+ mToken.addWindow(startingWindow);
+ assertTrue("Starting window should be present", mToken.hasStartingWindow());
+ mToken.startingDisplayed = false;
+ assertTrue("Starting window should be present", mToken.hasStartingWindow());
+
+ mToken.removeChild(startingWindow);
+ assertFalse("Starting window should not be present", mToken.hasStartingWindow());
+ }
+
private void assertHasStartingWindow(AppWindowToken atoken) {
assertNotNull(atoken.startingSurface);
assertNotNull(atoken.mStartingData);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 7cd097e..6889086 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -756,7 +756,8 @@
final ISystemGestureExclusionListener.Stub verifier =
new ISystemGestureExclusionListener.Stub() {
@Override
- public void onSystemGestureExclusionChanged(int displayId, Region actual) {
+ public void onSystemGestureExclusionChanged(int displayId, Region actual,
+ Region unrestricted) {
Region expected = Region.obtain();
expected.set(10, 20, 30, 40);
assertEquals(expected, actual);
@@ -790,7 +791,14 @@
final Region expected = Region.obtain();
expected.set(20, 30, 40, 50);
- assertEquals(expected, dc.calculateSystemGestureExclusion());
+ assertEquals(expected, calculateSystemGestureExclusion(dc));
+ }
+
+ private Region calculateSystemGestureExclusion(DisplayContent dc) {
+ Region out = Region.obtain();
+ Region unrestricted = Region.obtain();
+ dc.calculateSystemGestureExclusion(out, unrestricted);
+ return out;
}
@Test
@@ -814,7 +822,7 @@
win2.setHasSurface(true);
final Region expected = Region.obtain();
- assertEquals(expected, dc.calculateSystemGestureExclusion());
+ assertEquals(expected, calculateSystemGestureExclusion(dc));
}
@Test
@@ -839,7 +847,7 @@
final Region expected = Region.obtain();
expected.set(dc.getBounds());
- assertEquals(expected, dc.calculateSystemGestureExclusion());
+ assertEquals(expected, calculateSystemGestureExclusion(dc));
win.setHasSurface(false);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index cb74c3e..74791e2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -79,7 +79,7 @@
when(mMockRunner.asBinder()).thenReturn(new Binder());
mAdapter = new RemoteAnimationAdapter(mMockRunner, 100, 50, true /* changeNeedsSnapshot */);
- mAdapter.setCallingPid(123);
+ mAdapter.setCallingPidUid(123, 456);
mWm.mH.runWithScissors(() -> mHandler = new TestHandler(null, mClock), 0);
mController = new RemoteAnimationController(mWm, mAdapter, mHandler);
}
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 f918149..58614c6 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 @@
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/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index a7c84a1..8c56ffa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -23,12 +23,18 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.content.pm.ApplicationInfo;
import android.platform.test.annotations.Presubmit;
+import org.junit.Before;
import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
/**
* Tests for the {@link WindowProcessController} class.
@@ -39,43 +45,89 @@
@Presubmit
public class WindowProcessControllerTests extends ActivityTestsBase {
+ WindowProcessController mWpc;
+ WindowProcessListener mMockListener;
+
+ @Before
+ public void setUp() {
+ mMockListener = mock(WindowProcessListener.class);
+ mWpc = new WindowProcessController(
+ mService, mock(ApplicationInfo.class), null, 0, -1, null, mMockListener);
+ }
+
@Test
public void testDisplayConfigurationListener() {
- final WindowProcessController wpc = new WindowProcessController(
- mService, mock(ApplicationInfo.class), null, 0, -1, null, null);
+
//By default, the process should not listen to any display.
- assertEquals(INVALID_DISPLAY, wpc.getDisplayId());
+ assertEquals(INVALID_DISPLAY, mWpc.getDisplayId());
// Register to display 1 as a listener.
TestActivityDisplay testActivityDisplay1 = createTestActivityDisplayInContainer();
- wpc.registerDisplayConfigurationListenerLocked(testActivityDisplay1);
- assertTrue(testActivityDisplay1.containsListener(wpc));
- assertEquals(testActivityDisplay1.mDisplayId, wpc.getDisplayId());
+ mWpc.registerDisplayConfigurationListenerLocked(testActivityDisplay1);
+ assertTrue(testActivityDisplay1.containsListener(mWpc));
+ assertEquals(testActivityDisplay1.mDisplayId, mWpc.getDisplayId());
// Move to display 2.
TestActivityDisplay testActivityDisplay2 = createTestActivityDisplayInContainer();
- wpc.registerDisplayConfigurationListenerLocked(testActivityDisplay2);
- assertFalse(testActivityDisplay1.containsListener(wpc));
- assertTrue(testActivityDisplay2.containsListener(wpc));
- assertEquals(testActivityDisplay2.mDisplayId, wpc.getDisplayId());
+ mWpc.registerDisplayConfigurationListenerLocked(testActivityDisplay2);
+ assertFalse(testActivityDisplay1.containsListener(mWpc));
+ assertTrue(testActivityDisplay2.containsListener(mWpc));
+ assertEquals(testActivityDisplay2.mDisplayId, mWpc.getDisplayId());
// Null ActivityDisplay will not change anything.
- wpc.registerDisplayConfigurationListenerLocked(null);
- assertTrue(testActivityDisplay2.containsListener(wpc));
- assertEquals(testActivityDisplay2.mDisplayId, wpc.getDisplayId());
+ mWpc.registerDisplayConfigurationListenerLocked(null);
+ assertTrue(testActivityDisplay2.containsListener(mWpc));
+ assertEquals(testActivityDisplay2.mDisplayId, mWpc.getDisplayId());
// Unregister listener will remove the wpc from registered displays.
- wpc.unregisterDisplayConfigurationListenerLocked();
- assertFalse(testActivityDisplay1.containsListener(wpc));
- assertFalse(testActivityDisplay2.containsListener(wpc));
- assertEquals(INVALID_DISPLAY, wpc.getDisplayId());
+ mWpc.unregisterDisplayConfigurationListenerLocked();
+ assertFalse(testActivityDisplay1.containsListener(mWpc));
+ assertFalse(testActivityDisplay2.containsListener(mWpc));
+ assertEquals(INVALID_DISPLAY, mWpc.getDisplayId());
// Unregistration still work even if the display was removed.
- wpc.registerDisplayConfigurationListenerLocked(testActivityDisplay1);
- assertEquals(testActivityDisplay1.mDisplayId, wpc.getDisplayId());
+ mWpc.registerDisplayConfigurationListenerLocked(testActivityDisplay1);
+ assertEquals(testActivityDisplay1.mDisplayId, mWpc.getDisplayId());
mRootActivityContainer.removeChild(testActivityDisplay1);
- wpc.unregisterDisplayConfigurationListenerLocked();
- assertEquals(INVALID_DISPLAY, wpc.getDisplayId());
+ mWpc.unregisterDisplayConfigurationListenerLocked();
+ assertEquals(INVALID_DISPLAY, mWpc.getDisplayId());
+ }
+
+ @Test
+ public void testSetRunningRecentsAnimation() {
+ mWpc.setRunningRecentsAnimation(true);
+ mWpc.setRunningRecentsAnimation(false);
+ mService.mH.runWithScissors(() -> {}, 0);
+
+ InOrder orderVerifier = Mockito.inOrder(mMockListener);
+ orderVerifier.verify(mMockListener).setRunningRemoteAnimation(eq(true));
+ orderVerifier.verify(mMockListener).setRunningRemoteAnimation(eq(false));
+ }
+
+ @Test
+ public void testSetRunningRemoteAnimation() {
+ mWpc.setRunningRemoteAnimation(true);
+ mWpc.setRunningRemoteAnimation(false);
+ mService.mH.runWithScissors(() -> {}, 0);
+
+ InOrder orderVerifier = Mockito.inOrder(mMockListener);
+ orderVerifier.verify(mMockListener).setRunningRemoteAnimation(eq(true));
+ orderVerifier.verify(mMockListener).setRunningRemoteAnimation(eq(false));
+ }
+
+ @Test
+ public void testSetRunningBothAnimations() {
+ mWpc.setRunningRemoteAnimation(true);
+ mWpc.setRunningRecentsAnimation(true);
+
+ mWpc.setRunningRecentsAnimation(false);
+ mWpc.setRunningRemoteAnimation(false);
+ mService.mH.runWithScissors(() -> {}, 0);
+
+ InOrder orderVerifier = Mockito.inOrder(mMockListener);
+ orderVerifier.verify(mMockListener, times(3)).setRunningRemoteAnimation(eq(true));
+ orderVerifier.verify(mMockListener, times(1)).setRunningRemoteAnimation(eq(false));
+ orderVerifier.verifyNoMoreInteractions();
}
private TestActivityDisplay createTestActivityDisplayInContainer() {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index cea4faf..56a6d61 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -468,6 +468,14 @@
"notify_handover_video_from_wifi_to_lte_bool";
/**
+ * Flag specifying whether the carrier supports merging a RTT call with a voice call,
+ * downgrading the call in the process.
+ * @hide
+ */
+ public static final String KEY_ALLOW_MERGING_RTT_CALLS_BOOL =
+ "allow_merging_rtt_calls_bool";
+
+ /**
* Flag specifying whether the carrier wants to notify the user when a VT call has been handed
* over from LTE to WIFI.
* <p>
@@ -3057,6 +3065,7 @@
sDefaults.putBoolean(KEY_CARRIER_VOLTE_AVAILABLE_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_VT_AVAILABLE_BOOL, false);
sDefaults.putBoolean(KEY_NOTIFY_HANDOVER_VIDEO_FROM_WIFI_TO_LTE_BOOL, false);
+ sDefaults.putBoolean(KEY_ALLOW_MERGING_RTT_CALLS_BOOL, false);
sDefaults.putBoolean(KEY_NOTIFY_HANDOVER_VIDEO_FROM_LTE_TO_WIFI_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORT_DOWNGRADE_VT_TO_AUDIO_BOOL, true);
sDefaults.putString(KEY_DEFAULT_VM_NUMBER_STRING, "");
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 976cd0c..7477c3e 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2417,6 +2417,10 @@
* registered operator or the cell nearby, if available.
* .
* <p>
+ * Note: In multi-sim, this returns a shared emergency network country iso from other
+ * subscription if the subscription used to create the TelephonyManager doesn't camp on
+ * a network due to some reason (e.g. pin/puk locked), or sim is absent in the corresponding
+ * slot.
* Note: Result may be unreliable on CDMA networks (use {@link #getPhoneType()} to determine
* if on a CDMA network).
*/
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
index 511adf6..19d0724 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -22,6 +22,7 @@
import android.hardware.radio.V1_4.EmergencyServiceCategory;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.CarrierConfigManager;
import android.telephony.PhoneNumberUtils;
import android.telephony.Rlog;
@@ -301,6 +302,9 @@
* The character in the number string is only the dial pad
* character('0'-'9', '*', '+', or '#'). For example: 911.
*
+ * If the number starts with carrier prefix, the carrier prefix is configured in
+ * {@link CarrierConfigManager#KEY_EMERGENCY_NUMBER_PREFIX_STRING_ARRAY}.
+ *
* @return the dialing number.
*/
public @NonNull String getNumber() {
diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
index a1bea4d..d4ed923 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.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.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 @@
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);