Merge "Use an iterator in removeChannelNotifications rather than index." into sc-dev
diff --git a/core/api/current.txt b/core/api/current.txt
index b40604e..974c5a5 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -26547,9 +26547,6 @@
field public static final int UNSUPPORTED = -1; // 0xffffffff
}
- public interface TunnelConnectionParams {
- }
-
public abstract class Uri implements java.lang.Comparable<android.net.Uri> android.os.Parcelable {
method public abstract android.net.Uri.Builder buildUpon();
method public int compareTo(android.net.Uri);
@@ -27118,7 +27115,7 @@
}
public static final class VcnGatewayConnectionConfig.Builder {
- ctor public VcnGatewayConnectionConfig.Builder(@NonNull String, @NonNull android.net.TunnelConnectionParams);
+ ctor public VcnGatewayConnectionConfig.Builder(@NonNull String, @NonNull android.net.ipsec.ike.IkeTunnelConnectionParams);
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addExposedCapability(int);
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig build();
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeExposedCapability(int);
diff --git a/core/java/android/net/TunnelConnectionParams.java b/core/java/android/net/TunnelConnectionParams.java
deleted file mode 100644
index f5b3539..0000000
--- a/core/java/android/net/TunnelConnectionParams.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2021 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.net;
-
-/**
- * TunnelConnectionParams represents a configuration to set up a tunnel connection.
- *
- * <p>Concrete implementations for a control plane protocol should implement this interface.
- * Subclasses should be immutable data classes containing connection, authentication and
- * authorization parameters required to establish a tunnel connection.
- *
- * @see android.net.ipsec.ike.IkeTunnelConnectionParams
- */
-// TODO:b/186071626 Remove TunnelConnectionParams when non-updatable API stub can resolve
-// IkeTunnelConnectionParams
-public interface TunnelConnectionParams {}
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index 3c02cf0..eedeeb5 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -24,7 +24,7 @@
import android.annotation.SuppressLint;
import android.net.Network;
import android.net.NetworkCapabilities;
-import android.net.TunnelConnectionParams;
+import android.net.ipsec.ike.IkeTunnelConnectionParams;
import android.net.vcn.persistablebundleutils.TunnelConnectionParamsUtils;
import android.os.PersistableBundle;
import android.util.ArraySet;
@@ -159,7 +159,7 @@
@NonNull private final String mGatewayConnectionName;
private static final String TUNNEL_CONNECTION_PARAMS_KEY = "mTunnelConnectionParams";
- @NonNull private TunnelConnectionParams mTunnelConnectionParams;
+ @NonNull private IkeTunnelConnectionParams mTunnelConnectionParams;
private static final String EXPOSED_CAPABILITIES_KEY = "mExposedCapabilities";
@NonNull private final SortedSet<Integer> mExposedCapabilities;
@@ -176,7 +176,7 @@
/** Builds a VcnGatewayConnectionConfig with the specified parameters. */
private VcnGatewayConnectionConfig(
@NonNull String gatewayConnectionName,
- @NonNull TunnelConnectionParams tunnelConnectionParams,
+ @NonNull IkeTunnelConnectionParams tunnelConnectionParams,
@NonNull Set<Integer> exposedCapabilities,
@NonNull Set<Integer> underlyingCapabilities,
@NonNull long[] retryIntervalsMs,
@@ -276,7 +276,7 @@
* @hide
*/
@NonNull
- public TunnelConnectionParams getTunnelConnectionParams() {
+ public IkeTunnelConnectionParams getTunnelConnectionParams() {
return mTunnelConnectionParams;
}
@@ -419,7 +419,7 @@
*/
public static final class Builder {
@NonNull private final String mGatewayConnectionName;
- @NonNull private final TunnelConnectionParams mTunnelConnectionParams;
+ @NonNull private final IkeTunnelConnectionParams mTunnelConnectionParams;
@NonNull private final Set<Integer> mExposedCapabilities = new ArraySet();
@NonNull private final Set<Integer> mUnderlyingCapabilities = new ArraySet();
@NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS;
@@ -437,13 +437,13 @@
* VcnConfig} must be given a unique name. This name is used by the caller to
* distinguish between VcnGatewayConnectionConfigs configured on a single {@link
* VcnConfig}. This will be used as the identifier in VcnStatusCallback invocations.
- * @param tunnelConnectionParams the tunnel connection configuration
- * @see TunnelConnectionParams
+ * @param tunnelConnectionParams the IKE tunnel connection configuration
+ * @see IkeTunnelConnectionParams
* @see VcnManager.VcnStatusCallback#onGatewayConnectionError
*/
public Builder(
@NonNull String gatewayConnectionName,
- @NonNull TunnelConnectionParams tunnelConnectionParams) {
+ @NonNull IkeTunnelConnectionParams tunnelConnectionParams) {
Objects.requireNonNull(gatewayConnectionName, "gatewayConnectionName was null");
Objects.requireNonNull(tunnelConnectionParams, "tunnelConnectionParams was null");
diff --git a/core/java/android/net/vcn/persistablebundleutils/TunnelConnectionParamsUtils.java b/core/java/android/net/vcn/persistablebundleutils/TunnelConnectionParamsUtils.java
index 690e4e7..4bc5b49 100644
--- a/core/java/android/net/vcn/persistablebundleutils/TunnelConnectionParamsUtils.java
+++ b/core/java/android/net/vcn/persistablebundleutils/TunnelConnectionParamsUtils.java
@@ -16,7 +16,6 @@
package android.net.vcn.persistablebundleutils;
import android.annotation.NonNull;
-import android.net.TunnelConnectionParams;
import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.IkeTunnelConnectionParams;
import android.net.ipsec.ike.TunnelModeChildSessionParams;
@@ -25,7 +24,7 @@
import java.util.Objects;
/**
- * Utility class to convert TunnelConnectionParams to/from PersistableBundle
+ * Utility class to convert Tunnel Connection Params to/from PersistableBundle
*
* @hide
*/
@@ -34,30 +33,28 @@
private static final String PARAMS_TYPE_IKE = "IKE";
- /** Serializes an TunnelConnectionParams to a PersistableBundle. */
+ /** Serializes an IkeTunnelConnectionParams to a PersistableBundle. */
@NonNull
- public static PersistableBundle toPersistableBundle(@NonNull TunnelConnectionParams params) {
+ public static PersistableBundle toPersistableBundle(@NonNull IkeTunnelConnectionParams params) {
final PersistableBundle result = new PersistableBundle();
- if (params instanceof IkeTunnelConnectionParams) {
- result.putPersistableBundle(
- PARAMS_TYPE_IKE,
- IkeTunnelConnectionParamsUtils.serializeIkeParams(
- (IkeTunnelConnectionParams) params));
- return result;
- } else {
- throw new UnsupportedOperationException("Invalid TunnelConnectionParams type");
- }
+ result.putPersistableBundle(
+ PARAMS_TYPE_IKE,
+ IkeTunnelConnectionParamsUtils.serializeIkeParams(
+ (IkeTunnelConnectionParams) params));
+ return result;
}
- /** Constructs an TunnelConnectionParams by deserializing a PersistableBundle. */
+ /** Constructs an IkeTunnelConnectionParams by deserializing a PersistableBundle. */
@NonNull
- public static TunnelConnectionParams fromPersistableBundle(@NonNull PersistableBundle in) {
+ public static IkeTunnelConnectionParams fromPersistableBundle(@NonNull PersistableBundle in) {
Objects.requireNonNull(in, "PersistableBundle was null");
if (in.keySet().size() != EXPECTED_BUNDLE_KEY_CNT) {
throw new IllegalArgumentException(
- "Expect PersistableBundle to have one element but found: " + in.keySet());
+ String.format(
+ "Expect PersistableBundle to have %d element but found: %d",
+ EXPECTED_BUNDLE_KEY_CNT, in.keySet()));
}
if (in.get(PARAMS_TYPE_IKE) != null) {
@@ -66,7 +63,7 @@
}
throw new IllegalArgumentException(
- "Invalid TunnelConnectionParams type " + in.keySet().iterator().next());
+ "Invalid Tunnel Connection Params type " + in.keySet().iterator().next());
}
private static final class IkeTunnelConnectionParamsUtils {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index e47129e..0dbdb8f 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1226,6 +1226,7 @@
return rect;
}
+ @Nullable
private static Class<?> getParameterType(int type) {
switch (type) {
case BaseReflectionAction.BOOLEAN:
@@ -1267,6 +1268,7 @@
}
}
+ @Nullable
private MethodHandle getMethod(View view, String methodName, Class<?> paramType,
boolean async) {
MethodArgs result;
@@ -1517,6 +1519,7 @@
}
}
+ @Nullable
public Bitmap getBitmapForId(int id) {
if (id == -1 || id >= mBitmaps.size()) {
return null;
@@ -1864,8 +1867,9 @@
}
}
+ @Nullable
@Override
- protected Object getParameterValue(View view) throws ActionException {
+ protected Object getParameterValue(@Nullable View view) throws ActionException {
return this.value;
}
@@ -1904,8 +1908,11 @@
dest.writeInt(this.mResId);
}
+ @Nullable
@Override
- protected Object getParameterValue(View view) throws ActionException {
+ protected Object getParameterValue(@Nullable View view) throws ActionException {
+ if (view == null) return null;
+
Resources resources = view.getContext().getResources();
try {
switch (this.mResourceType) {
@@ -2079,8 +2086,11 @@
dest.writeInt(this.mUnit);
}
+ @Nullable
@Override
- protected Object getParameterValue(View view) throws ActionException {
+ protected Object getParameterValue(@Nullable View view) throws ActionException {
+ if (view == null) return null;
+
DisplayMetrics dm = view.getContext().getResources().getDisplayMetrics();
try {
int data = TypedValue.createComplexDimension(this.mValue, this.mUnit);
@@ -3592,6 +3602,9 @@
while (remoteViews.hasNext()) {
RemoteViews view = remoteViews.next();
SizeF size = view.getIdealSize();
+ if (size == null) {
+ throw new IllegalStateException("Expected RemoteViews to have ideal size");
+ }
float newViewArea = size.getWidth() * size.getHeight();
if (smallestView != null && !view.hasSameAppInfo(smallestView.mApplication)) {
throw new IllegalArgumentException(
@@ -5309,6 +5322,10 @@
float bestSqDist = Float.MAX_VALUE;
for (RemoteViews layout : mSizedRemoteViews) {
SizeF layoutSize = layout.getIdealSize();
+ if (layoutSize == null) {
+ throw new IllegalStateException("Expected RemoteViews to have ideal size");
+ }
+
if (fitsIn(layoutSize, widgetSize)) {
if (bestFit == null) {
bestFit = layout;
@@ -5342,7 +5359,7 @@
*/
public RemoteViews getRemoteViewsToApply(@NonNull Context context,
@Nullable SizeF widgetSize) {
- if (!hasSizedRemoteViews()) {
+ if (!hasSizedRemoteViews() || widgetSize == null) {
// If there isn't multiple remote views, fall back on the previous methods.
return getRemoteViewsToApply(context);
}
@@ -5419,7 +5436,7 @@
/** @hide */
public View apply(Context context, ViewGroup parent, InteractionHandler handler,
- @NonNull SizeF size, @Nullable ColorResources colorResources) {
+ @Nullable SizeF size, @Nullable ColorResources colorResources) {
RemoteViews rvToApply = getRemoteViewsToApply(context, size);
View result = inflateView(context, rvToApply, parent, 0, colorResources);
@@ -5431,7 +5448,7 @@
return inflateView(context, rv, parent, 0, null);
}
- private View inflateView(Context context, RemoteViews rv, ViewGroup parent,
+ private View inflateView(Context context, RemoteViews rv, @Nullable ViewGroup parent,
@StyleRes int applyThemeResId, @Nullable ColorResources colorResources) {
// RemoteViews may be built by an application installed in another
// user. So build a context that loads resources from that user but
@@ -5447,8 +5464,7 @@
if (applyThemeResId != 0) {
inflationContext = new ContextThemeWrapper(inflationContext, applyThemeResId);
}
- LayoutInflater inflater = (LayoutInflater)
- context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ LayoutInflater inflater = LayoutInflater.from(context);
// Clone inflater so we load resources from correct context and
// we don't add a filter to the static version returned by getSystemService.
@@ -5576,6 +5592,7 @@
mResult = result;
}
+ @Nullable
@Override
protected ViewTree doInBackground(Void... params) {
try {
@@ -5860,6 +5877,7 @@
* are in an array, the array's entries are 16 bytes each. We use this to work out the
* location of all the positions of the various resources.
*/
+ @Nullable
private static byte[] createCompiledResourcesContent(Context context,
SparseIntArray colorResources) throws IOException {
byte[] content;
@@ -5897,6 +5915,7 @@
*
* @hide
*/
+ @Nullable
public static ColorResources create(Context context, SparseIntArray colorMapping) {
try {
byte[] contentBytes = createCompiledResourcesContent(context, colorMapping);
@@ -6020,7 +6039,8 @@
}
}
- private static ApplicationInfo getApplicationInfo(String packageName, int userId) {
+ @Nullable
+ private static ApplicationInfo getApplicationInfo(@Nullable String packageName, int userId) {
if (packageName == null) {
return null;
}
@@ -6096,6 +6116,7 @@
}
}
+ @Nullable
public ViewTree findViewTreeById(@IdRes int id) {
if (mRoot.getId() == id) {
return this;
@@ -6112,6 +6133,7 @@
return null;
}
+ @Nullable
public ViewTree findViewTreeParentOf(ViewTree child) {
if (mChildren == null) {
return null;
@@ -6134,6 +6156,7 @@
createTree();
}
+ @Nullable
public <T extends View> T findViewById(@IdRes int id) {
if (mChildren == null) {
return mRoot.findViewById(id);
@@ -6391,6 +6414,8 @@
*/
@Nullable
private static AdapterView<?> getAdapterViewAncestor(@Nullable View view) {
+ if (view == null) return null;
+
View parent = (View) view.getParent();
// Break the for loop on the first encounter of:
// 1) an AdapterView,
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index ea0f704..4e96ae7 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -128,6 +128,8 @@
private CharSequence mFallbackChatName;
private CharSequence mFallbackGroupChatName;
private CharSequence mConversationTitle;
+ private int mMessageSpacingStandard;
+ private int mMessageSpacingGroup;
private int mNotificationHeaderExpandedPadding;
private View mConversationHeader;
private View mContentContainer;
@@ -241,6 +243,10 @@
mContentContainer = findViewById(R.id.notification_action_list_margin_target);
mExpandButtonAndContentContainer = findViewById(R.id.expand_button_and_content_container);
mExpandButton = findViewById(R.id.expand_button);
+ mMessageSpacingStandard = getResources().getDimensionPixelSize(
+ R.dimen.notification_messaging_spacing);
+ mMessageSpacingGroup = getResources().getDimensionPixelSize(
+ R.dimen.notification_messaging_spacing_conversation_group);
mNotificationHeaderExpandedPadding = getResources().getDimensionPixelSize(
R.dimen.conversation_header_expanded_padding_end);
mContentMarginEnd = getResources().getDimensionPixelSize(
@@ -699,6 +705,10 @@
}
private void updatePaddingsBasedOnContentAvailability() {
+ // groups have avatars that need more spacing
+ mMessagingLinearLayout.setSpacing(
+ mIsOneToOne ? mMessageSpacingStandard : mMessageSpacingGroup);
+
int messagingPadding = mIsOneToOne || mIsCollapsed
? 0
// Add some extra padding to the messages, since otherwise it will overlap with the
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
index 7cfd46c..cb1d387 100644
--- a/core/java/com/android/internal/widget/MessagingLinearLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -17,6 +17,7 @@
package com.android.internal.widget;
import android.annotation.Nullable;
+import android.annotation.Px;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
@@ -251,6 +252,16 @@
return super.drawChild(canvas, child, drawingTime);
}
+ /**
+ * Set the spacing to be applied between views.
+ */
+ public void setSpacing(@Px int spacing) {
+ if (mSpacing != spacing) {
+ mSpacing = spacing;
+ requestLayout();
+ }
+ }
+
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(mContext, attrs);
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 43c0ec9..fc3ed63 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -367,6 +367,9 @@
<!-- The spacing between messages in Notification.MessagingStyle -->
<dimen name="notification_messaging_spacing">6dp</dimen>
+ <!-- The spacing between messages in Notification.MessagingStyle -->
+ <dimen name="notification_messaging_spacing_conversation_group">24dp</dimen>
+
<!-- The rounding for messaging images -->
<dimen name="messaging_image_rounding">4dp</dimen>
@@ -760,7 +763,7 @@
<!-- The maximum size of the grayscale icon -->
<dimen name="notification_grayscale_icon_max_size">256dp</dimen>
- <dimen name="messaging_avatar_size">36dp</dimen>
+ <dimen name="messaging_avatar_size">48dp</dimen>
<dimen name="conversation_avatar_size">48dp</dimen>
<!-- start margin of the icon circle in the conversation's skin of the header -->
<dimen name="conversation_icon_circle_start">28dp</dimen>
@@ -779,17 +782,17 @@
<!-- size of the face pile icons -->
<dimen name="conversation_face_pile_avatar_size">32dp</dimen>
<!-- size of the face pile icons when the group is expanded -->
- <dimen name="conversation_face_pile_avatar_size_group_expanded">25dp</dimen>
+ <dimen name="conversation_face_pile_avatar_size_group_expanded">@dimen/conversation_face_pile_avatar_size</dimen>
<!-- Side margins of the conversation badge in relation to the conversation icon when the group is expanded-->
- <dimen name="conversation_badge_side_margin_group_expanded">22dp</dimen>
+ <dimen name="conversation_badge_side_margin_group_expanded">@dimen/conversation_badge_side_margin</dimen>
<!-- Side margins of the conversation badge in relation to the conversation icon when the group is expanded-->
- <dimen name="conversation_badge_side_margin_group_expanded_face_pile">18dp</dimen>
+ <dimen name="conversation_badge_side_margin_group_expanded_face_pile">@dimen/conversation_badge_side_margin</dimen>
<!-- The width of the protection of the face pile layout-->
<dimen name="conversation_face_pile_protection_width">2dp</dimen>
<!-- The width of the protection of the face pile layout when expanded-->
- <dimen name="conversation_face_pile_protection_width_expanded">1dp</dimen>
+ <dimen name="conversation_face_pile_protection_width_expanded">@dimen/conversation_face_pile_protection_width</dimen>
<!-- The padding of the expanded message container-->
- <dimen name="expanded_group_conversation_message_padding">17dp</dimen>
+ <dimen name="expanded_group_conversation_message_padding">32dp</dimen>
<!-- The stroke width of the ring used to visually mark a conversation as important -->
<dimen name="importance_ring_stroke_width">2dp</dimen>
<!-- The maximum stroke width used for the animation shown when a conversation is marked as important -->
@@ -801,7 +804,7 @@
<dimen name="conversation_icon_container_top_padding">20dp</dimen>
<!-- The top padding of the conversation icon container when the avatar is small-->
- <dimen name="conversation_icon_container_top_padding_small_avatar">9dp</dimen>
+ <dimen name="conversation_icon_container_top_padding_small_avatar">8dp</dimen>
<!-- The padding of the conversation header when expanded. This is calculated from the expand button size + notification_content_margin_end -->
<dimen name="conversation_header_expanded_padding_end">38dp</dimen>
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
index 439ae48..ad0d0e0 100644
--- a/core/res/res/values/styles_device_defaults.xml
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -302,10 +302,6 @@
<style name="TextAppearance.DeviceDefault.Notification.Time" parent="TextAppearance.Material.Notification.Time">
<item name="fontFamily">@string/config_bodyFontFamily</item>
</style>
- <style name="TextAppearance.DeviceDefault.Notification.Conversation.AppName"
- parent="TextAppearance.Material.Notification.Conversation.AppName">
- <item name="fontFamily">@string/config_headlineFontFamilyMedium</item>
- </style>
<style name="TextAppearance.DeviceDefault.Widget" parent="TextAppearance.Material.Widget">
<item name="fontFamily">@string/config_bodyFontFamily</item>
</style>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 3c4a5d4..eec6ae3 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -497,10 +497,6 @@
<!-- unused; keep identical to parent -->
<style name="TextAppearance.Material.Notification.Emphasis"/>
- <style name="TextAppearance.Material.Notification.Conversation.AppName" parent="TextAppearance.Material.Notification.Title">
- <item name="android:textSize">16sp</item>
- </style>
-
<style name="TextAppearance.Material.ListItem" parent="TextAppearance.Material.Subhead" />
<style name="TextAppearance.Material.ListItemSecondary" parent="TextAppearance.Material.Body1" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 9ac9e8e..d62f2bc 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3083,6 +3083,7 @@
<java-symbol type="string" name="negative_duration" />
<java-symbol type="dimen" name="notification_messaging_spacing" />
+ <java-symbol type="dimen" name="notification_messaging_spacing_conversation_group" />
<java-symbol type="dimen" name="notification_text_margin_top" />
<java-symbol type="dimen" name="notification_inbox_item_top_padding" />
@@ -4090,7 +4091,6 @@
<java-symbol type="dimen" name="button_inset_horizontal_material" />
<java-symbol type="layout" name="conversation_face_pile_layout" />
<java-symbol type="string" name="unread_convo_overflow" />
- <java-symbol type="style" name="TextAppearance.DeviceDefault.Notification.Conversation.AppName" />
<java-symbol type="drawable" name="conversation_badge_background" />
<java-symbol type="drawable" name="conversation_badge_ring" />
<java-symbol type="color" name="conversation_important_highlight" />
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index d5733e3..2650d9f 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -40,7 +40,7 @@
<shortcode country="al" pattern="\\d{5}" premium="15191|55[56]00" />
<!-- Argentina: 5 digits, known short codes listed -->
- <shortcode country="ar" pattern="\\d{5}" free="11711|28291" />
+ <shortcode country="ar" pattern="\\d{5}" free="11711|28291|44077" />
<!-- Armenia: 3-4 digits, emergency numbers 10[123] -->
<shortcode country="am" pattern="\\d{3,4}" premium="11[2456]1|3024" free="10[123]" />
@@ -76,14 +76,14 @@
<shortcode country="ch" pattern="[2-9]\\d{2,4}" premium="543|83111|30118" free="98765|30075|30047" />
<!-- Chile: 4-5 digits (not confirmed), known premium codes listed -->
- <shortcode country="cl" pattern="\\d{4,5}" free="9963|9240" />
+ <shortcode country="cl" pattern="\\d{4,5}" free="9963|9240|1038" />
<!-- China: premium shortcodes start with "1066", free shortcodes start with "1065":
http://clients.txtnation.com/entries/197192-china-premium-sms-short-code-requirements -->
<shortcode country="cn" premium="1066.*" free="1065.*" />
<!-- Colombia: 1-6 digits (not confirmed) -->
- <shortcode country="co" pattern="\\d{1,6}" free="890350|908160|892255|898002|898880|899960" />
+ <shortcode country="co" pattern="\\d{1,6}" free="890350|908160|892255|898002|898880|899960|899948|87739" />
<!-- Cyprus: 4-6 digits (not confirmed), known premium codes listed, plus EU -->
<shortcode country="cy" pattern="\\d{4,6}" premium="7510" free="116\\d{3}" />
@@ -156,7 +156,7 @@
<shortcode country="jp" pattern="\\d{1,5}" free="8083" />
<!-- Kenya: 5 digits, known premium codes listed -->
- <shortcode country="ke" pattern="\\d{5}" free="21725" />
+ <shortcode country="ke" pattern="\\d{5}" free="21725|21562|40520" />
<!-- Kyrgyzstan: 4 digits, known premium codes listed -->
<shortcode country="kg" pattern="\\d{4}" premium="415[2367]|444[69]" />
@@ -187,13 +187,13 @@
<shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" free="26259|46645|50025|50052|5050|76551|88778|9963" />
<!-- Malaysia: 5 digits: http://www.skmm.gov.my/attachment/Consumer_Regulation/Mobile_Content_Services_FAQs.pdf -->
- <shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288" />
+ <shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288|66668" />
<!-- The Netherlands, 4 digits, known premium codes listed, plus EU -->
<shortcode country="nl" pattern="\\d{4}" premium="4466|5040" free="116\\d{3}|2223|6225|2223|1662" />
<!-- Nigeria -->
- <shortcode country="ng" pattern="\\d{1,5}" free="2441" />
+ <shortcode country="ng" pattern="\\d{1,5}" free="2441|55019" />
<!-- Norway: 4-5 digits (not confirmed), known premium codes listed -->
<shortcode country="no" pattern="\\d{4,5}" premium="2201|222[67]" free="2171" />
@@ -202,7 +202,7 @@
<shortcode country="nz" pattern="\\d{3,4}" premium="3903|8995|4679" free="1737|176|2141|3067|3068|3110|4006|4053|4061|4062|4202|4300|4334|4412|4575|5626|8006|8681" />
<!-- Peru: 4-5 digits (not confirmed), known premium codes listed -->
- <shortcode country="pe" pattern="\\d{4,5}" free="9963" />
+ <shortcode country="pe" pattern="\\d{4,5}" free="9963|40777" />
<!-- Philippines -->
<shortcode country="ph" pattern="\\d{1,5}" free="2147|5495|5496" />
@@ -224,7 +224,7 @@
<shortcode country="re" pattern="\\d{1,5}" free="38600,36300,36303,959" />
<!-- Romania: 4 digits, plus EU: http://www.simplus.ro/en/resources/glossary-of-terms/ -->
- <shortcode country="ro" pattern="\\d{4}" premium="12(?:63|66|88)|13(?:14|80)" free="116\\d{3}|3654|8360" />
+ <shortcode country="ro" pattern="\\d{4}" premium="12(?:63|66|88)|13(?:14|80)" free="116\\d{3}|3654|8360|3838" />
<!-- Russia: 4 digits, known premium codes listed: http://smscoin.net/info/pricing-russia/ -->
<shortcode country="ru" pattern="\\d{4}" premium="1(?:1[56]1|899)|2(?:09[57]|322|47[46]|880|990)|3[589]33|4161|44(?:4[3-9]|81)|77(?:33|81)|8424" free="6954|8501" standard="2037|2044"/>
@@ -252,7 +252,7 @@
<shortcode country="tj" pattern="\\d{4}" premium="11[3-7]1|4161|4333|444[689]" />
<!-- Turkey -->
- <shortcode country="tr" pattern="\\d{1,5}" free="7529|5528|6493" />
+ <shortcode country="tr" pattern="\\d{1,5}" free="7529|5528|6493|3193" />
<!-- Ukraine: 4 digits, known premium codes listed -->
<shortcode country="ua" pattern="\\d{4}" premium="444[3-9]|70[579]4|7540" />
@@ -268,6 +268,6 @@
<shortcode country="yt" pattern="\\d{1,5}" free="38600,36300,36303,959" />
<!-- South Africa -->
- <shortcode country="za" pattern="\d{1,5}" free="44136" />
+ <shortcode country="za" pattern="\d{1,5}" free="44136|30791|36056" />
</shortcodes>
diff --git a/graphics/java/android/graphics/drawable/ColorStateListDrawable.java b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java
index 20cd825..423e66c 100644
--- a/graphics/java/android/graphics/drawable/ColorStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorStateListDrawable.java
@@ -48,6 +48,12 @@
setColorStateList(colorStateList);
}
+ private ColorStateListDrawable(@NonNull ColorStateListDrawableState state) {
+ mState = state;
+ initializeColorDrawable();
+ onStateChange(getState());
+ }
+
@Override
public void draw(@NonNull Canvas canvas) {
mColorDrawable.draw(canvas);
@@ -286,11 +292,6 @@
}
}
- private ColorStateListDrawable(@NonNull ColorStateListDrawableState state) {
- mState = state;
- initializeColorDrawable();
- }
-
private void initializeColorDrawable() {
mColorDrawable = new ColorDrawable();
mColorDrawable.setCallback(this);
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNotSupportNonResizable.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNotSupportNonResizable.kt
index 6bc9a5c..58e9204 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNotSupportNonResizable.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNotSupportNonResizable.kt
@@ -25,7 +25,6 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.canSplitScreen
-import com.android.server.wm.flicker.helpers.openQuickstep
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.dockedStackDividerIsInvisible
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
@@ -64,7 +63,6 @@
}
}
transitions {
- device.openQuickstep(wmHelper)
if (device.canSplitScreen(wmHelper)) {
Assert.fail("Non-resizeable app should not enter split screen")
}
diff --git a/native/graphics/jni/imagedecoder.cpp b/native/graphics/jni/imagedecoder.cpp
index 385e455..b0c8c61 100644
--- a/native/graphics/jni/imagedecoder.cpp
+++ b/native/graphics/jni/imagedecoder.cpp
@@ -442,6 +442,15 @@
return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
}
+ const auto colorType = imageDecoder->getOutputInfo().colorType();
+ switch (colorType) {
+ case kN32_SkColorType:
+ case kRGBA_F16_SkColorType:
+ break;
+ default:
+ return ANDROID_IMAGE_DECODER_INVALID_STATE;
+ }
+
if (imageDecoder->advanceFrame()) {
return ANDROID_IMAGE_DECODER_SUCCESS;
}
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index c5ba3d2..7f645ba 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -20,12 +20,14 @@
<!-- This is a view that shows general status information in Keyguard. -->
<com.android.keyguard.KeyguardStatusView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyguard_status_view"
android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal|top">
+ systemui:layout_constraintStart_toStartOf="parent"
+ systemui:layout_constraintEnd_toEndOf="parent"
+ systemui:layout_constraintTop_toTopOf="parent"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/status_view_container"
android:layout_width="match_parent"
@@ -70,5 +72,11 @@
android:letterSpacing="0.05"
android:ellipsize="marquee"
android:singleLine="true" />
+ <FrameLayout
+ android:id="@+id/status_view_media_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/qs_media_padding"
+ />
</LinearLayout>
</com.android.keyguard.KeyguardStatusView>
diff --git a/packages/SystemUI/res/color/qs_security_footer_background_stroke.xml b/packages/SystemUI/res/color/qs_security_footer_background_stroke.xml
new file mode 100644
index 0000000..aa4d4e8
--- /dev/null
+++ b/packages/SystemUI/res/color/qs_security_footer_background_stroke.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="@android:color/system_neutral1_100" android:alpha="0.8" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_security_footer_background.xml b/packages/SystemUI/res/drawable/qs_security_footer_background.xml
new file mode 100644
index 0000000..7d370e9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_security_footer_background.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetTop="@dimen/qs_security_footer_background_inset"
+ android:insetBottom="@dimen/qs_security_footer_background_inset"
+ >
+ <ripple
+ android:color="?android:attr/colorControlHighlight">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/white"/>
+ <corners android:radius="@dimen/qs_security_footer_corner_radius"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <stroke android:width="1dp"
+ android:color="@color/qs_security_footer_background_stroke"/>
+ <corners android:radius="@dimen/qs_security_footer_corner_radius"/>
+ </shape>
+ </item>
+ </ripple>
+</inset>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/hybrid_conversation_notification.xml b/packages/SystemUI/res/layout/hybrid_conversation_notification.xml
index 214c44a..335e0a4 100644
--- a/packages/SystemUI/res/layout/hybrid_conversation_notification.xml
+++ b/packages/SystemUI/res/layout/hybrid_conversation_notification.xml
@@ -26,21 +26,22 @@
<FrameLayout
android:layout_width="@*android:dimen/conversation_content_start"
- android:layout_height="25dp"
+ android:layout_height="@dimen/conversation_single_line_face_pile_size"
+ android:paddingHorizontal="16dp"
>
<ImageView
android:id="@*android:id/conversation_icon"
- android:layout_width="20dp"
- android:layout_height="20dp"
- android:layout_gravity="center"
+ android:layout_width="@dimen/conversation_single_line_avatar_size"
+ android:layout_height="@dimen/conversation_single_line_avatar_size"
+ android:layout_gravity="center_vertical|end"
/>
<ViewStub
android:id="@*android:id/conversation_face_pile"
android:layout="@*android:layout/conversation_face_pile_layout"
- android:layout_width="25dp"
- android:layout_height="25dp"
- android:layout_gravity="center"
+ android:layout_width="@dimen/conversation_single_line_face_pile_size"
+ android:layout_height="@dimen/conversation_single_line_face_pile_size"
+ android:layout_gravity="center_vertical|end"
/>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/quick_qs_status_icons.xml b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
index 1f90476..d8bb7e6 100644
--- a/packages/SystemUI/res/layout/quick_qs_status_icons.xml
+++ b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
@@ -44,14 +44,6 @@
android:layout_weight="1"
/>
- <!-- Will hold security footer in landscape with media -->
- <FrameLayout
- android:id="@+id/header_text_container"
- android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:gravity="center"
- />
-
<include layout="@layout/qs_carrier_group"
android:id="@+id/carrier_group"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/quick_settings_footer.xml b/packages/SystemUI/res/layout/quick_settings_footer.xml
deleted file mode 100644
index db712e4..0000000
--- a/packages/SystemUI/res/layout/quick_settings_footer.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2014 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.
--->
-<com.android.systemui.util.NeverExactlyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:minHeight="48dp"
- android:clickable="true"
- android:paddingBottom="@dimen/qs_tile_padding_top"
- android:paddingTop="@dimen/qs_tile_padding_top"
- android:paddingStart="@dimen/qs_footer_padding_start"
- android:paddingEnd="@dimen/qs_footer_padding_end"
- android:gravity="center_vertical"
- android:layout_gravity="center_vertical|center_horizontal"
- android:background="@android:color/transparent">
-
- <ImageView
- android:id="@+id/primary_footer_icon"
- android:layout_width="@dimen/qs_footer_icon_size"
- android:layout_height="@dimen/qs_footer_icon_size"
- android:gravity="start"
- android:layout_marginEnd="8dp"
- android:contentDescription="@null"
- android:tint="?android:attr/textColorPrimary" />
-
- <com.android.systemui.util.AutoMarqueeTextView
- android:id="@+id/footer_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:marqueeRepeatLimit="marquee_forever"
- android:textAppearance="@style/TextAppearance.QS.TileLabel"
- android:textColor="?android:attr/textColorPrimary"/>
-
- <ImageView
- android:id="@+id/footer_icon"
- android:layout_width="@dimen/qs_footer_icon_size"
- android:layout_height="@dimen/qs_footer_icon_size"
- android:layout_marginStart="8dp"
- android:contentDescription="@null"
- android:src="@drawable/ic_info_outline"
- android:tint="?android:attr/textColorPrimary" />
-
-</com.android.systemui.util.NeverExactlyLinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_settings_security_footer.xml b/packages/SystemUI/res/layout/quick_settings_security_footer.xml
new file mode 100644
index 0000000..de65fa0
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_security_footer.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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.
+-->
+<com.android.systemui.util.DualHeightHorizontalLinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/qs_security_footer_height"
+ android:clickable="true"
+ android:padding="@dimen/qs_footer_padding"
+ android:gravity="center_vertical"
+ android:layout_gravity="center_vertical|center_horizontal"
+ android:layout_marginVertical="@dimen/qs_security_footer_vertical_margin"
+ android:background="@drawable/qs_security_footer_background"
+ systemui:singleLineHeight="@dimen/qs_security_footer_single_line_height"
+ systemui:textViewId="@id/footer_text"
+ >
+
+ <ImageView
+ android:id="@+id/primary_footer_icon"
+ android:layout_width="@dimen/qs_footer_icon_size"
+ android:layout_height="@dimen/qs_footer_icon_size"
+ android:gravity="start"
+ android:layout_marginEnd="12dp"
+ android:contentDescription="@null"
+ android:tint="?android:attr/textColorSecondary" />
+
+ <TextView
+ android:id="@+id/footer_text"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:maxLines="@integer/qs_security_footer_maxLines"
+ android:ellipsize="end"
+ android:textAppearance="@style/TextAppearance.QS.SecurityFooter"
+ android:textColor="?android:attr/textColorSecondary"/>
+
+ <ImageView
+ android:id="@+id/footer_icon"
+ android:layout_width="@dimen/qs_footer_icon_size"
+ android:layout_height="@dimen/qs_footer_icon_size"
+ android:layout_marginStart="8dp"
+ android:contentDescription="@null"
+ android:src="@*android:drawable/ic_chevron_end"
+ android:tint="?android:attr/textColorSecondary" />
+
+</com.android.systemui.util.DualHeightHorizontalLinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml b/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
index 22cf2cb..d0e3d3c 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
@@ -55,6 +55,16 @@
android:layout_gravity="center_vertical|center_horizontal"
android:visibility="gone" />
+ <!-- Will hold security footer in landscape with media -->
+ <FrameLayout
+ android:id="@+id/header_text_container"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:gravity="center"
+ />
+
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 46a698a..52995ea 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -37,10 +37,6 @@
android:layout_height="match_parent"
android:layout_width="match_parent" />
- <include
- layout="@layout/keyguard_status_view"
- android:visibility="gone" />
-
<com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -49,6 +45,10 @@
android:clipToPadding="false"
android:clipChildren="false">
+ <include
+ layout="@layout/keyguard_status_view"
+ android:visibility="gone"/>
+
<include layout="@layout/dock_info_overlay" />
<FrameLayout
diff --git a/packages/SystemUI/res/layout/udfps_view.xml b/packages/SystemUI/res/layout/udfps_view.xml
index 50b2f20..e5e8fe6 100644
--- a/packages/SystemUI/res/layout/udfps_view.xml
+++ b/packages/SystemUI/res/layout/udfps_view.xml
@@ -20,7 +20,8 @@
android:id="@+id/udfps_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- systemui:sensorTouchAreaCoefficient="0.5">
+ systemui:sensorTouchAreaCoefficient="0.5"
+ android:contentDescription="@string/accessibility_fingerprint_label">
<ViewStub
android:id="@+id/animation_view"
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index 5f50fd4..46e7d71 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -30,6 +30,12 @@
-->
<dimen name="qs_customize_header_min_height">44dp</dimen>
+ <dimen name="qs_security_footer_single_line_height">@*android:dimen/quick_qs_offset_height</dimen>
+ <dimen name="qs_footer_padding">14dp</dimen>
+ <dimen name="qs_security_footer_vertical_margin">0dp</dimen>
+ <dimen name="qs_security_footer_background_inset">12dp</dimen>
+ <dimen name="qs_security_footer_corner_radius">28dp</dimen>
+
<dimen name="battery_detail_graph_space_top">9dp</dimen>
<dimen name="battery_detail_graph_space_bottom">9dp</dimen>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index f489fe8..eb72442 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -189,5 +189,11 @@
<attr name="borderThickness" format="dimension" />
<attr name="borderColor" format="color" />
</declare-styleable>
+
+ <declare-styleable name="DualHeightHorizontalLinearLayout">
+ <attr name="singleLineHeight" format="dimension" />
+ <attr name="singleLineVerticalPadding" format="dimension" />
+ <attr name="textViewId" format="reference" />
+ </declare-styleable>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index fff4a1b..f7578cbd 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -605,13 +605,18 @@
<dimen name="qs_header_carrier_separator_width">6dp</dimen>
<dimen name="qs_status_separator">32dp</dimen>
<dimen name="qs_carrier_margin_width">4dp</dimen>
- <dimen name="qs_footer_padding_start">16dp</dimen>
- <dimen name="qs_footer_padding_end">16dp</dimen>
- <dimen name="qs_footer_icon_size">16dp</dimen>
+ <dimen name="qs_footer_icon_size">20dp</dimen>
<dimen name="qs_paged_tile_layout_padding_bottom">0dp</dimen>
<dimen name="qs_header_top_padding">15dp</dimen>
<dimen name="qs_header_bottom_padding">14dp</dimen>
+ <dimen name="qs_footer_padding">20dp</dimen>
+ <dimen name="qs_security_footer_height">88dp</dimen>
+ <dimen name="qs_security_footer_single_line_height">48dp</dimen>
+ <dimen name="qs_security_footer_vertical_margin">8dp</dimen>
+ <dimen name="qs_security_footer_background_inset">0dp</dimen>
+ <dimen name="qs_security_footer_corner_radius">28dp</dimen>
+
<dimen name="qs_notif_collapsed_space">64dp</dimen>
<dimen name="qs_container_bottom_padding">24dp</dimen>
@@ -691,8 +696,11 @@
<!-- Size of the face pile shown on one-line (children of a group) conversation notifications -->
<dimen name="conversation_single_line_face_pile_size">25dp</dimen>
+ <!-- Size of the avatars within a face pile shown on one-line (children of a group) conversation notifications -->
+ <dimen name="conversation_single_line_face_pile_avatar_size">17dp</dimen>
+
<!-- Size of an avatar shown on one-line (children of a group) conversation notifications -->
- <dimen name="conversation_single_line_avatar_size">20dp</dimen>
+ <dimen name="conversation_single_line_avatar_size">24dp</dimen>
<!-- Border width for avatars in the face pile shown on one-line (children of a group) conversation notifications -->
<dimen name="conversation_single_line_face_pile_protection_width">1dp</dimen>
diff --git a/packages/SystemUI/res/values/integers.xml b/packages/SystemUI/res/values/integers.xml
index b50b5c1..116403c 100644
--- a/packages/SystemUI/res/values/integers.xml
+++ b/packages/SystemUI/res/values/integers.xml
@@ -22,6 +22,8 @@
<integer name="qs_footer_actions_width">0</integer>
<integer name="qs_footer_actions_weight">1</integer>
+ <integer name="qs_security_footer_maxLines">2</integer>
+
<integer name="magnification_default_scale">2</integer>
<!-- The position of the volume dialog on the screen.
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c117069..a9f6946 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -338,6 +338,8 @@
<string name="accessibility_voice_assist_button">Voice Assist</string>
<!-- Content description of the unlock button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_unlock_button">Unlock</string>
+ <!-- Content description of the lock icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_lock_icon">Device locked</string>
<!-- Content description hint of the unlock button when fingerprint is on (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_waiting_for_fingerprint">Waiting for fingerprint</string>
<!-- Accessibility action of the unlock button when fingerpint is on (not shown on the screen). [CHAR LIMIT=NONE] -->
@@ -2958,4 +2960,15 @@
<!-- Secondary label for alarm tile when there is no next alarm information [CHAR LIMIT=20] -->
<string name="qs_alarm_tile_no_alarm">No alarm set</string>
+
+ <!-- Accessibility label for fingerprint sensor [CHAR LIMIT=NONE] -->
+ <string name="accessibility_fingerprint_label">Fingerprint sensor</string>
+ <!-- Accessibility label for disabled udfps sensor [CHAR LIMIT=NONE] -->
+ <string name="accessibility_udfps_disabled_button">Fingerprint sensor disabled</string>
+ <!-- Accessibility action for tapping on an affordance that will bring up the user's
+ pin/pattern/password bouncer (ie: "Double tap to authenticate") [CHAR LIMIT=NONE] -->
+ <string name="accessibility_authenticate_hint">authenticate</string>
+ <!-- Accessibility action for tapping on an affordance on an unlocked lock screen (ie: "Double
+ tap to enter device") [CHAR LIMIT=NONE] -->
+ <string name="accessibility_enter_hint">enter device</string>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 5da75a1..2e45acc 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -220,6 +220,11 @@
<item name="android:textSize">@dimen/celltile_rat_type_size</item>
</style>
+ <style name="TextAppearance.QS.SecurityFooter">
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+ <item name="android:textSize">@dimen/qs_tile_text_size</item>
+ </style>
+
<style name="TextAppearance.QS.Status" parent="TextAppearance.QS.TileLabel.Secondary">
<item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
<item name="android:textColor">@color/dark_mode_qs_icon_color_single_tone</item>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 9df7734..3ab2cca 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -35,6 +35,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.R;
+import com.android.systemui.statusbar.CrossFadeHelper;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -44,6 +45,7 @@
* - keyguard clock
* - logout button (on certain managed devices)
* - owner information (if set)
+ * - media player (split shade mode only)
*/
public class KeyguardStatusView extends GridLayout {
private static final boolean DEBUG = KeyguardConstants.DEBUG;
@@ -60,6 +62,7 @@
private KeyguardSliceView mKeyguardSlice;
private Runnable mPendingMarqueeStart;
private Handler mHandler;
+ private View mMediaHostContainer;
private float mDarkAmount = 0;
private int mTextColor;
@@ -148,6 +151,8 @@
mKeyguardSlice.setContentChangeListener(this::onSliceContentChanged);
onSliceContentChanged();
+ mMediaHostContainer = findViewById(R.id.status_view_media_container);
+
updateOwnerInfo();
updateDark();
}
@@ -223,6 +228,9 @@
}
mDarkAmount = darkAmount;
mClockView.setDarkAmount(darkAmount);
+ if (mMediaHostContainer.getVisibility() != View.GONE) {
+ CrossFadeHelper.fadeOut(mMediaHostContainer, darkAmount);
+ }
updateDark();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 66ea2ad..9b0ae6b 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -29,9 +29,12 @@
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import com.android.settingslib.Utils;
import com.android.systemui.Dumpable;
@@ -63,6 +66,7 @@
@NonNull private final KeyguardStateController mKeyguardStateController;
@NonNull private final FalsingManager mFalsingManager;
@NonNull private final AuthController mAuthController;
+ @NonNull private final AccessibilityManager mAccessibilityManager;
private boolean mHasUdfpsOrFaceAuthFeatures;
private boolean mUdfpsEnrolled;
@@ -93,19 +97,17 @@
@NonNull KeyguardStateController keyguardStateController,
@NonNull FalsingManager falsingManager,
@NonNull AuthController authController,
- @NonNull DumpManager dumpManager
+ @NonNull DumpManager dumpManager,
+ @NonNull AccessibilityManager accessibilityManager
) {
super(view);
- if (mView != null) {
- mView.setOnClickListener(v -> onAffordanceClick());
- mView.setOnLongClickListener(v -> onAffordanceClick());
- }
mStatusBarStateController = statusBarStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mAuthController = authController;
mKeyguardViewController = keyguardViewController;
mKeyguardStateController = keyguardStateController;
mFalsingManager = falsingManager;
+ mAccessibilityManager = accessibilityManager;
final Context context = view.getContext();
mButton = context.getResources().getDrawable(
@@ -122,6 +124,11 @@
}
@Override
+ protected void onInit() {
+ mView.setAccessibilityDelegate(mAccessibilityDelegate);
+ }
+
+ @Override
protected void onViewAttached() {
// we check this here instead of onInit since the FingeprintManager + FaceManager may not
// have started up yet onInit
@@ -163,6 +170,8 @@
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
mStatusBarStateController.addCallback(mStatusBarStateListener);
mKeyguardStateController.addCallback(mKeyguardStateCallback);
+ mAccessibilityManager.addTouchExplorationStateChangeListener(
+ mTouchExplorationStateChangeListener);
updateVisibility();
}
@@ -172,6 +181,8 @@
mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
mStatusBarStateController.removeCallback(mStatusBarStateListener);
mKeyguardStateController.removeCallback(mKeyguardStateCallback);
+ mAccessibilityManager.removeTouchExplorationStateChangeListener(
+ mTouchExplorationStateChangeListener);
}
public float getTop() {
@@ -210,20 +221,56 @@
mShowLockIcon = !mUdfpsEnrolled && !mCanDismissLockScreen && isLockScreen()
&& mFaceAuthEnrolled;
+ updateClickListener();
if (mShowButton) {
mView.setImageDrawable(mButton);
mView.setVisibility(View.VISIBLE);
+ mView.setContentDescription(getResources().getString(
+ R.string.accessibility_udfps_disabled_button));
} else if (mShowUnlockIcon) {
mView.setImageDrawable(mUnlockIcon);
mView.setVisibility(View.VISIBLE);
+ mView.setContentDescription(getResources().getString(
+ R.string.accessibility_unlock_button));
} else if (mShowLockIcon) {
mView.setImageDrawable(mLockIcon);
mView.setVisibility(View.VISIBLE);
+ mView.setContentDescription(getResources().getString(
+ R.string.accessibility_lock_icon));
} else {
mView.setVisibility(View.INVISIBLE);
+ mView.setContentDescription(null);
}
}
+ private final View.AccessibilityDelegate mAccessibilityDelegate =
+ new View.AccessibilityDelegate() {
+ private final AccessibilityNodeInfo.AccessibilityAction mAccessibilityAuthenticateHint =
+ new AccessibilityNodeInfo.AccessibilityAction(
+ AccessibilityNodeInfoCompat.ACTION_CLICK,
+ getResources().getString(R.string.accessibility_authenticate_hint));
+ private final AccessibilityNodeInfo.AccessibilityAction mAccessibilityEnterHint =
+ new AccessibilityNodeInfo.AccessibilityAction(
+ AccessibilityNodeInfoCompat.ACTION_CLICK,
+ getResources().getString(R.string.accessibility_enter_hint));
+ public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(v, info);
+ removeAllActions(info);
+ if (mShowButton || mShowLockIcon) {
+ info.addAction(mAccessibilityAuthenticateHint);
+ } else if (mShowUnlockIcon) {
+ info.addAction(mAccessibilityEnterHint);
+ }
+ }
+
+ private void removeAllActions(AccessibilityNodeInfo info) {
+ info.removeAction(mAccessibilityAuthenticateHint);
+ info.removeAction(mAccessibilityEnterHint);
+ info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
+ mView.setLongClickable(false);
+ }
+ };
+
private boolean isLockScreen() {
return !mIsDozing
&& !mIsBouncerShowing
@@ -231,6 +278,17 @@
&& mStatusBarState == StatusBarState.KEYGUARD;
}
+ private void updateClickListener() {
+ if (mView != null) {
+ mView.setOnClickListener(v -> onAffordanceClick());
+ if (mAccessibilityManager.isTouchExplorationEnabled()) {
+ mView.setOnLongClickListener(null);
+ } else {
+ mView.setOnLongClickListener(v -> onAffordanceClick());
+ }
+ }
+ }
+
@Override
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
pw.println(" mShowBouncerButton: " + mShowButton);
@@ -298,4 +356,7 @@
updateVisibility();
}
};
+
+ private final AccessibilityManager.TouchExplorationStateChangeListener
+ mTouchExplorationStateChangeListener = enabled -> updateClickListener();
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 7ebfb72..ee5fb31 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -28,7 +28,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.RectF;
@@ -55,6 +54,7 @@
import android.view.VelocityTracker;
import android.view.View;
import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.KeyguardUpdateMonitor;
@@ -108,6 +108,7 @@
@NonNull private final Handler mMainHandler;
@NonNull private final FalsingManager mFalsingManager;
@NonNull private final PowerManager mPowerManager;
+ @NonNull private final AccessibilityManager mAccessibilityManager;
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
// sensors, this, in addition to a lot of the code here, will be updated.
@VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps;
@@ -276,6 +277,13 @@
private final UdfpsView.OnTouchListener mOnTouchListener = (view, event) ->
onTouch(view, event, true);
+ @SuppressLint("ClickableViewAccessibility")
+ private final UdfpsView.OnHoverListener mOnHoverListener = (view, event) ->
+ onTouch(view, event, true);
+
+ private final AccessibilityManager.TouchExplorationStateChangeListener
+ mTouchExplorationStateChangeListener = enabled -> updateTouchListener();
+
/**
* @param x coordinate
* @param y coordinate
@@ -300,6 +308,7 @@
udfpsView.onTouchOutsideView();
break;
case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_HOVER_ENTER:
// To simplify the lifecycle of the velocity tracker, make sure it's never null
// after ACTION_DOWN, and always null after ACTION_CANCEL or ACTION_UP.
if (mVelocityTracker == null) {
@@ -322,6 +331,7 @@
break;
case MotionEvent.ACTION_MOVE:
+ case MotionEvent.ACTION_HOVER_MOVE:
final int idx = mActivePointerId == -1
? event.getPointerId(0)
: event.findPointerIndex(mActivePointerId);
@@ -388,6 +398,7 @@
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_HOVER_EXIT:
mActivePointerId = -1;
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
@@ -409,10 +420,9 @@
@Inject
public UdfpsController(@NonNull Context context,
- @Main Resources resources,
@NonNull LayoutInflater inflater,
@Nullable FingerprintManager fingerprintManager,
- WindowManager windowManager,
+ @NonNull WindowManager windowManager,
@NonNull StatusBarStateController statusBarStateController,
@Main DelayableExecutor fgExecutor,
@NonNull StatusBar statusBar,
@@ -421,7 +431,8 @@
@NonNull KeyguardUpdateMonitor keyguardUpdateMonitor,
@NonNull KeyguardViewMediator keyguardViewMediator,
@NonNull FalsingManager falsingManager,
- @NonNull PowerManager powerManager) {
+ @NonNull PowerManager powerManager,
+ @NonNull AccessibilityManager accessibilityManager) {
mContext = context;
// TODO (b/185124905): inject main handler and vibrator once done prototyping
mMainHandler = new Handler(Looper.getMainLooper());
@@ -440,6 +451,7 @@
mKeyguardViewMediator = keyguardViewMediator;
mFalsingManager = falsingManager;
mPowerManager = powerManager;
+ mAccessibilityManager = accessibilityManager;
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
@@ -577,7 +589,9 @@
mView.setAnimationViewController(animation);
mWindowManager.addView(mView, computeLayoutParams(animation));
- mView.setOnTouchListener(mOnTouchListener);
+ mAccessibilityManager.addTouchExplorationStateChangeListener(
+ mTouchExplorationStateChangeListener);
+ updateTouchListener();
} catch (RuntimeException e) {
Log.e(TAG, "showUdfpsOverlay | failed to add window", e);
}
@@ -650,7 +664,10 @@
onFingerUp();
mWindowManager.removeView(mView);
mView.setOnTouchListener(null);
+ mView.setOnHoverListener(null);
mView.setAnimationViewController(null);
+ mAccessibilityManager.removeTouchExplorationStateChangeListener(
+ mTouchExplorationStateChangeListener);
mView = null;
} else {
Log.v(TAG, "hideUdfpsOverlay | the overlay is already hidden");
@@ -758,4 +775,18 @@
return defaultEffect;
}
}
+
+ private void updateTouchListener() {
+ if (mView == null) {
+ return;
+ }
+
+ if (mAccessibilityManager.isTouchExplorationEnabled()) {
+ mView.setOnHoverListener(mOnHoverListener);
+ mView.setOnTouchListener(null);
+ } else {
+ mView.setOnHoverListener(null);
+ mView.setOnTouchListener(mOnTouchListener);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index 9e621b3..2808450 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -197,31 +197,25 @@
public boolean isFalseTouch(@Classifier.InteractionType int interactionType) {
mPriorInteractionType = interactionType;
if (skipFalsing()) {
+ mPriorResults = getPassedResult(1);
+ logDebug("Skipped falsing");
return false;
}
- final boolean booleanResult;
+ final boolean[] localResult = {false};
+ mPriorResults = mClassifiers.stream().map(falsingClassifier -> {
+ FalsingClassifier.Result r = falsingClassifier.classifyGesture(
+ interactionType,
+ mHistoryTracker.falseBelief(),
+ mHistoryTracker.falseConfidence());
+ localResult[0] |= r.isFalse();
- if (!mTestHarness && !mDataProvider.isJustUnlockedWithFace() && !mDockManager.isDocked()) {
- final boolean[] localResult = {false};
- mPriorResults = mClassifiers.stream().map(falsingClassifier -> {
- FalsingClassifier.Result r = falsingClassifier.classifyGesture(
- interactionType,
- mHistoryTracker.falseBelief(),
- mHistoryTracker.falseConfidence());
- localResult[0] |= r.isFalse();
+ return r;
+ }).collect(Collectors.toList());
- return r;
- }).collect(Collectors.toList());
- booleanResult = localResult[0];
- } else {
- booleanResult = false;
- mPriorResults = Collections.singleton(FalsingClassifier.Result.passed(1));
- }
+ logDebug("False Gesture: " + localResult[0]);
- logDebug("False Gesture: " + booleanResult);
-
- return booleanResult;
+ return localResult[0];
}
@Override
@@ -236,6 +230,8 @@
@Override
public boolean isFalseTap(@Penalty int penalty) {
if (skipFalsing()) {
+ mPriorResults = getPassedResult(1);
+ logDebug("Skipped falsing");
return false;
}
@@ -264,7 +260,7 @@
if (!singleTapResult.isFalse()) {
if (mDataProvider.isJustUnlockedWithFace()) {
// Immediately pass if a face is detected.
- mPriorResults = Collections.singleton(FalsingClassifier.Result.passed(1));
+ mPriorResults = getPassedResult(1);
logDebug("False Single Tap: false (face detected)");
return false;
} else if (!isFalseDoubleTap()) {
@@ -281,7 +277,7 @@
mFalsingTapListeners.forEach(FalsingTapListener::onDoubleTapRequired);
return true;
} else {
- mPriorResults = Collections.singleton(FalsingClassifier.Result.passed(0.1));
+ mPriorResults = getPassedResult(0.1);
logDebug("False Single Tap: false (default)");
return false;
}
@@ -296,6 +292,8 @@
@Override
public boolean isFalseDoubleTap() {
if (skipFalsing()) {
+ mPriorResults = getPassedResult(1);
+ logDebug("Skipped falsing");
return false;
}
@@ -309,7 +307,10 @@
}
private boolean skipFalsing() {
- return !mKeyguardStateController.isShowing();
+ return !mKeyguardStateController.isShowing()
+ || mTestHarness
+ || mDataProvider.isJustUnlockedWithFace()
+ || mDockManager.isDocked();
}
@Override
@@ -411,6 +412,10 @@
mHistoryTracker.removeBeliefListener(mBeliefListener);
}
+ private static Collection<FalsingClassifier.Result> getPassedResult(double confidence) {
+ return Collections.singleton(FalsingClassifier.Result.passed(confidence));
+ }
+
static void logDebug(String msg) {
logDebug(msg, null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
index 6fb8650..2ea139e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
@@ -17,6 +17,7 @@
package com.android.systemui.media
import android.view.View
+import android.view.ViewGroup
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.media.dagger.MediaModule.KEYGUARD
import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -29,8 +30,8 @@
import javax.inject.Named
/**
- * A class that controls the media notifications on the lock screen, handles its visibility and
- * is responsible for the embedding of he media experience.
+ * Controls the media notifications on the lock screen, handles its visibility and placement -
+ * switches media player positioning between split pane container vs single pane container
*/
@SysUISingleton
class KeyguardMediaController @Inject constructor(
@@ -43,46 +44,114 @@
init {
statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
override fun onStateChanged(newState: Int) {
- updateVisibility()
+ refreshMediaPosition()
+ }
+
+ override fun onDozingChanged(isDozing: Boolean) {
+ if (!isDozing) {
+ mediaHost.visible = true
+ refreshMediaPosition()
+ }
}
})
}
var visibilityChangedListener: ((Boolean) -> Unit)? = null
- var view: MediaHeaderView? = null
- private set
/**
- * Attach this controller to a media view, initializing its state
+ * single pane media container placed at the top of the notifications list
*/
- fun attach(mediaView: MediaHeaderView) {
- view = mediaView
+ var singlePaneContainer: MediaHeaderView? = null
+ private set
+ private var splitShadeContainer: ViewGroup? = null
+ private var useSplitShadeContainer: () -> Boolean = { false }
+
+ /**
+ * Attaches media container in single pane mode, situated at the top of the notifications list
+ */
+ fun attachSinglePaneContainer(mediaView: MediaHeaderView?) {
+ singlePaneContainer = mediaView
// First let's set the desired state that we want for this host
- mediaHost.addVisibilityChangeListener { updateVisibility() }
- mediaHost.expansion = 0.0f
+ mediaHost.expansion = MediaHostState.COLLAPSED
mediaHost.showsOnlyActiveMedia = true
mediaHost.falsingProtectionNeeded = true
// Let's now initialize this view, which also creates the host view for us.
mediaHost.init(MediaHierarchyManager.LOCATION_LOCKSCREEN)
- mediaView.setContentView(mediaHost.hostView)
-
- // Ensure the visibility is correct
- updateVisibility()
+ // Required to show it for the first time, afterwards visibility is managed automatically
+ mediaHost.visible = true
+ mediaHost.addVisibilityChangeListener { visible ->
+ refreshMediaPosition()
+ if (visible) {
+ mediaHost.hostView.layoutParams.apply {
+ height = ViewGroup.LayoutParams.WRAP_CONTENT
+ width = ViewGroup.LayoutParams.MATCH_PARENT
+ }
+ }
+ }
+ refreshMediaPosition()
}
- private fun updateVisibility() {
+ /**
+ * Attaches media container in split shade mode, situated to the left of notifications
+ */
+ fun attachSplitShadeContainer(container: ViewGroup, useContainer: () -> Boolean) {
+ splitShadeContainer = container
+ useSplitShadeContainer = useContainer
+ }
+
+ fun refreshMediaPosition() {
val keyguardOrUserSwitcher = (statusBarStateController.state == StatusBarState.KEYGUARD ||
statusBarStateController.state == StatusBarState.FULLSCREEN_USER_SWITCHER)
+ // mediaHost.visible required for proper animations handling
val shouldBeVisible = mediaHost.visible &&
!bypassController.bypassEnabled &&
keyguardOrUserSwitcher &&
notifLockscreenUserManager.shouldShowLockscreenNotifications()
- val previousVisibility = view?.visibility ?: View.GONE
- val newVisibility = if (shouldBeVisible) View.VISIBLE else View.GONE
+ if (shouldBeVisible) {
+ showMediaPlayer()
+ } else {
+ hideMediaPlayer()
+ }
+ }
+
+ private fun showMediaPlayer() {
+ if (useSplitShadeContainer()) {
+ showMediaPlayer(
+ activeContainer = splitShadeContainer,
+ inactiveContainer = singlePaneContainer)
+ } else {
+ showMediaPlayer(
+ activeContainer = singlePaneContainer,
+ inactiveContainer = splitShadeContainer)
+ }
+ }
+
+ private fun showMediaPlayer(activeContainer: ViewGroup?, inactiveContainer: ViewGroup?) {
+ if (inactiveContainer?.childCount == 1) {
+ inactiveContainer.removeAllViews()
+ }
+ // might be called a few times for the same view, no need to add hostView again
+ if (activeContainer?.childCount == 0) {
+ activeContainer.addView(mediaHost.hostView)
+ }
+ setVisibility(activeContainer, View.VISIBLE)
+ setVisibility(inactiveContainer, View.GONE)
+ }
+
+ private fun hideMediaPlayer() {
+ if (useSplitShadeContainer()) {
+ setVisibility(splitShadeContainer, View.GONE)
+ } else {
+ setVisibility(singlePaneContainer, View.GONE)
+ }
+ }
+
+ private fun setVisibility(view: ViewGroup?, newVisibility: Int) {
+ val previousVisibility = view?.visibility
view?.visibility = newVisibility
if (previousVisibility != newVisibility) {
- visibilityChangedListener?.invoke(shouldBeVisible)
+ visibilityChangedListener?.invoke(newVisibility == View.VISIBLE)
}
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index e6eb317..473db9f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -532,7 +532,10 @@
mediaCoverImageView.setImageIcon(recommendation.getIcon());
// Set up the click listener if applicable.
- setSmartspaceRecItemOnClickListener(mediaCoverImageView, recommendation,
+ setSmartspaceRecItemOnClickListener(
+ mediaCoverImageView,
+ recommendation,
+ target.getSmartspaceTargetId(),
view -> mMediaDataManagerLazy
.get()
.dismissSmartspaceRecommendation(0L /* delay */));
@@ -640,6 +643,7 @@
private void setSmartspaceRecItemOnClickListener(
@NonNull View view,
@NonNull SmartspaceAction action,
+ @NonNull String targetId,
@Nullable View.OnClickListener callback) {
if (view == null || action == null || action.getIntent() == null) {
Log.e(TAG, "No tap action can be set up");
@@ -647,6 +651,16 @@
}
view.setOnClickListener(v -> {
+ // When media recommendation card is shown, there could be only one card.
+ SysUiStatsLog.write(SysUiStatsLog.SMARTSPACE_CARD_REPORTED,
+ 760, // SMARTSPACE_CARD_CLICK
+ targetId.hashCode(),
+ SysUiStatsLog
+ .SMART_SPACE_CARD_REPORTED__CARD_TYPE__HEADPHONE_MEDIA_RECOMMENDATIONS,
+ getSurfaceForSmartspaceLogging(mMediaViewController.getCurrentEndLocation()),
+ /* rank */ 1,
+ /* cardinality */ 1);
+
mActivityStarter.postStartActivityDismissingKeyguard(
action.getIntent(),
0 /* delay */,
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
index 8c12a30..2347481 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
@@ -264,15 +264,20 @@
*/
interface MediaHostState {
+ companion object {
+ const val EXPANDED: Float = 1.0f
+ const val COLLAPSED: Float = 0.0f
+ }
+
/**
- * The last measurement input that this state was measured with. Infers with and height of
+ * The last measurement input that this state was measured with. Infers width and height of
* the players.
*/
var measurementInput: MeasurementInput?
/**
- * The expansion of the player, 0 for fully collapsed (up to 3 actions), 1 for fully expanded
- * (up to 5 actions.)
+ * The expansion of the player, [COLLAPSED] for fully collapsed (up to 3 actions),
+ * [EXPANDED] for fully expanded (up to 5 actions).
*/
var expansion: Float
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index f89e70a..efa1a13 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -326,6 +326,7 @@
super.onConfigurationChanged(newConfig);
mOnConfigurationChangedListeners.forEach(
listener -> listener.onConfigurationChange(newConfig));
+ switchSecurityFooter();
}
@Override
@@ -364,19 +365,25 @@
switchToParent((View) newLayout, parent, index);
index++;
- if (mSecurityFooter != null) {
- if (mUsingHorizontalLayout && mHeaderContainer != null) {
- // Adding the security view to the header, that enables us to avoid scrolling
- switchToParent(mSecurityFooter, mHeaderContainer, 0);
- } else {
- switchToParent(mSecurityFooter, parent, index);
- index++;
- }
- }
-
if (mFooter != null) {
// Then the footer with the settings
switchToParent(mFooter, parent, index);
+ index++;
+ }
+
+ // The security footer is switched on orientation changes
+ }
+
+ private void switchSecurityFooter() {
+ if (mSecurityFooter != null) {
+ if (mContext.getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_LANDSCAPE && mHeaderContainer != null
+ && !mSecurityFooter.getParent().equals(mHeaderContainer)) {
+ // Adding the security view to the header, that enables us to avoid scrolling
+ switchToParent(mSecurityFooter, mHeaderContainer, 0);
+ } else {
+ switchToParent(mSecurityFooter, this, -1);
+ }
}
}
@@ -668,6 +675,7 @@
public void setSecurityFooter(View view) {
mSecurityFooter = view;
+ switchSecurityFooter();
}
void setUsingHorizontalLayout(boolean horizontal, ViewGroup mediaHostView, boolean force,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 670475f..baf781d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -16,6 +16,8 @@
package com.android.systemui.qs;
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static com.android.systemui.qs.dagger.QSFragmentModule.QS_SECURITY_FOOTER_VIEW;
@@ -26,6 +28,8 @@
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.UserInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
@@ -68,7 +72,6 @@
private final View mRootView;
private final TextView mFooterText;
- private final ImageView mFooterIcon;
private final ImageView mPrimaryFooterIcon;
private final Context mContext;
private final Callback mCallback = new Callback();
@@ -83,7 +86,6 @@
private boolean mIsVisible;
private CharSequence mFooterTextContent = null;
- private int mFooterTextId;
private int mFooterIconId;
private Drawable mPrimaryFooterIconDrawable;
@@ -94,7 +96,6 @@
mRootView = rootView;
mRootView.setOnClickListener(this);
mFooterText = mRootView.findViewById(R.id.footer_text);
- mFooterIcon = mRootView.findViewById(R.id.footer_icon);
mPrimaryFooterIcon = mRootView.findViewById(R.id.primary_footer_icon);
mFooterIconId = R.drawable.ic_info_outline;
mContext = rootView.getContext();
@@ -120,6 +121,23 @@
public void onConfigurationChanged() {
FontSizeUtils.updateFontSize(mFooterText, R.dimen.qs_tile_text_size);
+
+ Resources r = mContext.getResources();
+
+ mFooterText.setMaxLines(r.getInteger(R.integer.qs_security_footer_maxLines));
+ int padding = r.getDimensionPixelSize(R.dimen.qs_footer_padding);
+ mRootView.setPaddingRelative(padding, padding, padding, padding);
+
+ int verticalMargin = r.getDimensionPixelSize(R.dimen.qs_security_footer_vertical_margin);
+ ViewGroup.MarginLayoutParams lp =
+ (ViewGroup.MarginLayoutParams) mRootView.getLayoutParams();
+ lp.topMargin = verticalMargin;
+ lp.bottomMargin = verticalMargin;
+ lp.width = r.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT
+ ? MATCH_PARENT : WRAP_CONTENT;
+ mRootView.setLayoutParams(lp);
+
+ mRootView.setBackground(mContext.getDrawable(R.drawable.qs_security_footer_background));
}
public View getView() {
@@ -189,7 +207,6 @@
}
if (mFooterIconId != footerIconId) {
mFooterIconId = footerIconId;
- mMainHandler.post(mUpdateIcon);
}
// Update the primary icon
@@ -315,7 +332,7 @@
mDialog.setView(createDialogView());
mDialog.show();
- mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
+ mDialog.getWindow().setLayout(MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
@@ -575,19 +592,14 @@
== DEVICE_OWNER_TYPE_FINANCED;
}
- private final Runnable mUpdateIcon = new Runnable() {
- @Override
- public void run() {
- mFooterIcon.setImageResource(mFooterIconId);
- }
- };
-
private final Runnable mUpdatePrimaryIcon = new Runnable() {
@Override
public void run() {
- mPrimaryFooterIcon.setVisibility(mPrimaryFooterIconDrawable != null
- ? View.VISIBLE : View.GONE);
- mPrimaryFooterIcon.setImageDrawable(mPrimaryFooterIconDrawable);
+ if (mPrimaryFooterIconDrawable != null) {
+ mPrimaryFooterIcon.setImageDrawable(mPrimaryFooterIconDrawable);
+ } else {
+ mPrimaryFooterIcon.setImageResource(mFooterIconId);
+ }
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
index b0a9c25..34aac49 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java
@@ -136,7 +136,7 @@
@QSThemedContext LayoutInflater layoutInflater,
QSPanel qsPanel
) {
- return layoutInflater.inflate(R.layout.quick_settings_footer, qsPanel, false);
+ return layoutInflater.inflate(R.layout.quick_settings_security_footer, qsPanel, false);
}
/** */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
index 9e70f0a..caba3ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
@@ -37,8 +37,9 @@
private ImageView mConversationIconView;
private TextView mConversationSenderName;
private View mConversationFacePile;
- private int mConversationIconSize;
+ private int mSingleAvatarSize;
private int mFacePileSize;
+ private int mFacePileAvatarSize;
private int mFacePileProtectionWidth;
public HybridConversationNotificationView(Context context) {
@@ -67,7 +68,9 @@
mConversationSenderName = requireViewById(R.id.conversation_notification_sender);
mFacePileSize = getResources()
.getDimensionPixelSize(R.dimen.conversation_single_line_face_pile_size);
- mConversationIconSize = getResources()
+ mFacePileAvatarSize = getResources()
+ .getDimensionPixelSize(R.dimen.conversation_single_line_face_pile_avatar_size);
+ mSingleAvatarSize = getResources()
.getDimensionPixelSize(R.dimen.conversation_single_line_avatar_size);
mFacePileProtectionWidth = getResources().getDimensionPixelSize(
R.dimen.conversation_single_line_face_pile_protection_width);
@@ -89,6 +92,7 @@
mConversationFacePile.setVisibility(GONE);
mConversationIconView.setVisibility(VISIBLE);
mConversationIconView.setImageIcon(conversationIcon);
+ setSize(mConversationIconView, mSingleAvatarSize);
} else {
// If there isn't an icon, generate a "face pile" based on the sender avatars
mConversationIconView.setVisibility(GONE);
@@ -104,9 +108,9 @@
com.android.internal.R.id.conversation_face_pile_top);
conversationLayout.bindFacePile(facePileBottomBg, facePileBottom, facePileTop);
setSize(mConversationFacePile, mFacePileSize);
- setSize(facePileBottom, mConversationIconSize);
- setSize(facePileTop, mConversationIconSize);
- setSize(facePileBottomBg, mConversationIconSize + 2 * mFacePileProtectionWidth);
+ setSize(facePileBottom, mFacePileAvatarSize);
+ setSize(facePileTop, mFacePileAvatarSize);
+ setSize(facePileBottomBg, mFacePileAvatarSize + 2 * mFacePileProtectionWidth);
mTransformationHelper.addViewTransformingToSimilar(facePileTop);
mTransformationHelper.addViewTransformingToSimilar(facePileBottom);
mTransformationHelper.addViewTransformingToSimilar(facePileBottomBg);
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 884ad8d..fe4ea28 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
@@ -1258,7 +1258,7 @@
RemoteInputView riv = RemoteInputView.inflate(
mContext, actionContainer, entry, mRemoteInputController);
- riv.setVisibility(View.INVISIBLE);
+ riv.setVisibility(View.GONE);
actionContainer.addView(riv, new LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 15ca24e..8ee9134 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -20,14 +20,12 @@
import android.app.Notification;
import android.content.Context;
-import android.content.res.ColorStateList;
import android.util.ArraySet;
import android.util.Pair;
import android.view.NotificationHeaderView;
import android.view.NotificationTopLineView;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewGroup.MarginLayoutParams;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import android.widget.ImageButton;
@@ -168,53 +166,6 @@
}
}
- public void applyConversationSkin() {
- if (mAppNameText != null) {
- final ColorStateList colors = mAppNameText.getTextColors();
- mAppNameText.setTextAppearance(
- com.android.internal.R.style
- .TextAppearance_DeviceDefault_Notification_Conversation_AppName);
- mAppNameText.setTextColor(colors);
- MarginLayoutParams layoutParams = (MarginLayoutParams) mAppNameText.getLayoutParams();
- layoutParams.setMarginStart(0);
- }
- if (mNotificationTopLine != null) {
- int paddingStart = mNotificationTopLine.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.conversation_content_start);
- mNotificationTopLine.setPaddingStart(paddingStart);
- }
- if (mIcon != null) {
- MarginLayoutParams layoutParams = (MarginLayoutParams) mIcon.getLayoutParams();
- int marginStart = mIcon.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.conversation_icon_circle_start);
- layoutParams.setMarginStart(marginStart);
- }
- }
-
- public void clearConversationSkin() {
- if (mAppNameText != null) {
- final ColorStateList colors = mAppNameText.getTextColors();
- mAppNameText.setTextAppearance(
- com.android.internal.R.style.TextAppearance_DeviceDefault_Notification_Info);
- mAppNameText.setTextColor(colors);
- MarginLayoutParams layoutParams = (MarginLayoutParams) mAppNameText.getLayoutParams();
- final int marginStart = mAppNameText.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_header_app_name_margin_start);
- layoutParams.setMarginStart(marginStart);
- }
- if (mNotificationTopLine != null) {
- int paddingStart = mNotificationTopLine.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin_start);
- mNotificationTopLine.setPaddingStart(paddingStart);
- }
- if (mIcon != null) {
- MarginLayoutParams layoutParams = (MarginLayoutParams) mIcon.getLayoutParams();
- int marginStart = mIcon.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_icon_circle_start);
- layoutParams.setMarginStart(marginStart);
- }
- }
-
/**
* Adds the remaining TransformTypes to the TransformHelper. This is done to make sure that each
* child is faded automatically and doesn't have to be manually added.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java
index 040f707..0247a99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaHeaderView.java
@@ -19,7 +19,6 @@
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.util.AttributeSet;
-import android.view.ViewGroup;
import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -43,11 +42,4 @@
public void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear) {
// No animation, it doesn't need it, this would be local
}
-
- public void setContentView(ViewGroup contentView) {
- addView(contentView);
- ViewGroup.LayoutParams layoutParams = contentView.getLayoutParams();
- layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
- layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 5f3933b..99fe541 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -43,7 +43,6 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.HybridGroupManager;
import com.android.systemui.statusbar.notification.row.HybridNotificationView;
-import com.android.systemui.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
import java.util.ArrayList;
@@ -336,15 +335,6 @@
}
mNotificationHeaderWrapper.setExpanded(mChildrenExpanded);
mNotificationHeaderWrapper.onContentUpdated(mContainingNotification);
- if (mNotificationHeaderWrapper instanceof NotificationHeaderViewWrapper) {
- NotificationHeaderViewWrapper headerWrapper =
- (NotificationHeaderViewWrapper) mNotificationHeaderWrapper;
- if (isConversation) {
- headerWrapper.applyConversationSkin();
- } else {
- headerWrapper.clearConversationSkin();
- }
- }
recreateLowPriorityHeader(builder, isConversation);
updateHeaderVisibility(false /* animate */);
updateChildrenAppearance();
@@ -378,15 +368,6 @@
header.reapply(getContext(), mNotificationHeaderLowPriority);
}
mNotificationHeaderWrapperLowPriority.onContentUpdated(mContainingNotification);
- if (mNotificationHeaderWrapper instanceof NotificationHeaderViewWrapper) {
- NotificationHeaderViewWrapper headerWrapper =
- (NotificationHeaderViewWrapper) mNotificationHeaderWrapper;
- if (isConversation) {
- headerWrapper.applyConversationSkin();
- } else {
- headerWrapper.clearConversationSkin();
- }
- }
resetHeaderVisibilityIfNeeded(mNotificationHeaderLowPriority, calculateDesiredHeader());
} else {
removeView(mNotificationHeaderLowPriority);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
index b06f7d2..45ce20a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
@@ -138,7 +138,7 @@
incomingHeaderController.reinflateView(parent)
mediaControlsView =
reinflateView(mediaControlsView, layoutInflater, R.layout.keyguard_media_header)
- .also(keyguardMediaController::attach)
+ keyguardMediaController.attachSinglePaneContainer(mediaControlsView)
}
override fun beginsSection(view: View, previous: View?): Boolean =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 36a370c..527443e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -708,9 +708,10 @@
mView.setKeyguardMediaControllorVisible(visible);
if (visible) {
mView.generateAddAnimation(
- mKeyguardMediaController.getView(), false /*fromMoreCard */);
+ mKeyguardMediaController.getSinglePaneContainer(),
+ false /*fromMoreCard */);
} else {
- mView.generateRemoveAnimation(mKeyguardMediaController.getView());
+ mView.generateRemoveAnimation(mKeyguardMediaController.getSinglePaneContainer());
}
mView.requestChildrenUpdate();
return Unit.INSTANCE;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 481b2db..069c197 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -155,6 +155,8 @@
private int mLockScreenMode;
+ private boolean mIsSplitShade;
+
/**
* Refreshes the dimension values.
*/
@@ -180,7 +182,7 @@
int keyguardStatusHeight, int userSwitchHeight, int clockPreferredY,
int userSwitchPreferredY, boolean hasCustomClock, boolean hasVisibleNotifs, float dark,
float emptyDragAmount, boolean bypassEnabled, int unlockedStackScrollerPadding,
- float qsExpansion, int cutoutTopInset) {
+ float qsExpansion, int cutoutTopInset, boolean isSplitShade) {
mMinTopMargin = keyguardStatusBarHeaderHeight + Math.max(mContainerTopPadding,
userSwitchHeight);
mMaxShadeBottom = maxShadeBottom;
@@ -199,6 +201,7 @@
mUnlockedStackScrollerPadding = unlockedStackScrollerPadding;
mQsExpansion = qsExpansion;
mCutoutTopInset = cutoutTopInset;
+ mIsSplitShade = isSplitShade;
}
public void run(Result result) {
@@ -208,14 +211,23 @@
result.clockYFullyDozing = getClockY(
1.0f /* panelExpansion */, 1.0f /* darkAmount */);
result.clockAlpha = getClockAlpha(y);
- result.stackScrollerPadding = mBypassEnabled ? mUnlockedStackScrollerPadding
- : y + mKeyguardStatusHeight;
+ result.stackScrollerPadding = getStackScrollerPadding(y);
result.stackScrollerPaddingExpanded = mBypassEnabled ? mUnlockedStackScrollerPadding
: getClockY(1.0f, mDarkAmount) + mKeyguardStatusHeight;
result.clockX = (int) interpolate(0, burnInPreventionOffsetX(), mDarkAmount);
result.clockScale = interpolate(getBurnInScale(), 1.0f, 1.0f - mDarkAmount);
}
+ private int getStackScrollerPadding(int clockYPosition) {
+ if (mBypassEnabled) {
+ return mUnlockedStackScrollerPadding;
+ } else if (mIsSplitShade) {
+ return clockYPosition;
+ } else {
+ return clockYPosition + mKeyguardStatusHeight;
+ }
+ }
+
/**
* Update lock screen mode for testing different layouts
*/
@@ -232,15 +244,11 @@
return mHeight / 2 - mKeyguardStatusHeight - mClockNotificationsMargin;
}
- private int getPreferredClockY() {
- return mClockPreferredY;
- }
-
private int getExpandedPreferredClockY() {
if (mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) {
return mMinTopMargin + mUserSwitchHeight;
}
- return (mHasCustomClock && (!mHasVisibleNotifs || mBypassEnabled)) ? getPreferredClockY()
+ return (mHasCustomClock && (!mHasVisibleNotifs || mBypassEnabled)) ? mClockPreferredY
: getExpandedClockPosition();
}
@@ -271,7 +279,7 @@
private int getClockY(float panelExpansion, float darkAmount) {
// Dark: Align the bottom edge of the clock at about half of the screen:
- float clockYDark = (mHasCustomClock ? getPreferredClockY() : getMaxClockY())
+ float clockYDark = (mHasCustomClock ? mClockPreferredY : getMaxClockY())
+ burnInPreventionOffsetY();
clockYDark = MathUtils.max(0, clockYDark);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index d85be1d..8574830 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -28,6 +28,7 @@
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
+import static com.android.systemui.util.Utils.shouldUseSplitNotificationShade;
import static java.lang.Float.isNaN;
@@ -99,6 +100,7 @@
import com.android.systemui.doze.DozeLog;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
+import com.android.systemui.media.KeyguardMediaController;
import com.android.systemui.media.MediaDataManager;
import com.android.systemui.media.MediaHierarchyManager;
import com.android.systemui.plugins.FalsingManager;
@@ -527,6 +529,7 @@
private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
private int mScrimCornerRadius;
+ private KeyguardMediaController mKeyguardMediaController;
private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() {
@Override
@@ -597,6 +600,7 @@
LockIconViewController lockIconViewController,
FeatureFlags featureFlags,
QuickAccessWalletClient quickAccessWalletClient,
+ KeyguardMediaController keyguardMediaController,
@Main Executor uiExecutor) {
super(view, falsingManager, dozeLog, keyguardStateController,
(SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
@@ -604,6 +608,7 @@
statusBarTouchableRegionManager, ambientState);
mView = view;
mVibratorHelper = vibratorHelper;
+ mKeyguardMediaController = keyguardMediaController;
mMetricsLogger = metricsLogger;
mActivityManager = activityManager;
mConfigurationController = configurationController;
@@ -771,7 +776,6 @@
});
mView.setAccessibilityDelegate(mAccessibilityDelegate);
- // dynamically apply the split shade value overrides.
if (mShouldUseSplitNotificationShade) {
updateResources();
}
@@ -889,13 +893,17 @@
constraintSet.connect(
R.id.notification_stack_scroller, START,
R.id.qs_edge_guideline, START);
+ constraintSet.connect(R.id.keyguard_status_view, END, R.id.qs_edge_guideline, END);
} else {
constraintSet.connect(R.id.qs_frame, END, PARENT_ID, END);
constraintSet.connect(R.id.notification_stack_scroller, START, PARENT_ID, START);
+ constraintSet.connect(R.id.keyguard_status_view, END, PARENT_ID, END);
}
constraintSet.getConstraint(R.id.notification_stack_scroller).layout.mWidth = panelWidth;
constraintSet.getConstraint(R.id.qs_frame).layout.mWidth = qsWidth;
constraintSet.applyTo(mNotificationContainerParent);
+
+ mKeyguardMediaController.refreshMediaPosition();
}
private static void ensureAllViewsHaveIds(ViewGroup parentView) {
@@ -929,12 +937,18 @@
private void reInflateViews() {
if (DEBUG) Log.d(TAG, "reInflateViews");
// Re-inflate the status view group.
- KeyguardStatusView keyguardStatusView = mView.findViewById(R.id.keyguard_status_view);
- int index = mView.indexOfChild(keyguardStatusView);
- mView.removeView(keyguardStatusView);
+ KeyguardStatusView keyguardStatusView =
+ mNotificationContainerParent.findViewById(R.id.keyguard_status_view);
+ int statusIndex = mNotificationContainerParent.indexOfChild(keyguardStatusView);
+ mNotificationContainerParent.removeView(keyguardStatusView);
keyguardStatusView = (KeyguardStatusView) mLayoutInflater.inflate(
- R.layout.keyguard_status_view, mView, false);
- mView.addView(keyguardStatusView, index);
+ R.layout.keyguard_status_view, mNotificationContainerParent, false);
+ mNotificationContainerParent.addView(keyguardStatusView, statusIndex);
+ attachSplitShadeMediaPlayerContainer(
+ keyguardStatusView.findViewById(R.id.status_view_media_container));
+
+ // we need to update KeyguardStatusView constraints after reinflating it
+ updateResources();
// Re-inflate the keyguard user switcher group.
boolean isUserSwitcherEnabled = mUserManager.isUserSwitcherEnabled();
@@ -956,11 +970,11 @@
showKeyguardUserSwitcher /* enabled */);
mBigClockContainer.removeAllViews();
- updateViewControllers(
- keyguardStatusView, userAvatarView, mKeyguardStatusBar, keyguardUserSwitcherView);
+ updateViewControllers(mView.findViewById(R.id.keyguard_status_view), userAvatarView,
+ mKeyguardStatusBar, keyguardUserSwitcherView);
// Update keyguard bottom area
- index = mView.indexOfChild(mKeyguardBottomArea);
+ int index = mView.indexOfChild(mKeyguardBottomArea);
mView.removeView(mKeyguardBottomArea);
KeyguardBottomAreaView oldBottomArea = mKeyguardBottomArea;
mKeyguardBottomArea = (KeyguardBottomAreaView) mLayoutInflater.inflate(
@@ -998,6 +1012,11 @@
setKeyguardBottomAreaVisibility(mBarState, false);
}
+ private void attachSplitShadeMediaPlayerContainer(FrameLayout container) {
+ mKeyguardMediaController.attachSplitShadeContainer(container,
+ () -> mShouldUseSplitNotificationShade);
+ }
+
private void initBottomArea() {
mAffordanceHelper = new KeyguardAffordanceHelper(
mKeyguardAffordanceHelperCallback, mView.getContext(), mFalsingManager);
@@ -1110,7 +1129,8 @@
hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount,
bypassEnabled, getUnlockedStackScrollerPadding(),
getQsExpansionFraction(),
- mDisplayCutoutTopInset);
+ mDisplayCutoutTopInset,
+ shouldUseSplitNotificationShade(mFeatureFlags, mResources));
mClockPositionAlgorithm.run(mClockPositionResult);
mKeyguardStatusViewController.updatePosition(
mClockPositionResult.clockX, mClockPositionResult.clockY,
diff --git a/packages/SystemUI/src/com/android/systemui/util/DualHeightHorizontalLinearLayout.kt b/packages/SystemUI/src/com/android/systemui/util/DualHeightHorizontalLinearLayout.kt
new file mode 100644
index 0000000..0e04871
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/DualHeightHorizontalLinearLayout.kt
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util
+
+import android.content.Context
+import android.content.res.Configuration
+import android.util.AttributeSet
+import android.util.DisplayMetrics
+import android.util.TypedValue
+import android.widget.LinearLayout
+import android.widget.TextView
+import com.android.systemui.R
+
+/**
+ * Horizontal [LinearLayout] to contain some text.
+ *
+ * The height of this container can alternate between two different heights, depending on whether
+ * the text takes one line or more.
+ *
+ * When the text takes multiple lines, it will use the values in the regular attributes (`padding`,
+ * `layout_height`). The single line behavior must be set in XML.
+ *
+ * XML attributes for single line behavior:
+ * * `systemui:textViewId`: set the id for the [TextView] that determines the height of the
+ * container
+ * * `systemui:singleLineHeight`: sets the height of the view when the text takes up only one line.
+ * By default, it will use [getMinimumHeight].
+ * * `systemui:singleLineVerticalPadding`: sets the padding (top and bottom) when then text takes up
+ * only one line. By default, it is 0.
+ *
+ * All dimensions are updated when configuration changes.
+ */
+class DualHeightHorizontalLinearLayout @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttrs: Int = 0,
+ defStyleRes: Int = 0
+) : LinearLayout(context, attrs, defStyleAttrs, defStyleRes) {
+
+ private val singleLineHeightValue: TypedValue?
+ private var singleLineHeightPx = 0
+
+ private val singleLineVerticalPaddingValue: TypedValue?
+ private var singleLineVerticalPaddingPx = 0
+
+ private val textViewId: Int
+ private var textView: TextView? = null
+
+ private val displayMetrics: DisplayMetrics
+ get() = context.resources.displayMetrics
+
+ private var initialPadding = mPaddingTop // All vertical padding is the same
+
+ init {
+ if (orientation != HORIZONTAL) {
+ throw IllegalStateException("This view should always have horizontal orientation")
+ }
+
+ val ta = context.obtainStyledAttributes(
+ attrs,
+ R.styleable.DualHeightHorizontalLinearLayout, defStyleAttrs, defStyleRes
+ )
+
+ val tempHeight = TypedValue()
+ singleLineHeightValue = if (
+ ta.hasValue(R.styleable.DualHeightHorizontalLinearLayout_singleLineHeight)
+ ) {
+ ta.getValue(R.styleable.DualHeightHorizontalLinearLayout_singleLineHeight, tempHeight)
+ tempHeight
+ } else {
+ null
+ }
+
+ val tempPadding = TypedValue()
+ singleLineVerticalPaddingValue = if (
+ ta.hasValue(R.styleable.DualHeightHorizontalLinearLayout_singleLineVerticalPadding)
+ ) {
+ ta.getValue(
+ R.styleable.DualHeightHorizontalLinearLayout_singleLineVerticalPadding,
+ tempPadding
+ )
+ tempPadding
+ } else {
+ null
+ }
+
+ textViewId = ta.getResourceId(R.styleable.DualHeightHorizontalLinearLayout_textViewId, 0)
+
+ ta.recycle()
+ }
+
+ init {
+ updateResources()
+ }
+
+ override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
+ super.setPadding(left, top, right, bottom)
+ initialPadding = top
+ }
+
+ override fun setPaddingRelative(start: Int, top: Int, end: Int, bottom: Int) {
+ super.setPaddingRelative(start, top, end, bottom)
+ initialPadding = top
+ }
+
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+ textView?.let { tv ->
+ if (tv.lineCount < 2) {
+ setMeasuredDimension(measuredWidth, singleLineHeightPx)
+ mPaddingBottom = 0
+ mPaddingTop = 0
+ } else {
+ mPaddingBottom = initialPadding
+ mPaddingTop = initialPadding
+ }
+ }
+ }
+
+ override fun onFinishInflate() {
+ super.onFinishInflate()
+ textView = findViewById(textViewId)
+ }
+
+ override fun onConfigurationChanged(newConfig: Configuration?) {
+ super.onConfigurationChanged(newConfig)
+ updateResources()
+ }
+
+ override fun setOrientation(orientation: Int) {
+ if (orientation == VERTICAL) {
+ throw IllegalStateException("This view should always have horizontal orientation")
+ }
+ super.setOrientation(orientation)
+ }
+
+ private fun updateResources() {
+ updateDimensionValue(singleLineHeightValue, minimumHeight, ::singleLineHeightPx::set)
+ updateDimensionValue(singleLineVerticalPaddingValue, 0, ::singleLineVerticalPaddingPx::set)
+ }
+
+ private inline fun updateDimensionValue(
+ tv: TypedValue?,
+ defaultValue: Int,
+ propertySetter: (Int) -> Unit
+ ) {
+ val value = tv?.let {
+ if (it.resourceId != 0) {
+ context.resources.getDimensionPixelSize(it.resourceId)
+ } else {
+ it.getDimension(displayMetrics).toInt()
+ }
+ } ?: defaultValue
+ propertySetter(value)
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 725f0e6..40c4851 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -24,7 +24,6 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.content.res.Resources;
import android.content.res.TypedArray;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.SensorProperties;
@@ -40,6 +39,7 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
import androidx.test.filters.SmallTest;
@@ -85,8 +85,6 @@
// Dependencies
@Mock
- private Resources mResources;
- @Mock
private LayoutInflater mLayoutInflater;
@Mock
private FingerprintManager mFingerprintManager;
@@ -110,6 +108,8 @@
private FalsingManager mFalsingManager;
@Mock
private PowerManager mPowerManager;
+ @Mock
+ private AccessibilityManager mAccessibilityManager;
private FakeExecutor mFgExecutor;
@@ -151,7 +151,6 @@
mFgExecutor = new FakeExecutor(new FakeSystemClock());
mUdfpsController = new UdfpsController(
mContext,
- mResources,
mLayoutInflater,
mFingerprintManager,
mWindowManager,
@@ -163,7 +162,8 @@
mKeyguardUpdateMonitor,
mKeyguardViewMediator,
mFalsingManager,
- mPowerManager);
+ mPowerManager,
+ mAccessibilityManager);
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
mOverlayController = mOverlayCaptor.getValue();
@@ -174,16 +174,9 @@
when(mBrightnessValues.length()).thenReturn(2);
when(mBrightnessValues.getFloat(0, PowerManager.BRIGHTNESS_OFF_FLOAT)).thenReturn(1f);
when(mBrightnessValues.getFloat(1, PowerManager.BRIGHTNESS_OFF_FLOAT)).thenReturn(2f);
- when(mResources.obtainTypedArray(com.android.internal.R.array.config_screenBrightnessNits))
- .thenReturn(mBrightnessValues);
when(mBrightnessBacklight.length()).thenReturn(2);
when(mBrightnessBacklight.getFloat(0, PowerManager.BRIGHTNESS_OFF_FLOAT)).thenReturn(1f);
when(mBrightnessBacklight.getFloat(1, PowerManager.BRIGHTNESS_OFF_FLOAT)).thenReturn(2f);
- when(mResources.obtainTypedArray(
- com.android.internal.R.array.config_autoBrightnessDisplayValuesNits))
- .thenReturn(mBrightnessBacklight);
- when(mResources.getIntArray(com.android.internal.R.array.config_screenBrightnessBacklight))
- .thenReturn(new int[]{1, 2});
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
index 730c941..0d67d66 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
@@ -19,26 +19,23 @@
import android.testing.AndroidTestingRunner
import android.view.View.GONE
import android.view.View.VISIBLE
+import android.widget.FrameLayout
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.stack.MediaHeaderView
import com.android.systemui.statusbar.phone.KeyguardBypassController
-import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.animation.UniqueObjectHostView
+import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.Captor
import org.mockito.Mock
-import org.mockito.Mockito.`when`
-import org.mockito.Mockito.atLeastOnce
-import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
+import org.mockito.Mockito.`when` as whenever
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -52,51 +49,81 @@
private lateinit var statusBarStateController: SysuiStatusBarStateController
@Mock
private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager
- @Mock
- private lateinit var mediaHeaderView: MediaHeaderView
- @Captor
- private lateinit var visibilityListener: ArgumentCaptor<((Boolean) -> Unit)>
@JvmField @Rule
val mockito = MockitoJUnit.rule()
+
+ private val mediaHeaderView: MediaHeaderView = MediaHeaderView(context, null)
private lateinit var keyguardMediaController: KeyguardMediaController
@Before
fun setup() {
+ // default state is positive, media should show up
+ whenever(mediaHost.visible).thenReturn(true)
+ whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
+ whenever(notificationLockscreenUserManager.shouldShowLockscreenNotifications())
+ .thenReturn(true)
+ whenever(mediaHost.hostView).thenReturn(UniqueObjectHostView(context))
+
keyguardMediaController = KeyguardMediaController(mediaHost, bypassController,
statusBarStateController, notificationLockscreenUserManager)
+ keyguardMediaController.attachSinglePaneContainer(mediaHeaderView)
}
@Test
- fun testAttach_hiddenWhenHostIsHidden() {
- `when`(mediaHost.visible).thenReturn(false)
- triggerVisibilityListener()
+ fun testHiddenWhenHostIsHidden() {
+ whenever(mediaHost.visible).thenReturn(false)
- verify(mediaHeaderView, atLeastOnce()).visibility = eq(GONE)
- }
- @Test
- fun testAttach_visibleOnKeyguard() {
- `when`(mediaHost.visible).thenReturn(true)
- `when`(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
- `when`(notificationLockscreenUserManager.shouldShowLockscreenNotifications())
- .thenReturn(true)
- triggerVisibilityListener()
+ keyguardMediaController.refreshMediaPosition()
- verify(mediaHeaderView, atLeastOnce()).visibility = eq(VISIBLE)
+ assertThat(mediaHeaderView.visibility).isEqualTo(GONE)
}
+
@Test
- fun testAttach_hiddenOnKeyguard_whenNotificationsAreHidden() {
- `when`(mediaHost.visible).thenReturn(true)
- `when`(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
- `when`(notificationLockscreenUserManager.shouldShowLockscreenNotifications())
+ fun testVisibleOnKeyguardOrFullScreenUserSwitcher() {
+ testStateVisibility(StatusBarState.SHADE, GONE)
+ testStateVisibility(StatusBarState.SHADE_LOCKED, GONE)
+ testStateVisibility(StatusBarState.FULLSCREEN_USER_SWITCHER, VISIBLE)
+ testStateVisibility(StatusBarState.KEYGUARD, VISIBLE)
+ }
+
+ private fun testStateVisibility(state: Int, visibility: Int) {
+ whenever(statusBarStateController.state).thenReturn(state)
+ keyguardMediaController.refreshMediaPosition()
+ assertThat(mediaHeaderView.visibility).isEqualTo(visibility)
+ }
+
+ @Test
+ fun testHiddenOnKeyguard_whenNotificationsAreHidden() {
+ whenever(notificationLockscreenUserManager.shouldShowLockscreenNotifications())
.thenReturn(false)
- triggerVisibilityListener()
- verify(mediaHeaderView, atLeastOnce()).visibility = eq(GONE)
+ keyguardMediaController.refreshMediaPosition()
+
+ assertThat(mediaHeaderView.visibility).isEqualTo(GONE)
}
- private fun triggerVisibilityListener() {
- keyguardMediaController.attach(mediaHeaderView)
- verify(mediaHost).addVisibilityChangeListener(capture(visibilityListener))
- visibilityListener.value.invoke(true)
+ @Test
+ fun testActivatesSplitShadeContainerInSplitShadeMode() {
+ val splitShadeContainer = FrameLayout(context)
+ keyguardMediaController.attachSplitShadeContainer(
+ splitShadeContainer,
+ useContainer = { true })
+
+ keyguardMediaController.refreshMediaPosition()
+
+ assertThat(splitShadeContainer.visibility).isEqualTo(VISIBLE)
}
-}
\ No newline at end of file
+
+ @Test
+ fun testActivatesSinglePaneContainerInSinglePaneMode() {
+ val splitShadeContainer = FrameLayout(context)
+ keyguardMediaController.attachSplitShadeContainer(
+ splitShadeContainer,
+ useContainer = { false })
+
+ keyguardMediaController.refreshMediaPosition()
+
+ assertThat(splitShadeContainer.visibility).isEqualTo(GONE)
+ assertThat(mediaHeaderView.visibility).isEqualTo(VISIBLE)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
index 4ee639b..234dec2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
@@ -81,10 +81,10 @@
private static final String PARENTAL_CONTROLS_LABEL = "Parental Control App";
private static final ComponentName DEVICE_OWNER_COMPONENT =
new ComponentName("TestDPC", "Test");
+ private static final int DEFAULT_ICON_ID = R.drawable.ic_info_outline;
private ViewGroup mRootView;
private TextView mFooterText;
- private TestableImageView mFooterIcon;
private TestableImageView mPrimaryFooterIcon;
private QSSecurityFooter mFooter;
@Mock
@@ -101,11 +101,10 @@
when(mUserTracker.getUserInfo()).thenReturn(mock(UserInfo.class));
mRootView = (ViewGroup) new LayoutInflaterBuilder(mContext)
.replace("ImageView", TestableImageView.class)
- .build().inflate(R.layout.quick_settings_footer, null, false);
+ .build().inflate(R.layout.quick_settings_security_footer, null, false);
mFooter = new QSSecurityFooter(mRootView, mUserTracker, new Handler(looper),
mActivityStarter, mSecurityController, looper);
mFooterText = mRootView.findViewById(R.id.footer_text);
- mFooterIcon = mRootView.findViewById(R.id.footer_icon);
mPrimaryFooterIcon = mRootView.findViewById(R.id.primary_footer_icon);
mFooter.setHostEnvironment(null);
@@ -135,10 +134,8 @@
assertEquals(mContext.getString(R.string.quick_settings_disclosure_management),
mFooterText.getText());
assertEquals(View.VISIBLE, mRootView.getVisibility());
- assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
- assertEquals(View.GONE, mPrimaryFooterIcon.getVisibility());
- // -1 == never set.
- assertEquals(-1, mFooterIcon.getLastImageResource());
+ assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
+ assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
}
@Test
@@ -153,10 +150,8 @@
MANAGING_ORGANIZATION),
mFooterText.getText());
assertEquals(View.VISIBLE, mRootView.getVisibility());
- assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
- assertEquals(View.GONE, mPrimaryFooterIcon.getVisibility());
- // -1 == never set.
- assertEquals(-1, mFooterIcon.getLastImageResource());
+ assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
+ assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
}
@Test
@@ -174,10 +169,8 @@
R.string.quick_settings_financed_disclosure_named_management,
MANAGING_ORGANIZATION), mFooterText.getText());
assertEquals(View.VISIBLE, mRootView.getVisibility());
- assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
- assertEquals(View.GONE, mPrimaryFooterIcon.getVisibility());
- // -1 == never set.
- assertEquals(-1, mFooterIcon.getLastImageResource());
+ assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
+ assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
}
@Test
@@ -204,10 +197,8 @@
TestableLooper.get(this).processAllMessages();
assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
mFooterText.getText());
- assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
- assertEquals(View.GONE, mPrimaryFooterIcon.getVisibility());
- // -1 == never set.
- assertEquals(-1, mFooterIcon.getLastImageResource());
+ assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
+ assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
// Same situation, but with organization name set
when(mSecurityController.getDeviceOwnerOrganizationName())
@@ -255,9 +246,8 @@
assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_named_vpn,
VPN_PACKAGE),
mFooterText.getText());
- assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
- assertEquals(View.GONE, mPrimaryFooterIcon.getVisibility());
- assertEquals(R.drawable.stat_sys_vpn_ic, mFooterIcon.getLastImageResource());
+ assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
+ assertEquals(R.drawable.stat_sys_vpn_ic, mPrimaryFooterIcon.getLastImageResource());
// Same situation, but with organization name set
when(mSecurityController.getDeviceOwnerOrganizationName())
@@ -282,9 +272,8 @@
TestableLooper.get(this).processAllMessages();
assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_vpns),
mFooterText.getText());
- assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
- assertEquals(View.GONE, mPrimaryFooterIcon.getVisibility());
- assertEquals(R.drawable.stat_sys_vpn_ic, mFooterIcon.getLastImageResource());
+ assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
+ assertEquals(R.drawable.stat_sys_vpn_ic, mPrimaryFooterIcon.getLastImageResource());
// Same situation, but with organization name set
when(mSecurityController.getDeviceOwnerOrganizationName())
@@ -306,9 +295,8 @@
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
- assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
- assertEquals(View.GONE, mPrimaryFooterIcon.getVisibility());
- assertEquals(R.drawable.stat_sys_vpn_ic, mFooterIcon.getLastImageResource());
+ assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility());
+ assertEquals(R.drawable.stat_sys_vpn_ic, mPrimaryFooterIcon.getLastImageResource());
assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
mFooterText.getText());
}
@@ -320,8 +308,7 @@
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
- // -1 == never set.
- assertEquals(-1, mFooterIcon.getLastImageResource());
+ assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
assertEquals(mContext.getString(
R.string.quick_settings_disclosure_managed_profile_monitoring),
mFooterText.getText());
@@ -345,8 +332,7 @@
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
- // -1 == never set.
- assertEquals(-1, mFooterIcon.getLastImageResource());
+ assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
assertEquals(mContext.getString(R.string.quick_settings_disclosure_monitoring),
mFooterText.getText());
}
@@ -359,7 +345,7 @@
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
- assertEquals(R.drawable.stat_sys_vpn_ic, mFooterIcon.getLastImageResource());
+ assertEquals(R.drawable.stat_sys_vpn_ic, mPrimaryFooterIcon.getLastImageResource());
assertEquals(mContext.getString(R.string.quick_settings_disclosure_vpns),
mFooterText.getText());
}
@@ -371,7 +357,7 @@
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
- assertEquals(R.drawable.stat_sys_vpn_ic, mFooterIcon.getLastImageResource());
+ assertEquals(R.drawable.stat_sys_vpn_ic, mPrimaryFooterIcon.getLastImageResource());
assertEquals(mContext.getString(
R.string.quick_settings_disclosure_managed_profile_named_vpn,
VPN_PACKAGE_2),
@@ -412,7 +398,7 @@
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
- assertEquals(R.drawable.stat_sys_vpn_ic, mFooterIcon.getLastImageResource());
+ assertEquals(R.drawable.stat_sys_vpn_ic, mPrimaryFooterIcon.getLastImageResource());
assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_vpn,
VPN_PACKAGE),
mFooterText.getText());
@@ -648,12 +634,12 @@
assertEquals(testDrawable, mPrimaryFooterIcon.getDrawable());
- // Ensure the primary icon is set to gone when parental controls is disabled.
+ // Ensure the primary icon is back to default after parental controls are gone
when(mSecurityController.isParentalControlsEnabled()).thenReturn(false);
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
- assertEquals(View.GONE, mPrimaryFooterIcon.getVisibility());
+ assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index 02e2e4c..152ba90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -53,6 +53,7 @@
private boolean mHasVisibleNotifs;
private float mQsExpansion;
private int mCutoutTopInset = 0; // in pixels
+ private boolean mIsSplitShade = false;
@Before
public void setUp() {
@@ -265,6 +266,19 @@
}
@Test
+ public void notifPositionAlignedWithClockInSplitShadeMode() {
+ // GIVEN on lock screen and split shade mode
+ givenLockScreen();
+ mIsSplitShade = true;
+ mPreferredClockY = 100;
+ mHasCustomClock = true;
+ // WHEN the position algorithm is run
+ positionClock();
+ // THEN the notif padding DOESN'T adjust for keyguard status height.
+ assertThat(mClockPosition.stackScrollerPadding).isEqualTo(mPreferredClockY);
+ }
+
+ @Test
public void notifPositionWithLargeClockOnLockScreen() {
// GIVEN on lock screen and clock has a nonzero height
givenLockScreen();
@@ -397,7 +411,7 @@
0 /* userSwitchHeight */, mPreferredClockY, 0 /* userSwitchPreferredY */,
mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */,
0 /* unlockedStackScrollerPadding */, mQsExpansion,
- mCutoutTopInset);
+ mCutoutTopInset, mIsSplitShade);
mClockPositionAlgorithm.run(mClockPosition);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 2e4d253..4bac762 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -75,6 +75,7 @@
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.doze.DozeLog;
+import com.android.systemui.media.KeyguardMediaController;
import com.android.systemui.media.MediaDataManager;
import com.android.systemui.media.MediaHierarchyManager;
import com.android.systemui.qs.QSDetailDisplayer;
@@ -240,6 +241,8 @@
private LockIconViewController mLockIconViewController;
@Mock
private QuickAccessWalletClient mQuickAccessWalletClient;
+ @Mock
+ private KeyguardMediaController mKeyguardMediaController;
private SysuiStatusBarStateController mStatusBarStateController;
private NotificationPanelViewController mNotificationPanelViewController;
@@ -282,6 +285,7 @@
mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame));
mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller));
+ mNotificationContainerParent.addView(newViewWithId(R.id.keyguard_status_view));
when(mView.findViewById(R.id.notification_container_parent))
.thenReturn(mNotificationContainerParent);
FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
@@ -346,6 +350,7 @@
mLockIconViewController,
mFeatureFlags,
mQuickAccessWalletClient,
+ mKeyguardMediaController,
new FakeExecutor(new FakeSystemClock()));
mNotificationPanelViewController.initDependencies(
mStatusBar,
@@ -476,6 +481,20 @@
}
@Test
+ public void testKeyguardStatusView_isAlignedToGuidelineInSplitShadeMode() {
+ mNotificationPanelViewController.updateResources();
+
+ assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd)
+ .isEqualTo(ConstraintSet.PARENT_ID);
+
+ enableSplitShade();
+ mNotificationPanelViewController.updateResources();
+
+ assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd)
+ .isEqualTo(R.id.qs_edge_guideline);
+ }
+
+ @Test
public void testSplitShadeLayout_isAlignedToGuideline() {
enableSplitShade();
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 6ca3c4b..8f60b09 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -52,7 +52,6 @@
import android.net.NetworkScore;
import android.net.RouteInfo;
import android.net.TelephonyNetworkSpecifier;
-import android.net.TunnelConnectionParams;
import android.net.Uri;
import android.net.annotations.PolicyDirection;
import android.net.ipsec.ike.ChildSessionCallback;
@@ -1924,14 +1923,8 @@
@NonNull IpSecTunnelInterface tunnelIface,
@NonNull VcnChildSessionConfiguration childConfig,
@Nullable UnderlyingNetworkRecord underlying) {
- final TunnelConnectionParams tunnelParams =
+ final IkeTunnelConnectionParams ikeTunnelParams =
gatewayConnectionConfig.getTunnelConnectionParams();
- if (!(tunnelParams instanceof IkeTunnelConnectionParams)) {
- throw new IllegalStateException(
- "TunnelConnectionParams is not IkeTunnelConnectionParams");
- }
-
- final IkeTunnelConnectionParams ikeTunnelParams = (IkeTunnelConnectionParams) tunnelParams;
final LinkProperties lp = new LinkProperties();
lp.setInterfaceName(tunnelIface.getInterfaceName());
@@ -2138,32 +2131,16 @@
}
private IkeSessionParams buildIkeParams(@NonNull Network network) {
- final TunnelConnectionParams tunnelConnectionParams =
+ final IkeTunnelConnectionParams ikeTunnelConnectionParams =
mConnectionConfig.getTunnelConnectionParams();
-
- if (tunnelConnectionParams instanceof IkeTunnelConnectionParams) {
- final IkeTunnelConnectionParams ikeTunnelConnectionParams =
- (IkeTunnelConnectionParams) tunnelConnectionParams;
- final IkeSessionParams.Builder builder =
- new IkeSessionParams.Builder(ikeTunnelConnectionParams.getIkeSessionParams());
- builder.setNetwork(network);
-
- return builder.build();
- }
-
- throw new IllegalStateException("TunnelConnectionParams is not IkeTunnelConnectionParams");
+ final IkeSessionParams.Builder builder =
+ new IkeSessionParams.Builder(ikeTunnelConnectionParams.getIkeSessionParams());
+ builder.setNetwork(network);
+ return builder.build();
}
private ChildSessionParams buildChildParams() {
- final TunnelConnectionParams tunnelConnectionParams =
- mConnectionConfig.getTunnelConnectionParams();
-
- if (tunnelConnectionParams instanceof IkeTunnelConnectionParams) {
- return ((IkeTunnelConnectionParams) tunnelConnectionParams)
- .getTunnelModeChildSessionParams();
- }
-
- throw new IllegalStateException("TunnelConnectionParams is not IkeTunnelConnectionParams");
+ return mConnectionConfig.getTunnelConnectionParams().getTunnelModeChildSessionParams();
}
@VisibleForTesting(visibility = Visibility.PRIVATE)
diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java
index ca01d0f..aa2e6b9 100644
--- a/telephony/java/android/telephony/ims/SipDelegateManager.java
+++ b/telephony/java/android/telephony/ims/SipDelegateManager.java
@@ -34,6 +34,7 @@
import android.telephony.ims.stub.DelegateConnectionMessageCallback;
import android.telephony.ims.stub.DelegateConnectionStateCallback;
import android.telephony.ims.stub.SipDelegate;
+import android.util.ArrayMap;
import com.android.internal.annotations.VisibleForTesting;
@@ -163,6 +164,35 @@
})
public @interface MessageFailureReason {}
+ /**@hide*/
+ public static final ArrayMap<Integer, String> MESSAGE_FAILURE_REASON_STRING_MAP =
+ new ArrayMap<>(11);
+ static {
+ MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_UNKNOWN,
+ "MESSAGE_FAILURE_REASON_UNKNOWN");
+ MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_DELEGATE_DEAD,
+ "MESSAGE_FAILURE_REASON_DELEGATE_DEAD");
+ MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_DELEGATE_CLOSED,
+ "MESSAGE_FAILURE_REASON_DELEGATE_CLOSED");
+ MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS,
+ "MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS");
+ MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT,
+ "MESSAGE_FAILURE_REASON_INVALID_BODY_CONTENT");
+ MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG,
+ "MESSAGE_FAILURE_REASON_INVALID_FEATURE_TAG");
+ MESSAGE_FAILURE_REASON_STRING_MAP.append(
+ MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE,
+ "MESSAGE_FAILURE_REASON_TAG_NOT_ENABLED_FOR_DELEGATE");
+ MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE,
+ "MESSAGE_FAILURE_REASON_NETWORK_NOT_AVAILABLE");
+ MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_NOT_REGISTERED,
+ "MESSAGE_FAILURE_REASON_NOT_REGISTERED");
+ MESSAGE_FAILURE_REASON_STRING_MAP.append(MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION,
+ "MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION");
+ MESSAGE_FAILURE_REASON_STRING_MAP.append(
+ MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION,
+ "MESSAGE_FAILURE_REASON_INTERNAL_DELEGATE_STATE_TRANSITION");
+ }
/**
* Access to use this feature tag has been denied for an unknown reason.
diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
index 0d3fd3f..7cfd275 100644
--- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
@@ -22,7 +22,7 @@
import static org.junit.Assert.fail;
import android.net.NetworkCapabilities;
-import android.net.TunnelConnectionParams;
+import android.net.ipsec.ike.IkeTunnelConnectionParams;
import android.net.vcn.persistablebundleutils.TunnelConnectionParamsUtilsTest;
import androidx.test.filters.SmallTest;
@@ -60,7 +60,7 @@
};
public static final int MAX_MTU = 1360;
- public static final TunnelConnectionParams TUNNEL_CONNECTION_PARAMS =
+ public static final IkeTunnelConnectionParams TUNNEL_CONNECTION_PARAMS =
TunnelConnectionParamsUtilsTest.buildTestParams();
public static final String GATEWAY_CONNECTION_NAME_PREFIX = "gatewayConnectionName-";
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index 530e636..90ee738 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -51,7 +51,6 @@
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.ipsec.ike.ChildSaProposal;
-import android.net.ipsec.ike.IkeTunnelConnectionParams;
import android.net.ipsec.ike.exceptions.IkeException;
import android.net.ipsec.ike.exceptions.IkeInternalException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
@@ -181,7 +180,7 @@
assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
final List<ChildSaProposal> saProposals =
- ((IkeTunnelConnectionParams) mConfig.getTunnelConnectionParams())
+ mConfig.getTunnelConnectionParams()
.getTunnelModeChildSessionParams()
.getSaProposals();
final int expectedMtu =