Merge "Fix some issues reading xml"
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index dd951b4..c1d1518 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -224,6 +224,7 @@
field public static final String READ_APP_SPECIFIC_LOCALES = "android.permission.READ_APP_SPECIFIC_LOCALES";
field public static final String READ_CARRIER_APP_INFO = "android.permission.READ_CARRIER_APP_INFO";
field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
+ field public static final String READ_COMMUNAL_STATE = "android.permission.READ_COMMUNAL_STATE";
field public static final String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS";
field public static final String READ_DEVICE_CONFIG = "android.permission.READ_DEVICE_CONFIG";
field public static final String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
@@ -393,6 +394,7 @@
field public static final int config_helpPackageNameValue = 17039388; // 0x104001c
field public static final int config_systemActivityRecognizer = 17039416; // 0x1040038
field public static final int config_systemAmbientAudioIntelligence = 17039411; // 0x1040033
+ field public static final int config_systemAppProtectionService;
field public static final int config_systemAudioIntelligence = 17039412; // 0x1040034
field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
field public static final int config_systemAutomotiveProjection = 17039401; // 0x1040029
@@ -1309,6 +1311,20 @@
}
+package android.app.communal {
+
+ public final class CommunalManager {
+ method @RequiresPermission(android.Manifest.permission.READ_COMMUNAL_STATE) public void addCommunalModeListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.communal.CommunalManager.CommunalModeListener);
+ method @RequiresPermission(android.Manifest.permission.READ_COMMUNAL_STATE) public boolean isCommunalMode();
+ method @RequiresPermission(android.Manifest.permission.READ_COMMUNAL_STATE) public void removeCommunalModeListener(@NonNull android.app.communal.CommunalManager.CommunalModeListener);
+ }
+
+ @java.lang.FunctionalInterface public static interface CommunalManager.CommunalModeListener {
+ method public void onCommunalModeChanged(boolean);
+ }
+
+}
+
package android.app.compat {
public final class CompatChanges {
@@ -2491,6 +2507,7 @@
field public static final String BATTERY_STATS_SERVICE = "batterystats";
field @Deprecated public static final int BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS = 1048576; // 0x100000
field public static final int BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND = 262144; // 0x40000
+ field public static final String COMMUNAL_SERVICE = "communal";
field public static final String CONTENT_SUGGESTIONS_SERVICE = "content_suggestions";
field public static final String CONTEXTHUB_SERVICE = "contexthub";
field public static final String ETHERNET_SERVICE = "ethernet";
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index aa791aa..bf06db0 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -42,6 +42,7 @@
field public static final String TEST_BIOMETRIC = "android.permission.TEST_BIOMETRIC";
field public static final String TEST_MANAGE_ROLLBACKS = "android.permission.TEST_MANAGE_ROLLBACKS";
field public static final String UPGRADE_RUNTIME_PERMISSIONS = "android.permission.UPGRADE_RUNTIME_PERMISSIONS";
+ field public static final String WRITE_COMMUNAL_STATE = "android.permission.WRITE_COMMUNAL_STATE";
field public static final String WRITE_DEVICE_CONFIG = "android.permission.WRITE_DEVICE_CONFIG";
field @Deprecated public static final String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE";
field public static final String WRITE_OBB = "android.permission.WRITE_OBB";
@@ -608,6 +609,14 @@
}
+package android.app.communal {
+
+ public final class CommunalManager {
+ method @RequiresPermission(android.Manifest.permission.WRITE_COMMUNAL_STATE) public void setCommunalViewShowing(boolean);
+ }
+
+}
+
package android.app.contentsuggestions {
public final class ContentSuggestionsManager {
@@ -819,6 +828,7 @@
method public void holdLock(android.os.IBinder, int);
method @RequiresPermission(android.Manifest.permission.KEEP_UNINSTALLED_PACKAGES) public void setKeepUninstalledPackages(@NonNull java.util.List<java.lang.String>);
field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
+ field public static final String FEATURE_COMMUNAL_MODE = "android.software.communal_mode";
field public static final String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
field public static final String FEATURE_HDMI_CEC = "android.hardware.hdmi.cec";
field public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 128; // 0x80
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 089c269..81e6ae4 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1513,7 +1513,7 @@
}
});
- registerService(Context.COMMUNAL_MANAGER_SERVICE, CommunalManager.class,
+ registerService(Context.COMMUNAL_SERVICE, CommunalManager.class,
new CachedServiceFetcher<CommunalManager>() {
@Override
public CommunalManager createService(ContextImpl ctx) {
@@ -1522,7 +1522,7 @@
return null;
}
IBinder iBinder =
- ServiceManager.getService(Context.COMMUNAL_MANAGER_SERVICE);
+ ServiceManager.getService(Context.COMMUNAL_SERVICE);
return iBinder != null ? new CommunalManager(
ICommunalManager.Stub.asInterface(iBinder)) : null;
}
diff --git a/core/java/android/app/communal/CommunalManager.java b/core/java/android/app/communal/CommunalManager.java
index 60730ad..22f07693 100644
--- a/core/java/android/app/communal/CommunalManager.java
+++ b/core/java/android/app/communal/CommunalManager.java
@@ -17,15 +17,21 @@
package android.app.communal;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.compat.annotation.ChangeId;
import android.compat.annotation.Disabled;
import android.compat.annotation.Overridable;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.RemoteException;
+import android.util.ArrayMap;
+
+import java.util.concurrent.Executor;
/**
* System private class for talking with the
@@ -33,10 +39,12 @@
*
* @hide
*/
-@SystemService(Context.COMMUNAL_MANAGER_SERVICE)
+@SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
+@SystemService(Context.COMMUNAL_SERVICE)
@RequiresFeature(PackageManager.FEATURE_COMMUNAL_MODE)
public final class CommunalManager {
private final ICommunalManager mService;
+ private final ArrayMap<CommunalModeListener, ICommunalModeListener> mCommunalModeListeners;
/**
* This change id is used to annotate packages which can run in communal mode by default,
@@ -59,15 +67,20 @@
@Disabled
public static final long ALLOW_COMMUNAL_MODE_WITH_USER_CONSENT = 200324021L;
+ /** @hide */
public CommunalManager(ICommunalManager service) {
mService = service;
+ mCommunalModeListeners = new ArrayMap<CommunalModeListener, ICommunalModeListener>();
}
/**
* Updates whether or not the communal view is currently showing over the lockscreen.
*
* @param isShowing Whether communal view is showing.
+ *
+ * @hide
*/
+ @TestApi
@RequiresPermission(Manifest.permission.WRITE_COMMUNAL_STATE)
public void setCommunalViewShowing(boolean isShowing) {
try {
@@ -76,4 +89,72 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Checks whether or not the communal view is currently showing over the lockscreen.
+ */
+ @RequiresPermission(Manifest.permission.READ_COMMUNAL_STATE)
+ public boolean isCommunalMode() {
+ try {
+ return mService.isCommunalMode();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Listener for communal state changes.
+ */
+ @FunctionalInterface
+ public interface CommunalModeListener {
+ /**
+ * Callback function that executes when the communal state changes.
+ */
+ void onCommunalModeChanged(boolean isCommunalMode);
+ }
+
+ /**
+ * Registers a callback to execute when the communal state changes.
+ *
+ * @param listener The listener to add to receive communal state changes.
+ * @param executor {@link Executor} to dispatch to. To dispatch the callback to the main
+ * thread of your application, use
+ * {@link android.content.Context#getMainExecutor()}.
+ */
+ @RequiresPermission(Manifest.permission.READ_COMMUNAL_STATE)
+ public void addCommunalModeListener(@NonNull Executor executor,
+ @NonNull CommunalModeListener listener) {
+ synchronized (mCommunalModeListeners) {
+ try {
+ ICommunalModeListener iListener = new ICommunalModeListener.Stub() {
+ @Override
+ public void onCommunalModeChanged(boolean isCommunalMode) {
+ executor.execute(() -> listener.onCommunalModeChanged(isCommunalMode));
+ }
+ };
+ mService.addCommunalModeListener(iListener);
+ mCommunalModeListeners.put(listener, iListener);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Unregisters a callback that executes when communal state changes.
+ */
+ @RequiresPermission(Manifest.permission.READ_COMMUNAL_STATE)
+ public void removeCommunalModeListener(@NonNull CommunalModeListener listener) {
+ synchronized (mCommunalModeListeners) {
+ ICommunalModeListener iListener = mCommunalModeListeners.get(listener);
+ if (iListener != null) {
+ try {
+ mService.removeCommunalModeListener(iListener);
+ mCommunalModeListeners.remove(listener);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+ }
}
diff --git a/core/java/android/app/communal/ICommunalManager.aidl b/core/java/android/app/communal/ICommunalManager.aidl
index 02e8a65..869891e 100644
--- a/core/java/android/app/communal/ICommunalManager.aidl
+++ b/core/java/android/app/communal/ICommunalManager.aidl
@@ -16,12 +16,17 @@
package android.app.communal;
+import android.app.communal.ICommunalModeListener;
+
/**
* System private API for talking with the communal manager service that handles communal mode
* state.
*
* @hide
*/
-oneway interface ICommunalManager {
- void setCommunalViewShowing(boolean isShowing);
+interface ICommunalManager {
+ oneway void setCommunalViewShowing(boolean isShowing);
+ boolean isCommunalMode();
+ void addCommunalModeListener(in ICommunalModeListener listener);
+ void removeCommunalModeListener(in ICommunalModeListener listener);
}
\ No newline at end of file
diff --git a/core/java/android/app/communal/ICommunalModeListener.aidl b/core/java/android/app/communal/ICommunalModeListener.aidl
new file mode 100644
index 0000000..006e782
--- /dev/null
+++ b/core/java/android/app/communal/ICommunalModeListener.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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.app.communal;
+
+/**
+ * System private API to be notified about communal mode changes.
+ *
+ * @hide
+ */
+oneway interface ICommunalModeListener {
+ void onCommunalModeChanged(boolean isCommunalMode);
+}
\ No newline at end of file
diff --git a/core/java/android/bluetooth/le/TransportBlock.java b/core/java/android/bluetooth/le/TransportBlock.java
index b388bed..18bad9c 100644
--- a/core/java/android/bluetooth/le/TransportBlock.java
+++ b/core/java/android/bluetooth/le/TransportBlock.java
@@ -24,6 +24,7 @@
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
+import java.util.Arrays;
/**
* Wrapper for Transport Discovery Data Transport Blocks.
@@ -59,8 +60,12 @@
mOrgId = in.readInt();
mTdsFlags = in.readInt();
mTransportDataLength = in.readInt();
- mTransportData = new byte[mTransportDataLength];
- in.readByteArray(mTransportData);
+ if (mTransportDataLength > 0) {
+ mTransportData = new byte[mTransportDataLength];
+ in.readByteArray(mTransportData);
+ } else {
+ mTransportData = null;
+ }
}
@Override
@@ -68,7 +73,9 @@
dest.writeInt(mOrgId);
dest.writeInt(mTdsFlags);
dest.writeInt(mTransportDataLength);
- dest.writeByteArray(mTransportData);
+ if (mTransportData != null) {
+ dest.writeByteArray(mTransportData);
+ }
}
/**
@@ -79,6 +86,21 @@
return 0;
}
+ /**
+ * @hide
+ */
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ TransportBlock other = (TransportBlock) obj;
+ return Arrays.equals(toByteArray(), other.toByteArray());
+ }
+
public static final @NonNull Creator<TransportBlock> CREATOR = new Creator<TransportBlock>() {
@Override
public TransportBlock createFromParcel(Parcel in) {
diff --git a/core/java/android/bluetooth/le/TransportDiscoveryData.java b/core/java/android/bluetooth/le/TransportDiscoveryData.java
index c8e97f9..2b52f19 100644
--- a/core/java/android/bluetooth/le/TransportDiscoveryData.java
+++ b/core/java/android/bluetooth/le/TransportDiscoveryData.java
@@ -26,6 +26,7 @@
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -96,6 +97,21 @@
return 0;
}
+ /**
+ * @hide
+ */
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ TransportDiscoveryData other = (TransportDiscoveryData) obj;
+ return Arrays.equals(toByteArray(), other.toByteArray());
+ }
+
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mTransportDataType);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 73740d2c..543239b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -5862,13 +5862,14 @@
/**
* Use with {@link #getSystemService(String)} to retrieve a
- * {@link android.app.CommunalManager} for interacting with the global system state.
+ * {@link android.app.communal.CommunalManager} for interacting with the global system state.
*
* @see #getSystemService(String)
- * @see android.app.CommunalManager
+ * @see android.app.communal.CommunalManager
* @hide
*/
- public static final String COMMUNAL_MANAGER_SERVICE = "communal_manager";
+ @SystemApi
+ public static final String COMMUNAL_SERVICE = "communal";
/**
* Use with {@link #getSystemService(String)} to retrieve a
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index bea536e..1c35b47 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3981,6 +3981,7 @@
* @hide
*/
@SdkConstant(SdkConstantType.FEATURE)
+ @TestApi
public static final String FEATURE_COMMUNAL_MODE = "android.software.communal_mode";
/** @hide */
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index c76245b..75d5ecf 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -533,10 +533,11 @@
boolean mReportNextDraw;
/**
- * Set if the reportDraw was requested from WM. If just a local report draw was invoked, there's
- * no need to report back to system server and can just apply immediately on the client.
+ * Set whether the draw should use blast sync. This is in case the draw is canceled,
+ * but will be rescheduled. We still want the next draw to be sync.
*/
- boolean mReportDrawToWm;
+ boolean mNextDrawUseBlastSync;
+
boolean mFullRedrawNeeded;
boolean mNewSurfaceNeeded;
boolean mForceNextWindowRelayout;
@@ -2761,7 +2762,7 @@
}
}
final boolean wasReportNextDraw = mReportNextDraw;
- boolean useBlastSync = false;
+ boolean useBlastSync = mNextDrawUseBlastSync;
if (mFirst || windowShouldResize || viewVisibilityChanged || params != null
|| mForceNextWindowRelayout) {
@@ -3292,9 +3293,11 @@
mPendingTransitions.clear();
}
performDraw(useBlastSync);
+ mNextDrawUseBlastSync = false;
} else {
if (isViewVisible) {
// Try again
+ mNextDrawUseBlastSync = useBlastSync;
scheduleTraversals();
} else {
if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
@@ -3984,17 +3987,8 @@
}
mDrawsNeededToReport = 0;
- if (!mReportDrawToWm) {
- if (DEBUG_BLAST) {
- Log.d(mTag, "No need to report finishDrawing. Apply immediately");
- }
- mSurfaceChangedTransaction.apply();
- return;
- }
-
try {
mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction);
- mReportDrawToWm = false;
} catch (RemoteException e) {
Log.e(mTag, "Unable to report draw finished", e);
mSurfaceChangedTransaction.apply();
@@ -9604,7 +9598,6 @@
if (mReportNextDraw == false) {
drawPending();
}
- mReportDrawToWm = true;
mReportNextDraw = true;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6e2c807..7018df2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2798,7 +2798,7 @@
<!-- @SystemApi @hide Allows an application to set the profile owners and the device owner.
This permission is not available to third party applications.-->
<permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"
- android:protectionLevel="signature|role"
+ android:protectionLevel="signature|role|setup"
android:label="@string/permlab_manageProfileAndDeviceOwners"
android:description="@string/permdesc_manageProfileAndDeviceOwners" />
@@ -5531,10 +5531,18 @@
<!-- Allows an application to interact with the currently active
{@link com.android.server.communal.CommunalManagerService}.
- @hide -->
+ @hide
+ @TestApi -->
<permission android:name="android.permission.WRITE_COMMUNAL_STATE"
android:protectionLevel="signature" />
+ <!-- Allows an application to view information from the currently active
+ {@link com.android.server.communal.CommunalManagerService}.
+ @hide
+ @SystemApi -->
+ <permission android:name="android.permission.READ_COMMUNAL_STATE"
+ android:protectionLevel="signature|privileged"/>
+
<!-- Allows the holder to manage whether the system can bind to services
provided by instant apps. This permission is intended to protect
test/development fucntionality and should be used only in such cases.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ccde348..480c679 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2123,6 +2123,8 @@
<string name="config_systemTelevisionRemoteService" translatable="false">@string/config_tvRemoteServicePackage</string>
<!-- The name of the package that will hold the device management role -->
<string name="config_deviceManager" translatable="false"></string>
+ <!-- The name of the package that will hold the app protection service role. -->
+ <string name="config_systemAppProtectionService" translatable="false"></string>
<!-- The name of the package that will be allowed to change its components' label/icon. -->
<string name="config_overrideComponentUiPackage" translatable="false">com.android.stk</string>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ca80def..1aa3ac2 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3267,6 +3267,8 @@
<public name="config_systemSupervision" />
<!-- @hide @SystemApi -->
<public name="config_deviceManager" />
+ <!-- @hide @SystemApi -->
+ <public name="config_systemAppProtectionService" />
</staging-public-group>
<staging-public-group type="dimen" first-id="0x01db0000">
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 60cb9d3..81db63e 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -519,6 +519,9 @@
<permission name="android.permission.LOCK_DEVICE" />
<!-- Permission required for CTS test - CtsSafetyCenterTestCases -->
<permission name="android.permission.SEND_SAFETY_CENTER_UPDATE" />
+ <!-- Permission required for CTS test - CommunalManagerTest -->
+ <permission name="android.permission.WRITE_COMMUNAL_STATE" />
+ <permission name="android.permission.READ_COMMUNAL_STATE" />
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
index 9a41cb4..fa173072 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
@@ -189,7 +189,10 @@
if (!actualPerm.containsAll(expectedPerm)) {
return buildDescription(tree)
.setMessage("Method " + method.name.toString() + "() annotated " + expectedPerm
- + " but too wide; only invokes methods requiring " + actualPerm)
+ + " but too wide; only invokes methods requiring " + actualPerm
+ + "\n If calling an AIDL interface, it can be annotated by adding:"
+ + "\n @JavaPassthrough(annotation=\""
+ + "@android.annotation.RequiresPermission(...)\")")
.build();
}
diff --git a/packages/PackageInstaller/res/values/strings.xml b/packages/PackageInstaller/res/values/strings.xml
index ca3ec3c..688d116 100644
--- a/packages/PackageInstaller/res/values/strings.xml
+++ b/packages/PackageInstaller/res/values/strings.xml
@@ -112,6 +112,8 @@
<!-- [CHAR LIMIT=none] -->
<string name="uninstall_application_text_user">Do you want to uninstall this app for the user <xliff:g id="username">%1$s</xliff:g>?</string>
<!-- [CHAR LIMIT=none] -->
+ <string name="uninstall_application_text_current_user_work_profile">Do you want to uninstall this app from your work profile?</string>
+ <!-- [CHAR LIMIT=none] -->
<string name="uninstall_update_text">Replace this app with the factory version? All data will be removed.</string>
<!-- [CHAR LIMIT=none] -->
<string name="uninstall_update_text_multiuser">Replace this app with the factory version? All data will be removed. This affects all users of this device, including those with work profiles.</string>
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
index 99f6a92..36294ac 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
@@ -31,6 +31,7 @@
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.Bundle;
+import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
@@ -125,6 +126,7 @@
final boolean isUpdate =
((dialogInfo.appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
+ final UserHandle myUserHandle = Process.myUserHandle();
UserManager userManager = UserManager.get(getActivity());
if (isUpdate) {
if (isSingleUser(userManager)) {
@@ -135,10 +137,17 @@
} else {
if (dialogInfo.allUsers && !isSingleUser(userManager)) {
messageBuilder.append(getString(R.string.uninstall_application_text_all_users));
- } else if (!dialogInfo.user.equals(android.os.Process.myUserHandle())) {
+ } else if (!dialogInfo.user.equals(myUserHandle)) {
UserInfo userInfo = userManager.getUserInfo(dialogInfo.user.getIdentifier());
- messageBuilder.append(
- getString(R.string.uninstall_application_text_user, userInfo.name));
+ if (userInfo.isManagedProfile()
+ && userInfo.profileGroupId == myUserHandle.getIdentifier()) {
+ messageBuilder.append(
+ getString(R.string.uninstall_application_text_current_user_work_profile,
+ userInfo.name));
+ } else {
+ messageBuilder.append(
+ getString(R.string.uninstall_application_text_user, userInfo.name));
+ }
} else {
messageBuilder.append(getString(R.string.uninstall_application_text));
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java
index 21d25f5..2d241ca 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/television/UninstallAlertFragment.java
@@ -21,7 +21,10 @@
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.Bundle;
+import android.os.Process;
+import android.os.UserHandle;
import android.os.UserManager;
+
import androidx.leanback.app.GuidedStepFragment;
import androidx.leanback.widget.GuidanceStylist;
import androidx.leanback.widget.GuidedAction;
@@ -59,6 +62,7 @@
final boolean isUpdate =
((dialogInfo.appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
+ final UserHandle myUserHandle = Process.myUserHandle();
UserManager userManager = UserManager.get(getActivity());
if (isUpdate) {
if (isSingleUser(userManager)) {
@@ -69,10 +73,17 @@
} else {
if (dialogInfo.allUsers && !isSingleUser(userManager)) {
messageBuilder.append(getString(R.string.uninstall_application_text_all_users));
- } else if (!dialogInfo.user.equals(android.os.Process.myUserHandle())) {
+ } else if (!dialogInfo.user.equals(myUserHandle)) {
UserInfo userInfo = userManager.getUserInfo(dialogInfo.user.getIdentifier());
- messageBuilder.append(
- getString(R.string.uninstall_application_text_user, userInfo.name));
+ if (userInfo.isManagedProfile()
+ && userInfo.profileGroupId == myUserHandle.getIdentifier()) {
+ messageBuilder.append(
+ getString(R.string.uninstall_application_text_current_user_work_profile,
+ userInfo.name));
+ } else {
+ messageBuilder.append(
+ getString(R.string.uninstall_application_text_user, userInfo.name));
+ }
} else {
messageBuilder.append(getString(R.string.uninstall_application_text));
}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 262cf53..e5b5285 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -606,6 +606,10 @@
<!-- Permission required for CTS test - CtsSafetyCenterTestCases -->
<uses-permission android:name="android.permission.SEND_SAFETY_CENTER_UPDATE" />
+ <!-- Permission required for CTS test - CommunalManagerTest -->
+ <uses-permission android:name="android.permission.WRITE_COMMUNAL_STATE" />
+ <uses-permission android:name="android.permission.READ_COMMUNAL_STATE" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/res-keyguard/drawable/keyguard_user_switcher_header_bg.xml b/packages/SystemUI/res-keyguard/drawable/keyguard_user_switcher_header_bg.xml
new file mode 100644
index 0000000..177f695
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/keyguard_user_switcher_header_bg.xml
@@ -0,0 +1,36 @@
+<?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.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:paddingMode="stack"
+ android:paddingStart="44dp"
+ android:paddingEnd="44dp"
+ android:paddingLeft="0dp"
+ android:paddingRight="0dp">
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="?androidprv:attr/colorSurface" />
+ <corners android:radius="@dimen/keyguard_user_switcher_corner" />
+ </shape>
+ </item>
+ <item
+ android:drawable="@drawable/ic_ksh_key_down"
+ android:gravity="end|center_vertical"
+ android:width="32dp"
+ android:height="32dp"
+ android:end="12dp" />
+</layer-list>
diff --git a/packages/SystemUI/res-keyguard/drawable/keyguard_user_switcher_popup_bg.xml b/packages/SystemUI/res-keyguard/drawable/keyguard_user_switcher_popup_bg.xml
new file mode 100644
index 0000000..96a2d15
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/keyguard_user_switcher_popup_bg.xml
@@ -0,0 +1,22 @@
+<?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
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle">
+ <solid android:color="?androidprv:attr/colorSurface" />
+ <corners android:radius="@dimen/keyguard_user_switcher_popup_corner" />
+</shape>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher.xml b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher.xml
new file mode 100644
index 0000000..a2b8bf6
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/keyguard_bouncer_user_switcher"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:paddingTop="12dp"
+ android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent
+ from this view when bouncer is shown -->
+
+ <ImageView
+ android:id="@+id/user_icon"
+ android:layout_width="@dimen/keyguard_user_switcher_icon_size"
+ android:layout_height="@dimen/keyguard_user_switcher_icon_size" />
+
+ <!-- need to keep this outer view in order to have a correctly sized anchor
+ for the dropdown menu, as well as dropdown background in the right place -->
+ <LinearLayout
+ android:id="@+id/user_switcher_anchor"
+ android:orientation="horizontal"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginTop="32dp"
+ android:minHeight="48dp">
+ <TextView
+ style="@style/Keyguard.UserSwitcher.Spinner.Header"
+ android:clickable="false"
+ android:id="@+id/user_switcher_header"
+ android:layout_width="@dimen/keyguard_user_switcher_width"
+ android:layout_height="wrap_content" />
+ </LinearLayout>>
+
+</LinearLayout>
+
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher_item.xml b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher_item.xml
new file mode 100644
index 0000000..b08e1ff
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher_item.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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.
+ -->
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/Keyguard.UserSwitcher.Spinner.Item"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start"
+ android:paddingStart="@dimen/control_menu_horizontal_padding"
+ android:paddingEnd="@dimen/control_menu_horizontal_padding"
+ android:textDirection="locale"/>
+
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index a946318..94566c7 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -49,8 +49,6 @@
android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
androidprv:layout_constraintEnd_toEndOf="parent"
androidprv:layout_constraintStart_toStartOf="parent"
-
- androidprv:layout_constraintTop_toTopOf="parent"
androidprv:layout_constraintBottom_toTopOf="@id/key1"
androidprv:layout_constraintVertical_bias="0.0">
diff --git a/packages/SystemUI/res-keyguard/values-sw720dp/bools.xml b/packages/SystemUI/res-keyguard/values-sw720dp/bools.xml
index 4daa648..54bb1fc 100644
--- a/packages/SystemUI/res-keyguard/values-sw720dp/bools.xml
+++ b/packages/SystemUI/res-keyguard/values-sw720dp/bools.xml
@@ -18,7 +18,7 @@
<resources>
<!-- Allows PIN/Pattern to be drawn on one side of a display, and for the user to
switch sides -->
- <bool name="can_use_one_handed_bouncer">true</bool>
+ <bool name="can_use_one_handed_bouncer">false</bool>
<!-- Will display the bouncer on one side of the display, and the current user icon and
user switcher on the other side -->
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 89dd741..9533040 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -106,4 +106,13 @@
opacity is zero), but this controls how much motion will actually be applied to it while
animating. Larger values will cause it to move "faster" while fading out/in. -->
<dimen name="one_handed_bouncer_move_animation_translation">120dp</dimen>
+
+
+ <dimen name="keyguard_user_switcher_header_text_size">24sp</dimen>
+ <dimen name="keyguard_user_switcher_item_text_size">18sp</dimen>
+ <dimen name="keyguard_user_switcher_width">300dp</dimen>
+ <dimen name="keyguard_user_switcher_icon_size">250dp</dimen>
+ <dimen name="keyguard_user_switcher_corner">32dp</dimen>
+ <dimen name="keyguard_user_switcher_popup_corner">24dp</dimen>
+ <dimen name="keyguard_user_switcher_item_padding_vertical">15dp</dimen>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index b0bdc72..a7b2b47 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -139,4 +139,23 @@
<style name="TextAppearance.Keyguard.BottomArea.Button">
<item name="android:shadowRadius">0</item>
</style>
+
+ <style name="Keyguard.UserSwitcher.Spinner" parent="@android:style/Widget.DeviceDefault.TextView">
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
+ <item name="android:singleLine">true</item>
+ <item name="android:ellipsize">end</item>
+ <item name="android:paddingTop">@dimen/keyguard_user_switcher_item_padding_vertical</item>
+ <item name="android:paddingBottom">@dimen/keyguard_user_switcher_item_padding_vertical</item>
+ </style>
+
+ <style name="Keyguard.UserSwitcher.Spinner.Header">
+ <item name="android:background">@drawable/keyguard_user_switcher_header_bg</item>
+ <item name="android:textSize">@dimen/keyguard_user_switcher_header_text_size</item>
+ </style>
+
+ <style name="Keyguard.UserSwitcher.Spinner.Item">
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+ <item name="android:textSize">@dimen/keyguard_user_switcher_item_text_size</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java
index 40190c1..7eae729 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputView.java
@@ -48,10 +48,6 @@
abstract CharSequence getTitle();
- void animateForIme(float interpolatedFraction, boolean appearingAnim) {
- return;
- }
-
boolean disallowInterceptTouch(MotionEvent event) {
return false;
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 3a3d308..bc366ab 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -156,8 +156,7 @@
setAlpha(0f);
animate()
.alpha(1f)
- .setDuration(500)
- .setStartDelay(300)
+ .setDuration(300)
.start();
setTranslationY(0f);
@@ -219,15 +218,6 @@
return true;
}
-
- @Override
- public void animateForIme(float interpolatedFraction, boolean appearingAnim) {
- animate().cancel();
- setAlpha(appearingAnim
- ? Math.max(interpolatedFraction, getAlpha())
- : 1 - interpolatedFraction);
- }
-
@Override
public CharSequence getTitle() {
return getResources().getString(
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 172c7f6..95567ec 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -23,17 +23,23 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.util.MathUtils;
import android.util.TypedValue;
import android.view.Gravity;
+import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
@@ -44,7 +50,10 @@
import android.view.WindowManager;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+import android.widget.AdapterView;
import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
@@ -56,12 +65,17 @@
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
+import com.android.internal.util.UserIcons;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
+import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.shared.system.SysUiStatsLog;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.UserSwitcherController.BaseUserAdapter;
+import com.android.systemui.statusbar.policy.UserSwitcherController.UserRecord;
import com.android.systemui.util.settings.GlobalSettings;
import java.util.ArrayList;
@@ -110,6 +124,8 @@
@VisibleForTesting
KeyguardSecurityViewFlipper mSecurityViewFlipper;
private GlobalSettings mGlobalSettings;
+ private FalsingCollector mFalsingCollector;
+ private UserSwitcherController mUserSwitcherController;
private AlertDialog mAlertDialog;
private boolean mSwipeUpToRetry;
@@ -124,7 +140,7 @@
private float mStartTouchY = -1;
private boolean mDisappearAnimRunning;
private SwipeListener mSwipeListener;
- private ModeLogic mModeLogic = new DefaultModeLogic();
+ private ViewMode mViewMode = new DefaultViewMode();
private @Mode int mCurrentMode = MODE_DEFAULT;
private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
@@ -173,8 +189,11 @@
interpolatedFraction);
translationY += paddingBottom;
}
- mSecurityViewFlipper.animateForIme(translationY, interpolatedFraction,
- !mDisappearAnimRunning);
+
+ float alpha = mDisappearAnimRunning
+ ? 1 - interpolatedFraction
+ : Math.max(interpolatedFraction, getAlpha());
+ updateChildren(translationY, alpha);
return windowInsets;
}
@@ -183,12 +202,19 @@
public void onEnd(WindowInsetsAnimation animation) {
if (!mDisappearAnimRunning) {
endJankInstrument(InteractionJankMonitor.CUJ_LOCKSCREEN_PASSWORD_APPEAR);
- mSecurityViewFlipper.animateForIme(0, /* interpolatedFraction */ 1f,
- true /* appearingAnim */);
+ updateChildren(0 /* translationY */, 1f /* alpha */);
} else {
endJankInstrument(InteractionJankMonitor.CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR);
}
}
+
+ private void updateChildren(int translationY, float alpha) {
+ for (int i = 0; i < KeyguardSecurityContainer.this.getChildCount(); ++i) {
+ View child = KeyguardSecurityContainer.this.getChildAt(i);
+ child.setTranslationY(translationY);
+ child.setAlpha(alpha);
+ }
+ }
};
// Used to notify the container when something interesting happens.
@@ -270,9 +296,12 @@
void onResume(SecurityMode securityMode, boolean faceAuthEnabled) {
mSecurityViewFlipper.setWindowInsetsAnimationCallback(mWindowInsetsAnimationCallback);
updateBiometricRetry(securityMode, faceAuthEnabled);
+
+ setupViewMode();
}
- void initMode(@Mode int mode, GlobalSettings globalSettings) {
+ void initMode(@Mode int mode, GlobalSettings globalSettings, FalsingCollector falsingCollector,
+ UserSwitcherController userSwitcherController) {
if (mCurrentMode == mode) return;
Log.i(TAG, "Switching mode from " + modeToString(mCurrentMode) + " to "
+ modeToString(mode));
@@ -280,16 +309,18 @@
switch (mode) {
case MODE_ONE_HANDED:
- mModeLogic = new OneHandedModeLogic();
+ mViewMode = new OneHandedViewMode();
break;
case MODE_USER_SWITCHER:
- mModeLogic = new UserSwitcherModeLogic();
+ mViewMode = new UserSwitcherViewMode();
break;
default:
- mModeLogic = new DefaultModeLogic();
+ mViewMode = new DefaultViewMode();
}
mGlobalSettings = globalSettings;
- finishSetup();
+ mFalsingCollector = falsingCollector;
+ mUserSwitcherController = userSwitcherController;
+ setupViewMode();
}
private String modeToString(@Mode int mode) {
@@ -305,10 +336,14 @@
}
}
- private void finishSetup() {
- if (mSecurityViewFlipper == null || mGlobalSettings == null) return;
+ private void setupViewMode() {
+ if (mSecurityViewFlipper == null || mGlobalSettings == null
+ || mFalsingCollector == null || mUserSwitcherController == null) {
+ return;
+ }
- mModeLogic.init(this, mGlobalSettings, mSecurityViewFlipper);
+ mViewMode.init(this, mGlobalSettings, mSecurityViewFlipper, mFalsingCollector,
+ mUserSwitcherController);
}
@Mode int getMode() {
@@ -321,13 +356,13 @@
* that the user last interacted with.
*/
void updatePositionByTouchX(float x) {
- mModeLogic.updatePositionByTouchX(x);
+ mViewMode.updatePositionByTouchX(x);
}
/** Returns whether the inner SecurityViewFlipper is left-aligned when in one-handed mode. */
public boolean isOneHandedModeLeftAligned() {
return mCurrentMode == MODE_ONE_HANDED
- && ((OneHandedModeLogic) mModeLogic).isLeftAligned();
+ && ((OneHandedViewMode) mViewMode).isLeftAligned();
}
public void onPause() {
@@ -336,6 +371,7 @@
mAlertDialog = null;
}
mSecurityViewFlipper.setWindowInsetsAnimationCallback(null);
+ mViewMode.reset();
}
@Override
@@ -428,7 +464,7 @@
}
} else {
if (!mIsDragging) {
- mModeLogic.handleTap(event);
+ mViewMode.handleTap(event);
}
}
}
@@ -453,8 +489,19 @@
.animateToFinalPosition(0);
}
+ /**
+ * Runs after a succsssful authentication only
+ */
public void startDisappearAnimation(SecurityMode securitySelection) {
mDisappearAnimRunning = true;
+ mViewMode.startDisappearAnimation(securitySelection);
+ }
+
+ /**
+ * This will run when the bouncer shows in all cases except when the user drags the bouncer up.
+ */
+ public void startAppearAnimation(SecurityMode securityMode) {
+ mViewMode.startAppearAnimation(securityMode);
}
private void beginJankInstrument(int cuj) {
@@ -490,8 +537,6 @@
public void onFinishInflate() {
super.onFinishInflate();
mSecurityViewFlipper = findViewById(R.id.view_flipper);
-
- finishSetup();
}
@Override
@@ -562,10 +607,7 @@
for (int i = 0; i < getChildCount(); i++) {
final View view = getChildAt(i);
if (view.getVisibility() != GONE) {
- int updatedWidthMeasureSpec = widthMeasureSpec;
- if (view == mSecurityViewFlipper) {
- updatedWidthMeasureSpec = mModeLogic.getChildWidthMeasureSpec(widthMeasureSpec);
- }
+ int updatedWidthMeasureSpec = mViewMode.getChildWidthMeasureSpec(widthMeasureSpec);
measureChildWithMargins(view, updatedWidthMeasureSpec, 0, heightMeasureSpec, 0);
final LayoutParams lp = (LayoutParams) view.getLayoutParams();
@@ -595,7 +637,13 @@
// After a layout pass, we need to re-place the inner bouncer, as our bounds may have
// changed.
- mModeLogic.updateSecurityViewLocation();
+ mViewMode.updateSecurityViewLocation();
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration config) {
+ super.onConfigurationChanged(config);
+ mViewMode.updateSecurityViewLocation();
}
void showAlmostAtWipeDialog(int attempts, int remaining, int userType) {
@@ -643,10 +691,12 @@
/**
* Enscapsulates the differences between bouncer modes for the container.
*/
- private interface ModeLogic {
+ interface ViewMode {
- default void init(ViewGroup v, GlobalSettings globalSettings,
- KeyguardSecurityViewFlipper viewFlipper) {};
+ default void init(@NonNull ViewGroup v, @NonNull GlobalSettings globalSettings,
+ @NonNull KeyguardSecurityViewFlipper viewFlipper,
+ @NonNull FalsingCollector falsingCollector,
+ @NonNull UserSwitcherController userSwitcherController) {};
/** Reinitialize the location */
default void updateSecurityViewLocation() {};
@@ -657,19 +707,33 @@
/** A tap on the container, outside of the ViewFlipper */
default void handleTap(MotionEvent event) {};
+ /** Called when the view needs to reset or hides */
+ default void reset() {};
+
+ /** On a successful auth, optionally handle how the view disappears */
+ default void startDisappearAnimation(SecurityMode securityMode) {};
+
+ /** On notif tap, this animation will run */
+ default void startAppearAnimation(SecurityMode securityMode) {};
+
/** Override to alter the width measure spec to perhaps limit the ViewFlipper size */
default int getChildWidthMeasureSpec(int parentWidthMeasureSpec) {
return parentWidthMeasureSpec;
}
}
- private static class DefaultModeLogic implements ModeLogic {
+ /**
+ * Default bouncer is centered within the space
+ */
+ static class DefaultViewMode implements ViewMode {
private ViewGroup mView;
private KeyguardSecurityViewFlipper mViewFlipper;
@Override
- public void init(ViewGroup v, GlobalSettings globalSettings,
- KeyguardSecurityViewFlipper viewFlipper) {
+ public void init(@NonNull ViewGroup v, @NonNull GlobalSettings globalSettings,
+ @NonNull KeyguardSecurityViewFlipper viewFlipper,
+ @NonNull FalsingCollector falsingCollector,
+ @NonNull UserSwitcherController userSwitcherController) {
mView = v;
mViewFlipper = viewFlipper;
@@ -682,7 +746,6 @@
(FrameLayout.LayoutParams) mViewFlipper.getLayoutParams();
lp.gravity = Gravity.CENTER_HORIZONTAL;
mViewFlipper.setLayoutParams(lp);
-
mViewFlipper.setTranslationX(0);
}
}
@@ -691,13 +754,171 @@
* User switcher mode will display both the current user icon as well as
* a user switcher, in both portrait and landscape modes.
*/
- private static class UserSwitcherModeLogic implements ModeLogic {
+ static class UserSwitcherViewMode implements ViewMode {
private ViewGroup mView;
+ private ViewGroup mUserSwitcherViewGroup;
+ private KeyguardSecurityViewFlipper mViewFlipper;
+ private ImageView mUserIconView;
+ private TextView mUserSwitcher;
+ private FalsingCollector mFalsingCollector;
+ private UserSwitcherController mUserSwitcherController;
+ private KeyguardUserSwitcherPopupMenu mPopup;
@Override
- public void init(ViewGroup v, GlobalSettings globalSettings,
- KeyguardSecurityViewFlipper viewFlipper) {
+ public void init(@NonNull ViewGroup v, @NonNull GlobalSettings globalSettings,
+ @NonNull KeyguardSecurityViewFlipper viewFlipper,
+ @NonNull FalsingCollector falsingCollector,
+ @NonNull UserSwitcherController userSwitcherController) {
mView = v;
+ mViewFlipper = viewFlipper;
+ mFalsingCollector = falsingCollector;
+ mUserSwitcherController = userSwitcherController;
+
+ if (mUserSwitcherViewGroup == null) {
+ LayoutInflater.from(v.getContext()).inflate(
+ R.layout.keyguard_bouncer_user_switcher,
+ mView,
+ true);
+ mUserSwitcherViewGroup = mView.findViewById(R.id.keyguard_bouncer_user_switcher);
+ }
+
+ mUserIconView = mView.findViewById(R.id.user_icon);
+ Drawable icon = UserIcons.getDefaultUserIcon(v.getContext().getResources(), 0, false);
+ mUserIconView.setImageDrawable(icon);
+
+ updateSecurityViewLocation();
+
+ mUserSwitcher = mView.findViewById(R.id.user_switcher_header);
+ setupUserSwitcher();
+ }
+
+ @Override
+ public void reset() {
+ if (mPopup != null) {
+ mPopup.dismiss();
+ mPopup = null;
+ }
+ }
+
+ @Override
+ public void startAppearAnimation(SecurityMode securityMode) {
+ // IME insets animations handle alpha and translation
+ if (securityMode == SecurityMode.Password) {
+ return;
+ }
+
+ mUserSwitcherViewGroup.setAlpha(0f);
+ ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mUserSwitcherViewGroup, View.ALPHA,
+ 1f);
+ alphaAnim.setInterpolator(Interpolators.ALPHA_IN);
+ alphaAnim.setDuration(500);
+ alphaAnim.start();
+ }
+
+ @Override
+ public void startDisappearAnimation(SecurityMode securityMode) {
+ // IME insets animations handle alpha and translation
+ if (securityMode == SecurityMode.Password) {
+ return;
+ }
+
+ int yTranslation = mView.getContext().getResources().getDimensionPixelSize(
+ R.dimen.disappear_y_translation);
+
+ AnimatorSet anims = new AnimatorSet();
+ ObjectAnimator yAnim = ObjectAnimator.ofFloat(mView, View.TRANSLATION_Y, yTranslation);
+ ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mView, View.ALPHA, 0f);
+
+ anims.setInterpolator(Interpolators.STANDARD_ACCELERATE);
+ anims.playTogether(alphaAnim, yAnim);
+ anims.start();
+ }
+
+ private void setupUserSwitcher() {
+ String currentUserName = mUserSwitcherController.getCurrentUserName();
+ mUserSwitcher.setText(currentUserName);
+
+ ViewGroup anchor = mView.findViewById(R.id.user_switcher_anchor);
+ BaseUserAdapter adapter = new BaseUserAdapter(mUserSwitcherController) {
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ UserRecord item = getItem(position);
+ TextView view = (TextView) convertView;
+ if (view == null) {
+ view = (TextView) LayoutInflater.from(parent.getContext()).inflate(
+ R.layout.keyguard_bouncer_user_switcher_item,
+ parent,
+ false);
+ }
+ view.setText(getName(parent.getContext(), item));
+ return view;
+ }
+ };
+
+ if (adapter.getCount() < 2) {
+ // The drop down arrow is at index 1
+ ((LayerDrawable) mUserSwitcher.getBackground()).getDrawable(1).setAlpha(0);
+ anchor.setClickable(false);
+ return;
+ } else {
+ ((LayerDrawable) mUserSwitcher.getBackground()).getDrawable(1).setAlpha(255);
+ }
+
+ anchor.setClickable(true);
+ anchor.setOnTouchListener((v, ev) -> {
+ if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mFalsingCollector.avoidGesture();
+ mPopup = new KeyguardUserSwitcherPopupMenu(v.getContext(),
+ mFalsingCollector);
+ mPopup.setAnchorView(anchor);
+ mPopup.setAdapter(adapter);
+ mPopup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ public void onItemClick(AdapterView parent, View view, int pos,
+ long id) {
+ mFalsingCollector.avoidGesture();
+
+ // - 1 to account for the header view
+ UserRecord user = adapter.getItem(pos - 1);
+ if (!user.isCurrent) {
+ adapter.onUserListItemClicked(user);
+ }
+ mPopup.dismiss();
+ mPopup = null;
+ }
+ });
+ mPopup.show();
+ }
+ return true;
+ });
+ }
+
+ /**
+ * Each view will get half the width. Yes, it would be easier to use something other than
+ * FrameLayout but it was too disruptive to downstream projects to change.
+ */
+ @Override
+ public int getChildWidthMeasureSpec(int parentWidthMeasureSpec) {
+ return MeasureSpec.makeMeasureSpec(
+ MeasureSpec.getSize(parentWidthMeasureSpec) / 2,
+ MeasureSpec.getMode(parentWidthMeasureSpec));
+ }
+
+ @Override
+ public void updateSecurityViewLocation() {
+ if (mView.getContext().getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_PORTRAIT) {
+ updateViewGravity(mViewFlipper, Gravity.CENTER_HORIZONTAL);
+ updateViewGravity(mUserSwitcherViewGroup, Gravity.CENTER_HORIZONTAL);
+ } else {
+ updateViewGravity(mViewFlipper, Gravity.RIGHT | Gravity.BOTTOM);
+ updateViewGravity(mUserSwitcherViewGroup, Gravity.LEFT | Gravity.TOP);
+ }
+ }
+
+ private void updateViewGravity(View v, int gravity) {
+ FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
+ lp.gravity = gravity;
+ v.setLayoutParams(lp);
}
}
@@ -705,7 +926,7 @@
* Logic to enabled one-handed bouncer mode. Supports animating the bouncer
* between alternate sides of the display.
*/
- private static class OneHandedModeLogic implements ModeLogic {
+ static class OneHandedViewMode implements ViewMode {
@Nullable private ValueAnimator mRunningOneHandedAnimator;
private ViewGroup mView;
private KeyguardSecurityViewFlipper mViewFlipper;
@@ -713,7 +934,9 @@
@Override
public void init(@NonNull ViewGroup v, @NonNull GlobalSettings globalSettings,
- @NonNull KeyguardSecurityViewFlipper viewFlipper) {
+ @NonNull KeyguardSecurityViewFlipper viewFlipper,
+ @NonNull FalsingCollector falsingCollector,
+ @NonNull UserSwitcherController userSwitcherController) {
mView = v;
mViewFlipper = viewFlipper;
mGlobalSettings = globalSettings;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 4035229..6b73a32 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -54,6 +54,7 @@
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.ViewController;
import com.android.systemui.util.settings.GlobalSettings;
@@ -78,6 +79,7 @@
private final SecurityCallback mSecurityCallback;
private final ConfigurationController mConfigurationController;
private final FalsingCollector mFalsingCollector;
+ private final UserSwitcherController mUserSwitcherController;
private final GlobalSettings mGlobalSettings;
private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
@@ -232,6 +234,7 @@
KeyguardSecurityViewFlipperController securityViewFlipperController,
ConfigurationController configurationController,
FalsingCollector falsingCollector,
+ UserSwitcherController userSwitcherController,
GlobalSettings globalSettings) {
super(view);
mLockPatternUtils = lockPatternUtils;
@@ -247,6 +250,7 @@
mConfigurationController = configurationController;
mLastOrientation = getResources().getConfiguration().orientation;
mFalsingCollector = falsingCollector;
+ mUserSwitcherController = userSwitcherController;
mGlobalSettings = globalSettings;
}
@@ -343,14 +347,14 @@
public void startAppearAnimation() {
if (mCurrentSecurityMode != SecurityMode.None) {
+ mView.startAppearAnimation(mCurrentSecurityMode);
getCurrentSecurityController().startAppearAnimation();
}
}
public boolean startDisappearAnimation(Runnable onFinishRunnable) {
- mView.startDisappearAnimation(getCurrentSecurityMode());
-
if (mCurrentSecurityMode != SecurityMode.None) {
+ mView.startDisappearAnimation(mCurrentSecurityMode);
return getCurrentSecurityController().startDisappearAnimation(onFinishRunnable);
}
@@ -506,15 +510,16 @@
}
private void configureMode() {
- // One-handed mode and user-switcher are currently mutually exclusive, and enforced here
+ boolean useSimSecurity = mCurrentSecurityMode == SecurityMode.SimPin
+ || mCurrentSecurityMode == SecurityMode.SimPuk;
int mode = KeyguardSecurityContainer.MODE_DEFAULT;
- if (canDisplayUserSwitcher()) {
+ if (canDisplayUserSwitcher() && !useSimSecurity) {
mode = KeyguardSecurityContainer.MODE_USER_SWITCHER;
} else if (canUseOneHandedBouncer()) {
mode = KeyguardSecurityContainer.MODE_ONE_HANDED;
}
- mView.initMode(mode, mGlobalSettings);
+ mView.initMode(mode, mGlobalSettings, mFalsingCollector, mUserSwitcherController);
}
public void reportFailedUnlockAttempt(int userId, int timeoutMs) {
@@ -605,6 +610,7 @@
private final ConfigurationController mConfigurationController;
private final FalsingCollector mFalsingCollector;
private final GlobalSettings mGlobalSettings;
+ private final UserSwitcherController mUserSwitcherController;
@Inject
Factory(KeyguardSecurityContainer view,
@@ -619,6 +625,7 @@
KeyguardSecurityViewFlipperController securityViewFlipperController,
ConfigurationController configurationController,
FalsingCollector falsingCollector,
+ UserSwitcherController userSwitcherController,
GlobalSettings globalSettings) {
mView = view;
mAdminSecondaryLockScreenControllerFactory = adminSecondaryLockScreenControllerFactory;
@@ -632,6 +639,7 @@
mConfigurationController = configurationController;
mFalsingCollector = falsingCollector;
mGlobalSettings = globalSettings;
+ mUserSwitcherController = userSwitcherController;
}
public KeyguardSecurityContainerController create(
@@ -640,7 +648,8 @@
mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
mKeyguardStateController, securityCallback, mSecurityViewFlipperController,
- mConfigurationController, mFalsingCollector, mGlobalSettings);
+ mConfigurationController, mFalsingCollector, mUserSwitcherController,
+ mGlobalSettings);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index e01e17d..4d2391a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -83,16 +83,6 @@
return "";
}
- /**
- * Translate the entire view, and optionally inform the wrapped view of the progress
- * so it can animate with the parent.
- */
- public void animateForIme(int translationY, float interpolatedFraction, boolean appearingAnim) {
- super.setTranslationY(translationY);
- KeyguardInputView v = getSecurityView();
- if (v != null) v.animateForIme(interpolatedFraction, appearingAnim);
- }
-
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 0d72c93..03b647b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -92,11 +92,6 @@
}
@Override
- public boolean startDisappearAnimation(Runnable finishRunnable) {
- return false;
- }
-
- @Override
public CharSequence getTitle() {
return getContext().getString(
com.android.internal.R.string.keyguard_accessibility_sim_puk_unlock);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherPopupMenu.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherPopupMenu.java
new file mode 100644
index 0000000..ca31b40d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherPopupMenu.java
@@ -0,0 +1,90 @@
+/*
+ * 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.keyguard;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.res.Resources;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ListPopupWindow;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.classifier.FalsingCollector;
+
+/**
+ * Custom user-switcher for use on the bouncer.
+ */
+public class KeyguardUserSwitcherPopupMenu extends ListPopupWindow {
+ private Context mContext;
+ private FalsingCollector mFalsingCollector;
+ private int mLastHeight = -1;
+ private View.OnLayoutChangeListener mLayoutListener = (v, l, t, r, b, ol, ot, or, ob) -> {
+ int height = -v.getMeasuredHeight() + getAnchorView().getHeight();
+ if (height != mLastHeight) {
+ mLastHeight = height;
+ setVerticalOffset(height);
+ KeyguardUserSwitcherPopupMenu.super.show();
+ }
+ };
+
+ public KeyguardUserSwitcherPopupMenu(@NonNull Context context,
+ @NonNull FalsingCollector falsingCollector) {
+ super(context);
+ mContext = context;
+ mFalsingCollector = falsingCollector;
+ Resources res = mContext.getResources();
+ setBackgroundDrawable(
+ res.getDrawable(R.drawable.keyguard_user_switcher_popup_bg, context.getTheme()));
+ setModal(true);
+ setOverlapAnchor(true);
+ }
+
+ /**
+ * Show the dialog.
+ */
+ @Override
+ public void show() {
+ // need to call show() first in order to construct the listView
+ super.show();
+ ListView listView = getListView();
+
+ // This will force the popupwindow to show upward instead of drop down
+ listView.addOnLayoutChangeListener(mLayoutListener);
+
+ TextView header = (TextView) LayoutInflater.from(mContext).inflate(
+ R.layout.keyguard_bouncer_user_switcher_item, listView, false);
+ header.setText(mContext.getResources().getString(
+ R.string.accessibility_multi_user_switch_switcher));
+ listView.addHeaderView(header);
+
+ listView.setOnTouchListener((v, ev) -> {
+ if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mFalsingCollector.avoidGesture();
+ }
+ return false;
+ });
+ }
+
+ @Override
+ public void dismiss() {
+ getListView().removeOnLayoutChangeListener(mLayoutListener);
+ super.dismiss();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index f725b9f..da0069f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -378,26 +378,26 @@
@Override
public void onAccessPointsChanged(final List<WifiEntry> accessPoints) {
- mAccessPoints = accessPoints.toArray(new WifiEntry[accessPoints.size()]);
- filterUnreachableAPs();
+ mAccessPoints = filterUnreachableAPs(accessPoints);
updateItems();
}
/** Filter unreachable APs from mAccessPoints */
- private void filterUnreachableAPs() {
+ private WifiEntry[] filterUnreachableAPs(List<WifiEntry> unfiltered) {
int numReachable = 0;
- for (WifiEntry ap : mAccessPoints) {
+ for (WifiEntry ap : unfiltered) {
if (isWifiEntryReachable(ap)) numReachable++;
}
- if (numReachable != mAccessPoints.length) {
- WifiEntry[] unfiltered = mAccessPoints;
- mAccessPoints = new WifiEntry[numReachable];
+ if (numReachable != unfiltered.size()) {
+ WifiEntry[] accessPoints = new WifiEntry[numReachable];
int i = 0;
for (WifiEntry ap : unfiltered) {
- if (isWifiEntryReachable(ap)) mAccessPoints[i++] = ap;
+ if (isWifiEntryReachable(ap)) accessPoints[i++] = ap;
}
+ return accessPoints;
}
+ return unfiltered.toArray(new WifiEntry[0]);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index aa3b3e1..ad1c232 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -74,7 +74,7 @@
private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock";
private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl();
- private static final int FP_ATTEMPTS_BEFORE_SHOW_BOUNCER = 3;
+ private static final int FP_ATTEMPTS_BEFORE_SHOW_BOUNCER = 2;
@IntDef(prefix = { "MODE_" }, value = {
MODE_NONE,
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 a64e579..4e68b19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -3419,12 +3419,6 @@
mStatusBarStateController.setState(KEYGUARD);
}
return true;
- case StatusBarState.SHADE:
-
- // This gets called in the middle of the touch handling, where the state is still
- // that we are tracking the panel. Collapse the panel after this is done.
- mView.post(mPostCollapseRunnable);
- return false;
default:
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index 9af79a9..53bfd77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -933,7 +933,6 @@
private void abortAnimations() {
cancelHeightAnimator();
- mView.removeCallbacks(mPostCollapseRunnable);
mView.removeCallbacks(mFlingCollapseRunnable);
}
@@ -1110,13 +1109,6 @@
return onMiddleClicked();
}
- protected final Runnable mPostCollapseRunnable = new Runnable() {
- @Override
- public void run() {
- collapse(false /* delayed */, 1.0f /* speedUpFactor */);
- }
- };
-
protected abstract boolean onMiddleClicked();
protected abstract boolean isDozing();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index ec7e93b..b9386bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -15,12 +15,14 @@
*/
package com.android.systemui.statusbar.phone
+import android.content.res.Configuration
import android.graphics.Point
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import com.android.systemui.R
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
+import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.unfold.SysUIUnfoldComponent
import com.android.systemui.unfold.UNFOLD_STATUS_BAR
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
@@ -35,9 +37,16 @@
view: PhoneStatusBarView,
@Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider?,
private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
- touchEventHandler: PhoneStatusBarView.TouchEventHandler
+ touchEventHandler: PhoneStatusBarView.TouchEventHandler,
+ private val configurationController: ConfigurationController
) : ViewController<PhoneStatusBarView>(view) {
+ private val configurationListener = object : ConfigurationController.ConfigurationListener {
+ override fun onConfigChanged(newConfig: Configuration?) {
+ mView.updateResources()
+ }
+ }
+
override fun onViewAttached() {
moveFromCenterAnimationController?.let { animationController ->
val statusBarLeftSide: View = mView.findViewById(R.id.status_bar_left_side)
@@ -66,11 +75,13 @@
}
progressProvider?.setReadyToHandleTransition(true)
+ configurationController.addCallback(configurationListener)
}
override fun onViewDetached() {
progressProvider?.setReadyToHandleTransition(false)
moveFromCenterAnimationController?.onViewDetached()
+ configurationController.removeCallback(configurationListener)
}
init {
@@ -116,7 +127,8 @@
class Factory @Inject constructor(
private val unfoldComponent: Optional<SysUIUnfoldComponent>,
@Named(UNFOLD_STATUS_BAR)
- private val progressProvider: Optional<ScopedUnfoldTransitionProgressProvider>
+ private val progressProvider: Optional<ScopedUnfoldTransitionProgressProvider>,
+ private val configurationController: ConfigurationController
) {
fun create(
view: PhoneStatusBarView,
@@ -128,7 +140,8 @@
unfoldComponent.map {
it.getStatusBarMoveFromCenterAnimationController()
}.getOrNull(),
- touchEventHandler
+ touchEventHandler,
+ configurationController
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java
index a54251a..b4fed2b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java
@@ -218,10 +218,6 @@
return getStatusBar().getNotificationShadeWindowView();
}
- protected PhoneStatusBarView getStatusBarView() {
- return (PhoneStatusBarView) getStatusBar().getStatusBarView();
- }
-
private NotificationPanelViewController getNotificationPanelViewController() {
return getStatusBar().getPanelController();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
index 1ad9fa6..f6e19bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
@@ -18,6 +18,7 @@
import android.view.View
import androidx.constraintlayout.motion.widget.MotionLayout
+import com.android.settingslib.Utils
import com.android.systemui.R
import com.android.systemui.animation.ShadeInterpolation
import com.android.systemui.battery.BatteryMeterView
@@ -49,7 +50,7 @@
private val combinedHeaders = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)
// TODO(b/194178072) Handle RSSI hiding when multi carrier
- private val iconManager: StatusBarIconController.IconManager
+ private val iconManager: StatusBarIconController.TintedIconManager
private val qsCarrierGroupController: QSCarrierGroupController
private var visible = false
set(value) {
@@ -117,7 +118,9 @@
batteryIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
val iconContainer: StatusIconContainer = statusBar.findViewById(R.id.statusIcons)
- iconManager = StatusBarIconController.IconManager(iconContainer, featureFlags)
+ iconManager = StatusBarIconController.TintedIconManager(iconContainer, featureFlags)
+ iconManager.setTint(Utils.getColorAttrDefaultColor(statusBar.context,
+ android.R.attr.textColorPrimary))
qsCarrierGroupController = qsCarrierGroupControllerBuilder
.setQSCarrierGroup(statusBar.findViewById(R.id.carrier_group))
.build()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 0f0a2f0..6c0b717 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -2715,9 +2715,6 @@
mStatusBarWindowController.refreshStatusBarHeight();
}
- if (mStatusBarView != null) {
- mStatusBarView.updateResources();
- }
if (mNotificationPanelViewController != null) {
mNotificationPanelViewController.updateResources();
}
@@ -4192,7 +4189,7 @@
if (userSetup != mUserSetup) {
mUserSetup = userSetup;
- if (!mUserSetup && mStatusBarView != null) {
+ if (!mUserSetup) {
animateCollapseQuickSettings();
}
if (mNotificationPanelViewController != null) {
@@ -4307,7 +4304,7 @@
updateTheme();
mNavigationBarController.touchAutoDim(mDisplayId);
Trace.beginSection("StatusBar#updateKeyguardState");
- if (mState == StatusBarState.KEYGUARD && mStatusBarView != null) {
+ if (mState == StatusBarState.KEYGUARD) {
mNotificationPanelViewController.cancelPendingPanelCollapse();
}
updateDozingState();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
index abb7449..b391de3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
@@ -529,9 +529,7 @@
if (StatusBar.DEBUG_WINDOW_STATE) {
Log.d(StatusBar.TAG, "Status bar " + windowStateToString(state));
}
- if (mStatusBar.getStatusBarView() != null
- && !showing
- && mStatusBarStateController.getState() == StatusBarState.SHADE) {
+ if (!showing && mStatusBarStateController.getState() == StatusBarState.SHADE) {
mNotificationPanelViewController.collapsePanel(
false /* animate */, false /* delayed */, 1.0f /* speedUpFactor */);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index dc8dc99..79ee746 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -836,6 +836,11 @@
mRootView = notificationShadeWindowView;
}
+ @VisibleForTesting
+ public KeyguardStateController getKeyguardStateController() {
+ return mKeyguardStateController;
+ }
+
public static abstract class BaseUserAdapter extends BaseAdapter {
final UserSwitcherController mController;
@@ -843,7 +848,7 @@
protected BaseUserAdapter(UserSwitcherController controller) {
mController = controller;
- mKeyguardStateController = controller.mKeyguardStateController;
+ mKeyguardStateController = controller.getKeyguardStateController();
controller.addAdapter(new WeakReference<>(this));
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index 030464a..98ce138 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -50,6 +50,7 @@
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.util.settings.GlobalSettings;
import org.junit.Before;
@@ -111,6 +112,8 @@
private FalsingCollector mFalsingCollector;
@Mock
private GlobalSettings mGlobalSettings;
+ @Mock
+ private UserSwitcherController mUserSwitcherController;
private Configuration mConfiguration;
private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
@@ -144,8 +147,8 @@
mView, mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
mKeyguardStateController, mKeyguardSecurityViewFlipperController,
- mConfigurationController, mFalsingCollector, mGlobalSettings)
- .create(mSecurityCallback);
+ mConfigurationController, mFalsingCollector, mUserSwitcherController,
+ mGlobalSettings).create(mSecurityCallback);
}
@Test
@@ -182,13 +185,15 @@
public void onResourcesUpdate_callsThroughOnRotationChange() {
// Rotation is the same, shouldn't cause an update
mKeyguardSecurityContainerController.updateResources();
- verify(mView, never()).initMode(MODE_DEFAULT, mGlobalSettings);
+ verify(mView, never()).initMode(MODE_DEFAULT, mGlobalSettings, mFalsingCollector,
+ mUserSwitcherController);
// Update rotation. Should trigger update
mConfiguration.orientation = Configuration.ORIENTATION_LANDSCAPE;
mKeyguardSecurityContainerController.updateResources();
- verify(mView).initMode(MODE_DEFAULT, mGlobalSettings);
+ verify(mView).initMode(MODE_DEFAULT, mGlobalSettings, mFalsingCollector,
+ mUserSwitcherController);
}
private void touchDownLeftSide() {
@@ -245,7 +250,8 @@
.thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Pattern);
- verify(mView).initMode(MODE_DEFAULT, mGlobalSettings);
+ verify(mView).initMode(MODE_DEFAULT, mGlobalSettings, mFalsingCollector,
+ mUserSwitcherController);
}
@Test
@@ -256,7 +262,8 @@
.thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Pattern);
- verify(mView).initMode(MODE_ONE_HANDED, mGlobalSettings);
+ verify(mView).initMode(MODE_ONE_HANDED, mGlobalSettings, mFalsingCollector,
+ mUserSwitcherController);
}
@Test
@@ -267,6 +274,7 @@
.thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password);
- verify(mView).initMode(MODE_DEFAULT, mGlobalSettings);
+ verify(mView).initMode(MODE_DEFAULT, mGlobalSettings, mFalsingCollector,
+ mUserSwitcherController);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index c751081..ea7940a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -16,21 +16,27 @@
package com.android.keyguard;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.systemBars;
import static com.android.keyguard.KeyguardSecurityContainer.MODE_DEFAULT;
import static com.android.keyguard.KeyguardSecurityContainer.MODE_ONE_HANDED;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.pm.UserInfo;
+import android.content.res.Configuration;
import android.graphics.Insets;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
@@ -39,17 +45,26 @@
import androidx.test.filters.SmallTest;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.UserSwitcherController.UserRecord;
import com.android.systemui.util.settings.GlobalSettings;
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.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import java.util.ArrayList;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper()
@@ -67,28 +82,43 @@
private KeyguardSecurityViewFlipper mSecurityViewFlipper;
@Mock
private GlobalSettings mGlobalSettings;
+ @Mock
+ private FalsingCollector mFalsingCollector;
+ @Mock
+ private UserSwitcherController mUserSwitcherController;
+ @Mock
+ private KeyguardStateController mKeyguardStateController;
+ @Captor
+ private ArgumentCaptor<FrameLayout.LayoutParams> mLayoutCaptor;
private KeyguardSecurityContainer mKeyguardSecurityContainer;
+ private FrameLayout.LayoutParams mSecurityViewFlipperLayoutParams;
@Before
public void setup() {
// Needed here, otherwise when mKeyguardSecurityContainer is created below, it'll cache
// the real references (rather than the TestableResources that this call creates).
mContext.ensureTestableResources();
- FrameLayout.LayoutParams securityViewFlipperLayoutParams = new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+ mSecurityViewFlipperLayoutParams = new FrameLayout.LayoutParams(
+ MATCH_PARENT, MATCH_PARENT);
when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController);
- when(mSecurityViewFlipper.getLayoutParams()).thenReturn(securityViewFlipperLayoutParams);
+ when(mSecurityViewFlipper.getLayoutParams()).thenReturn(mSecurityViewFlipperLayoutParams);
mKeyguardSecurityContainer = new KeyguardSecurityContainer(getContext());
mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper;
mKeyguardSecurityContainer.addView(mSecurityViewFlipper, new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+
+ when(mUserSwitcherController.getCurrentUserName()).thenReturn("Test User");
+ when(mUserSwitcherController.getKeyguardStateController())
+ .thenReturn(mKeyguardStateController);
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
}
@Test
public void onMeasure_usesHalfWidthWithOneHandedModeEnabled() {
- mKeyguardSecurityContainer.initMode(MODE_ONE_HANDED, mGlobalSettings);
+ mKeyguardSecurityContainer.initMode(MODE_ONE_HANDED, mGlobalSettings, mFalsingCollector,
+ mUserSwitcherController);
int halfWidthMeasureSpec =
View.MeasureSpec.makeMeasureSpec(SCREEN_WIDTH / 2, View.MeasureSpec.EXACTLY);
@@ -99,7 +129,8 @@
@Test
public void onMeasure_usesFullWidthWithOneHandedModeDisabled() {
- mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings);
+ mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings, mFalsingCollector,
+ mUserSwitcherController);
mKeyguardSecurityContainer.measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
@@ -110,7 +141,8 @@
int imeInsetAmount = 100;
int systemBarInsetAmount = 10;
- mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings);
+ mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings, mFalsingCollector,
+ mUserSwitcherController);
Insets imeInset = Insets.of(0, 0, 0, imeInsetAmount);
Insets systemBarInset = Insets.of(0, 0, 0, systemBarInsetAmount);
@@ -134,7 +166,8 @@
int imeInsetAmount = 0;
int systemBarInsetAmount = 10;
- mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings);
+ mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings, mFalsingCollector,
+ mUserSwitcherController);
Insets imeInset = Insets.of(0, 0, 0, imeInsetAmount);
Insets systemBarInset = Insets.of(0, 0, 0, systemBarInsetAmount);
@@ -154,7 +187,8 @@
private void setupForUpdateKeyguardPosition(boolean oneHandedMode) {
int mode = oneHandedMode ? MODE_ONE_HANDED : MODE_DEFAULT;
- mKeyguardSecurityContainer.initMode(mode, mGlobalSettings);
+ mKeyguardSecurityContainer.initMode(mode, mGlobalSettings, mFalsingCollector,
+ mUserSwitcherController);
mKeyguardSecurityContainer.measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
mKeyguardSecurityContainer.layout(0, 0, SCREEN_WIDTH, SCREEN_WIDTH);
@@ -189,4 +223,92 @@
mKeyguardSecurityContainer.updatePositionByTouchX(1f);
verify(mSecurityViewFlipper, never()).setTranslationX(anyInt());
}
+
+ @Test
+ public void testUserSwitcherModeViewGravityLandscape() {
+ // GIVEN one user has been setup and in landscape
+ when(mUserSwitcherController.getUsers()).thenReturn(buildUserRecords(1));
+ Configuration config = new Configuration();
+ config.orientation = Configuration.ORIENTATION_LANDSCAPE;
+ when(getContext().getResources().getConfiguration()).thenReturn(config);
+
+ // WHEN UserSwitcherViewMode is initialized and config has changed
+ setupUserSwitcher();
+ reset(mSecurityViewFlipper);
+ when(mSecurityViewFlipper.getLayoutParams()).thenReturn(mSecurityViewFlipperLayoutParams);
+ mKeyguardSecurityContainer.onConfigurationChanged(config);
+
+ // THEN views are oriented side by side
+ verify(mSecurityViewFlipper).setLayoutParams(mLayoutCaptor.capture());
+ assertThat(mLayoutCaptor.getValue().gravity).isEqualTo(Gravity.RIGHT | Gravity.BOTTOM);
+ ViewGroup userSwitcher = mKeyguardSecurityContainer.findViewById(
+ R.id.keyguard_bouncer_user_switcher);
+ assertThat(((FrameLayout.LayoutParams) userSwitcher.getLayoutParams()).gravity)
+ .isEqualTo(Gravity.LEFT | Gravity.TOP);
+ }
+
+ @Test
+ public void testUserSwitcherModeViewGravityPortrait() {
+ // GIVEN one user has been setup and in landscape
+ when(mUserSwitcherController.getUsers()).thenReturn(buildUserRecords(1));
+ Configuration config = new Configuration();
+ config.orientation = Configuration.ORIENTATION_PORTRAIT;
+ when(getContext().getResources().getConfiguration()).thenReturn(config);
+
+ // WHEN UserSwitcherViewMode is initialized and config has changed
+ setupUserSwitcher();
+ reset(mSecurityViewFlipper);
+ when(mSecurityViewFlipper.getLayoutParams()).thenReturn(mSecurityViewFlipperLayoutParams);
+ mKeyguardSecurityContainer.onConfigurationChanged(config);
+
+ // THEN views are both centered horizontally
+ verify(mSecurityViewFlipper).setLayoutParams(mLayoutCaptor.capture());
+ assertThat(mLayoutCaptor.getValue().gravity).isEqualTo(Gravity.CENTER_HORIZONTAL);
+ ViewGroup userSwitcher = mKeyguardSecurityContainer.findViewById(
+ R.id.keyguard_bouncer_user_switcher);
+ assertThat(((FrameLayout.LayoutParams) userSwitcher.getLayoutParams()).gravity)
+ .isEqualTo(Gravity.CENTER_HORIZONTAL);
+ }
+
+ @Test
+ public void testLessThanTwoUsersDoesNotAllowDropDown() {
+ // GIVEN one user has been setup
+ when(mUserSwitcherController.getUsers()).thenReturn(buildUserRecords(1));
+
+ // WHEN UserSwitcherViewMode is initialized
+ setupUserSwitcher();
+
+ // THEN the UserSwitcher anchor should not be clickable
+ ViewGroup anchor = mKeyguardSecurityContainer.findViewById(R.id.user_switcher_anchor);
+ assertThat(anchor.isClickable()).isFalse();
+ }
+
+ @Test
+ public void testTwoOrMoreUsersDoesAllowDropDown() {
+ // GIVEN one user has been setup
+ when(mUserSwitcherController.getUsers()).thenReturn(buildUserRecords(2));
+
+ // WHEN UserSwitcherViewMode is initialized
+ setupUserSwitcher();
+
+ // THEN the UserSwitcher anchor should not be clickable
+ ViewGroup anchor = mKeyguardSecurityContainer.findViewById(R.id.user_switcher_anchor);
+ assertThat(anchor.isClickable()).isTrue();
+ }
+
+ private void setupUserSwitcher() {
+ mKeyguardSecurityContainer.initMode(KeyguardSecurityContainer.MODE_USER_SWITCHER,
+ mGlobalSettings, mFalsingCollector, mUserSwitcherController);
+ }
+
+ private ArrayList<UserRecord> buildUserRecords(int count) {
+ ArrayList<UserRecord> users = new ArrayList<>();
+ for (int i = 0; i < count; ++i) {
+ UserInfo info = new UserInfo(i /* id */, "Name: " + i, null /* iconPath */,
+ 0 /* flags */);
+ users.add(new UserRecord(info, null, false /* isGuest */, false /* isCurrent */,
+ false /* isAddUser */, false /* isRestricted */, true /* isSwitchToEnabled */));
+ }
+ return users;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index 07debe6..c3349f1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -381,16 +381,15 @@
}
@Test
- public void onUdfpsConsecutivelyFailedThreeTimes_showBouncer() {
+ public void onUdfpsConsecutivelyFailedTwoTimes_showBouncer() {
// GIVEN UDFPS is supported
when(mUpdateMonitor.isUdfpsSupported()).thenReturn(true);
- // WHEN udfps fails twice - then don't show the bouncer
- mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
+ // WHEN udfps fails once - then don't show the bouncer
mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
- // WHEN udfps fails the third time
+ // WHEN udfps fails the second time
mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
// THEN show the bouncer
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index 7d266e9..235de1e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -26,6 +26,7 @@
import androidx.test.platform.app.InstrumentationRegistry
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.unfold.SysUIUnfoldComponent
import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
@@ -57,6 +58,8 @@
private lateinit var sysuiUnfoldComponent: SysUIUnfoldComponent
@Mock
private lateinit var progressProvider: ScopedUnfoldTransitionProgressProvider
+ @Mock
+ private lateinit var configurationController: ConfigurationController
private lateinit var view: PhoneStatusBarView
private lateinit var controller: PhoneStatusBarViewController
@@ -116,7 +119,8 @@
private fun createController(view: PhoneStatusBarView): PhoneStatusBarViewController {
return PhoneStatusBarViewController.Factory(
Optional.of(sysuiUnfoldComponent),
- Optional.of(progressProvider)
+ Optional.of(progressProvider),
+ configurationController
).create(view, touchEventHandler)
}
diff --git a/services/companion/Android.bp b/services/companion/Android.bp
index e3926b4..d3ef6dc 100644
--- a/services/companion/Android.bp
+++ b/services/companion/Android.bp
@@ -24,5 +24,8 @@
type: "stream",
},
srcs: [":services.companion-sources"],
- libs: ["services.core"],
+ libs: [
+ "app-compat-annotations",
+ "services.core",
+ ],
}
diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
new file mode 100644
index 0000000..a6a8793
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -0,0 +1,94 @@
+/*
+ * 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.server.companion.virtual;
+
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
+import android.annotation.NonNull;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
+import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
+import android.os.Build;
+import android.os.UserHandle;
+import android.window.DisplayWindowPolicyController;
+
+import java.util.List;
+
+
+/**
+ * A controller to control the policies of the windows that can be displayed on the virtual display.
+ */
+class GenericWindowPolicyController extends DisplayWindowPolicyController {
+
+ /**
+ * If required, allow the secure activity to display on remote device since
+ * {@link android.os.Build.VERSION_CODES#TIRAMISU}.
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ public static final long ALLOW_SECURE_ACTIVITY_DISPLAY_ON_REMOTE_DEVICE = 201712607L;
+
+ GenericWindowPolicyController(int windowFlags, int systemWindowFlags) {
+ setInterestedWindowFlags(windowFlags, systemWindowFlags);
+ }
+
+ @Override
+ public boolean canContainActivities(@NonNull List<ActivityInfo> activities) {
+ // Can't display all the activities if any of them don't want to be displayed.
+ final int activityCount = activities.size();
+ for (int i = 0; i < activityCount; i++) {
+ final ActivityInfo aInfo = activities.get(i);
+ if ((aInfo.flags & ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES) == 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean keepActivityOnWindowFlagsChanged(ActivityInfo activityInfo, int windowFlags,
+ int systemWindowFlags) {
+ if ((activityInfo.flags & ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES) == 0) {
+ return false;
+ }
+ if (!CompatChanges.isChangeEnabled(ALLOW_SECURE_ACTIVITY_DISPLAY_ON_REMOTE_DEVICE,
+ activityInfo.packageName,
+ UserHandle.getUserHandleForUid(activityInfo.applicationInfo.uid))) {
+ // TODO(b/201712607): Add checks for the apps that use SurfaceView#setSecure.
+ if ((windowFlags & FLAG_SECURE) != 0) {
+ return false;
+ }
+ if ((systemWindowFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void onTopActivityChanged(ComponentName topActivity, int uid) {
+
+ }
+
+ @Override
+ public void onRunningAppsChanged(int[] runningUids) {
+
+ }
+}
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index 020d08f..2742608 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -16,6 +16,9 @@
package com.android.server.companion.virtual;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
@@ -131,11 +134,14 @@
private final AssociationInfo mAssociationInfo;
private final int mOwnerUid;
+ private final GenericWindowPolicyController mGenericWindowPolicyController;
private final ArrayList<Integer> mDisplayIds = new ArrayList<>();
private VirtualDeviceImpl(int ownerUid, IBinder token, AssociationInfo associationInfo) {
mOwnerUid = ownerUid;
mAssociationInfo = associationInfo;
+ mGenericWindowPolicyController = new GenericWindowPolicyController(FLAG_SECURE,
+ SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
try {
token.linkToDeath(this, 0);
} catch (RemoteException e) {
@@ -167,8 +173,7 @@
"Virtual device already have a virtual display with ID " + displayId);
}
mDisplayIds.add(displayId);
- // TODO(b/201712607): Return the corresponding DisplayWindowPolicyController.
- return null;
+ return mGenericWindowPolicyController;
}
void onVirtualDisplayRemovedLocked(int displayId) {
diff --git a/services/core/java/com/android/server/communal/CommunalManagerService.java b/services/core/java/com/android/server/communal/CommunalManagerService.java
index 8d9b13e..3bf6ca2 100644
--- a/services/core/java/com/android/server/communal/CommunalManagerService.java
+++ b/services/core/java/com/android/server/communal/CommunalManagerService.java
@@ -30,6 +30,7 @@
import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.communal.ICommunalManager;
+import android.app.communal.ICommunalModeListener;
import android.app.compat.CompatChanges;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -42,6 +43,8 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.dreams.DreamManagerInternal;
@@ -77,6 +80,8 @@
private final PackageReceiver mPackageReceiver;
private final PackageManager mPackageManager;
private final DreamManagerInternal mDreamManagerInternal;
+ private final RemoteCallbackList<ICommunalModeListener> mListeners =
+ new RemoteCallbackList<>();
private final ActivityInterceptorCallback mActivityInterceptorCallback =
new ActivityInterceptorCallback() {
@@ -129,7 +134,7 @@
@Override
public void onStart() {
- publishBinderService(Context.COMMUNAL_MANAGER_SERVICE, mBinderService);
+ publishBinderService(Context.COMMUNAL_SERVICE, mBinderService);
}
@Override
@@ -242,6 +247,27 @@
return !isAppAllowed(appInfo);
}
+ private void dispatchCommunalMode(boolean isShowing) {
+ synchronized (mListeners) {
+ int i = mListeners.beginBroadcast();
+ while (i > 0) {
+ i--;
+ try {
+ mListeners.getBroadcastItem(i).onCommunalModeChanged(isShowing);
+ } catch (RemoteException e) {
+ // Handled by the RemoteCallbackList.
+ }
+ }
+ mListeners.finishBroadcast();
+ }
+ }
+
+ private void enforceReadPermission() {
+ mContext.enforceCallingPermission(Manifest.permission.READ_COMMUNAL_STATE,
+ Manifest.permission.READ_COMMUNAL_STATE
+ + "permission required to read communal state.");
+ }
+
private final class BinderService extends ICommunalManager.Stub {
/**
* Sets whether or not we are in communal mode.
@@ -252,7 +278,43 @@
mContext.enforceCallingPermission(Manifest.permission.WRITE_COMMUNAL_STATE,
Manifest.permission.WRITE_COMMUNAL_STATE
+ "permission required to modify communal state.");
+ if (mCommunalViewIsShowing.get() == isShowing) {
+ return;
+ }
mCommunalViewIsShowing.set(isShowing);
+ dispatchCommunalMode(isShowing);
+ }
+
+ /**
+ * Checks whether or not we are in communal mode.
+ */
+ @RequiresPermission(Manifest.permission.READ_COMMUNAL_STATE)
+ @Override
+ public boolean isCommunalMode() {
+ enforceReadPermission();
+ return mCommunalViewIsShowing.get();
+ }
+
+ /**
+ * Adds a callback to execute when communal state changes.
+ */
+ @RequiresPermission(Manifest.permission.READ_COMMUNAL_STATE)
+ public void addCommunalModeListener(ICommunalModeListener listener) {
+ enforceReadPermission();
+ synchronized (mListeners) {
+ mListeners.register(listener);
+ }
+ }
+
+ /**
+ * Removes an added callback that execute when communal state changes.
+ */
+ @RequiresPermission(Manifest.permission.READ_COMMUNAL_STATE)
+ public void removeCommunalModeListener(ICommunalModeListener listener) {
+ enforceReadPermission();
+ synchronized (mListeners) {
+ mListeners.unregister(listener);
+ }
}
}
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
index 6628802..e508260 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
@@ -243,21 +243,24 @@
@Override
public boolean requestFrontend(@NonNull TunerFrontendRequest request,
- @NonNull int[] frontendHandle) throws RemoteException {
+ @NonNull int[] frontendHandle) {
enforceTunerAccessPermission("requestFrontend");
enforceTrmAccessPermission("requestFrontend");
if (frontendHandle == null) {
- throw new RemoteException("frontendHandle can't be null");
+ Slog.e(TAG, "frontendHandle can't be null");
+ return false;
}
synchronized (mLock) {
if (!checkClientExists(request.clientId)) {
- throw new RemoteException("Request frontend from unregistered client: "
+ Slog.e(TAG, "Request frontend from unregistered client: "
+ request.clientId);
+ return false;
}
// If the request client is holding or sharing a frontend, throw an exception.
if (!getClientProfile(request.clientId).getInUseFrontendHandles().isEmpty()) {
- throw new RemoteException("Release frontend before requesting another one. "
- + "Client id: " + request.clientId);
+ Slog.e(TAG, "Release frontend before requesting another one. Client id: "
+ + request.clientId);
+ return false;
}
return requestFrontendInternal(request, frontendHandle);
}
@@ -1153,7 +1156,8 @@
ClientProfile ownerClient = getClientProfile(fe.getOwnerClientId());
if (ownerClient != null) {
for (int shareOwnerId : ownerClient.getShareFeClientIds()) {
- clearFrontendAndClientMapping(getClientProfile(shareOwnerId));
+ reclaimResource(shareOwnerId,
+ TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND);
}
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/communal/CommunalManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/communal/CommunalManagerServiceTest.java
index 17d7c51..d6db1b2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/communal/CommunalManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/communal/CommunalManagerServiceTest.java
@@ -123,6 +123,8 @@
doNothing().when(mContextSpy).enforceCallingPermission(
eq(Manifest.permission.WRITE_COMMUNAL_STATE), anyString());
+ doNothing().when(mContextSpy).enforceCallingPermission(
+ eq(Manifest.permission.READ_COMMUNAL_STATE), anyString());
mService = new CommunalManagerService(mContextSpy);
mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
@@ -203,6 +205,18 @@
}
@Test
+ public void testIsCommunalMode_isTrue() throws RemoteException {
+ mBinder.setCommunalViewShowing(true);
+ assertThat(mBinder.isCommunalMode()).isTrue();
+ }
+
+ @Test
+ public void testIsCommunalMode_isFalse() throws RemoteException {
+ mBinder.setCommunalViewShowing(false);
+ assertThat(mBinder.isCommunalMode()).isFalse();
+ }
+
+ @Test
public void testIntercept_unlocked_communalOff_appNotEnabled_showWhenLockedOff() {
when(mKeyguardManager.isKeyguardLocked()).thenReturn(false);
mAInfo.flags = 0;
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 6f92c31..7d24b76 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1063,6 +1063,12 @@
"always_show_emergency_alert_onoff_bool";
/**
+ * Default mobile network MTU value, in bytes.
+ * @hide
+ */
+ public static final String KEY_DEFAULT_MTU_INT = "default_mtu_int";
+
+ /**
* The data call retry configuration for different types of APN.
* @hide
*/
@@ -2914,19 +2920,37 @@
"signal_strength_nr_nsa_use_lte_as_primary_bool";
/**
+ * String array of TCP buffer sizes per network type.
+ * The entries should be of the following form, with values in bytes:
+ * "network_name:read_min,read_default,read_max,write_min,write_default,write_max".
+ * For NR (5G), the following network names should be used:
+ * - NR_NSA: NR NSA, sub-6 frequencies
+ * - NR_NSA_MMWAVE: NR NSA, mmwave frequencies
+ * - NR_SA: NR SA, sub-6 frequencies
+ * - NR_SA_MMWAVE: NR SA, mmwave frequencies
+ * @hide
+ */
+ public static final String KEY_TCP_BUFFERS_STRING_ARRAY = "tcp_buffers_string_array";
+
+ /**
* String array of default bandwidth values per network type.
- * The entries should be of form "network_name:downstream,upstream", with values in Kbps.
+ * The entries should be of form: "network_name:downlink,uplink", with values in Kbps.
+ * For NR (5G), the following network names should be used:
+ * - NR_NSA: NR NSA, sub-6 frequencies
+ * - NR_NSA_MMWAVE: NR NSA, mmwave frequencies
+ * - NR_SA: NR SA, sub-6 frequencies
+ * - NR_SA_MMWAVE: NR SA, mmwave frequencies
* @hide
*/
public static final String KEY_BANDWIDTH_STRING_ARRAY = "bandwidth_string_array";
/**
* For NR (non-standalone), whether to use the LTE value instead of NR value as the default for
- * upstream bandwidth. Downstream bandwidth will still use the NR value as the default.
+ * uplink bandwidth. Downlink bandwidth will still use the NR value as the default.
* @hide
*/
- public static final String KEY_BANDWIDTH_NR_NSA_USE_LTE_VALUE_FOR_UPSTREAM_BOOL =
- "bandwidth_nr_nsa_use_lte_value_for_upstream_bool";
+ public static final String KEY_BANDWIDTH_NR_NSA_USE_LTE_VALUE_FOR_UPLINK_BOOL =
+ "bandwidth_nr_nsa_use_lte_value_for_uplink_bool";
/**
* Key identifying if voice call barring notification is required to be shown to the user.
@@ -3628,6 +3652,18 @@
public static final String KEY_5G_WATCHDOG_TIME_MS_LONG = "5g_watchdog_time_ms_long";
/**
+ * Which NR types are unmetered. A string array containing the following keys:
+ * NR_NSA - NR NSA is unmetered for sub-6 frequencies
+ * NR_NSA_MMWAVE - NR NSA is unmetered for mmwave frequencies
+ * NR_SA - NR SA is unmetered for sub-6 frequencies
+ * NR_SA_MMWAVE - NR SA is unmetered for mmwave frequencies
+ * TODO: remove other unmetered keys and replace with this
+ * @hide
+ */
+ public static final String KEY_UNMETERED_NETWORK_TYPES_STRING_ARRAY =
+ "unmetered_network_types_string_array";
+
+ /**
* Whether NR (non-standalone) should be unmetered for all frequencies.
* If either {@link #KEY_UNMETERED_NR_NSA_MMWAVE_BOOL} or
* {@link #KEY_UNMETERED_NR_NSA_SUB6_BOOL} are true, then this value will be ignored.
@@ -5483,6 +5519,7 @@
sDefaults.putBoolean(KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL, false);
sDefaults.putBoolean(KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false);
+ sDefaults.putInt(KEY_DEFAULT_MTU_INT, 1500);
sDefaults.putStringArray(KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS, new String[]{
"default:default_randomization=2000,5000,10000,20000,40000,80000:5000,160000:5000,"
+ "320000:5000,640000:5000,1280000:5000,1800000:5000",
@@ -5801,12 +5838,35 @@
CellSignalStrengthNr.USE_SSRSRP);
sDefaults.putBoolean(KEY_SIGNAL_STRENGTH_NR_NSA_USE_LTE_AS_PRIMARY_BOOL, true);
sDefaults.putStringArray(KEY_BANDWIDTH_STRING_ARRAY, new String[]{
- "GPRS:24,24", "EDGE:70,18", "UMTS:115,115", "CDMA-IS95A:14,14", "CDMA-IS95B:14,14",
- "1xRTT:30,30", "EvDo-rev.0:750,48", "EvDo-rev.A:950,550", "HSDPA:4300,620",
- "HSUPA:4300,1800", "HSPA:4300,1800", "EvDo-rev.B:1500,550", "eHRPD:750,48",
- "HSPAP:13000,3400", "TD-SCDMA:115,115", "LTE:30000,15000", "NR_NSA:47000,18000",
- "NR_NSA_MMWAVE:145000,60000", "NR_SA:145000,60000"});
- sDefaults.putBoolean(KEY_BANDWIDTH_NR_NSA_USE_LTE_VALUE_FOR_UPSTREAM_BOOL, false);
+ "GPRS:24,24", "EDGE:70,18", "UMTS:115,115", "CDMA:14,14",
+ "1xRTT:30,30", "EvDo_0:750,48", "EvDo_A:950,550", "HSDPA:4300,620",
+ "HSUPA:4300,1800", "HSPA:4300,1800", "EvDo_B:1500,550", "eHRPD:750,48",
+ "iDEN:14,14", "LTE:30000,15000", "HSPA+:13000,3400", "GSM:24,24",
+ "TD_SCDMA:115,115", "LTE_CA:30000,15000", "NR_NSA:47000,18000",
+ "NR_NSA_MMWAVE:145000,60000", "NR_SA:145000,60000", "NR_SA_MMWAVE:145000,60000"});
+ sDefaults.putStringArray(KEY_TCP_BUFFERS_STRING_ARRAY, new String[]{
+ "GPRS:4092,8760,48000,4096,8760,48000", "EDGE:4093,26280,70800,4096,16384,70800",
+ "UMTS:58254,349525,1048576,58254,349525,1048576",
+ "CDMA:4094,87380,262144,4096,16384,262144",
+ "1xRTT:16384,32768,131072,4096,16384,102400",
+ "EvDo_0:4094,87380,262144,4096,16384,262144",
+ "EvDo_A:4094,87380,262144,4096,16384,262144",
+ "HSDPA:61167,367002,1101005,8738,52429,262114",
+ "HSUPA:40778,244668,734003,16777,100663,301990",
+ "HSPA:40778,244668,734003,16777,100663,301990",
+ "EvDo_B:4094,87380,262144,4096,16384,262144",
+ "eHRPD:131072,262144,1048576,4096,16384,524288",
+ "iDEN:4094,87380,262144,4096,16384,262144",
+ "LTE:524288,1048576,2097152,262144,524288,1048576",
+ "HSPA+:122334,734003,2202010,32040,192239,576717",
+ "GSM:4092,8760,48000,4096,8760,48000",
+ "TD_SCDMA:58254,349525,1048576,58254,349525,1048576",
+ "LTE_CA:4096,6291456,12582912,4096,1048576,2097152",
+ "NR_NSA:2097152,6291456,16777216,512000,2097152,8388608",
+ "NR_NSA_MMWAVE:2097152,6291456,16777216,512000,2097152,8388608",
+ "NR_SA:2097152,6291456,16777216,512000,2097152,8388608",
+ "NR_SA_MMWAVE:2097152,6291456,16777216,512000,2097152,8388608"});
+ sDefaults.putBoolean(KEY_BANDWIDTH_NR_NSA_USE_LTE_VALUE_FOR_UPLINK_BOOL, false);
sDefaults.putString(KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING, "rssi");
sDefaults.putBoolean(KEY_CONFIG_SHOW_ORIG_DIAL_STRING_FOR_CDMA_BOOL, false);
sDefaults.putBoolean(KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL, false);
@@ -5832,6 +5892,7 @@
sDefaults.putInt(KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT, 0);
sDefaults.putBoolean(KEY_ENABLE_NR_ADVANCED_WHILE_ROAMING_BOOL, true);
sDefaults.putBoolean(KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL, false);
+ sDefaults.putStringArray(KEY_UNMETERED_NETWORK_TYPES_STRING_ARRAY, new String[0]);
sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_BOOL, false);
sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_MMWAVE_BOOL, false);
sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_SUB6_BOOL, false);
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 114f10d..1f336f7 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2502,4 +2502,7 @@
*/
CellIdentity getLastKnownCellIdentity(int subId, String callingPackage,
String callingFeatureId);
+
+ /** Check if telephony new data stack is enabled. */
+ boolean isUsingNewDataStack();
}