summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java5
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java3
-rw-r--r--core/api/current.txt2
-rw-r--r--core/api/system-current.txt9
-rw-r--r--core/api/test-current.txt8
-rw-r--r--core/java/android/app/contextualsearch/CallbackToken.java159
-rw-r--r--core/java/android/app/contextualsearch/ContextualSearchManager.java70
-rw-r--r--core/java/android/app/contextualsearch/ContextualSearchState.java10
-rw-r--r--core/java/android/app/contextualsearch/IContextualSearchManager.aidl1
-rw-r--r--core/java/android/provider/Settings.java2
-rw-r--r--core/res/AndroidManifest.xml1
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/common/ui/RemoteViewsFactory.kt43
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilder.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt20
-rw-r--r--services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java9
20 files changed, 285 insertions, 145 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index bd00c03741f3..b897c1acd17f 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -4783,6 +4783,10 @@ public class JobSchedulerService extends com.android.server.SystemService
* Returns whether the app holds the {@link Manifest.permission.RUN_BACKUP_JOBS} permission.
*/
private boolean hasRunBackupJobsPermission(@NonNull String packageName, int packageUid) {
+ // This permission is currently hidden so always return false for now (see b/331272951)
+ return false;
+
+ /**
if (packageName == null) {
Slog.wtfStack(TAG,
"Expected a non-null package name when calling hasRunBackupJobsPermission");
@@ -4793,6 +4797,7 @@ public class JobSchedulerService extends com.android.server.SystemService
android.Manifest.permission.RUN_BACKUP_JOBS,
PermissionChecker.PID_UNKNOWN, packageUid, packageName)
== PermissionChecker.PERMISSION_GRANTED;
+ */
}
/**
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index edd86e3454a5..d643768185e3 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -1213,7 +1213,8 @@ public final class JobStatus {
return ACTIVE_INDEX;
}
- final boolean isEligibleAsBackupJob = job.getTriggerContentUris() != null
+ final boolean isEligibleAsBackupJob = false // this exemption is being disabled for now.
+ && job.getTriggerContentUris() != null
&& job.getRequiredNetwork() != null
&& !job.hasLateConstraint()
&& mJobSchedulerInternal.hasRunBackupJobsPermission(sourcePackageName, sourceUid);
diff --git a/core/api/current.txt b/core/api/current.txt
index 218fbebd66c0..950f2da02599 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -285,7 +285,6 @@ package android {
field @FlaggedApi("android.companion.flags.device_presence") public static final String REQUEST_OBSERVE_DEVICE_UUID_PRESENCE = "android.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE";
field public static final String REQUEST_PASSWORD_COMPLEXITY = "android.permission.REQUEST_PASSWORD_COMPLEXITY";
field @Deprecated public static final String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
- field @FlaggedApi("android.app.job.backup_jobs_exemption") public static final String RUN_BACKUP_JOBS = "android.permission.RUN_BACKUP_JOBS";
field public static final String RUN_USER_INITIATED_JOBS = "android.permission.RUN_USER_INITIATED_JOBS";
field public static final String SCHEDULE_EXACT_ALARM = "android.permission.SCHEDULE_EXACT_ALARM";
field public static final String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
@@ -37338,7 +37337,6 @@ package android.provider {
field public static final String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
field public static final String ACTION_REQUEST_MANAGE_MEDIA = "android.settings.REQUEST_MANAGE_MEDIA";
field @FlaggedApi("com.android.media.flags.enable_privileged_routing_for_media_routing_control") public static final String ACTION_REQUEST_MEDIA_ROUTING_CONTROL = "android.settings.REQUEST_MEDIA_ROUTING_CONTROL";
- field @FlaggedApi("android.provider.backup_tasks_settings_screen") public static final String ACTION_REQUEST_RUN_BACKUP_JOBS = "android.settings.REQUEST_RUN_BACKUP_JOBS";
field public static final String ACTION_REQUEST_SCHEDULE_EXACT_ALARM = "android.settings.REQUEST_SCHEDULE_EXACT_ALARM";
field public static final String ACTION_REQUEST_SET_AUTOFILL_SERVICE = "android.settings.REQUEST_SET_AUTOFILL_SERVICE";
field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String ACTION_SATELLITE_SETTING = "android.settings.SATELLITE_SETTING";
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 702a47ef54ec..5547028e489f 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -2178,8 +2178,15 @@ package android.app.contentsuggestions {
package android.app.contextualsearch {
+ @FlaggedApi("android.app.contextualsearch.flags.enable_service") public final class CallbackToken implements android.os.Parcelable {
+ ctor public CallbackToken();
+ method public int describeContents();
+ method public void getContextualSearchState(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.app.contextualsearch.ContextualSearchState,java.lang.Throwable>);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.contextualsearch.CallbackToken> CREATOR;
+ }
+
@FlaggedApi("android.app.contextualsearch.flags.enable_service") public class ContextualSearchManager {
- method public void getContextualSearchState(@NonNull android.os.IBinder, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.app.contextualsearch.ContextualSearchState,java.lang.Throwable>);
method @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXTUAL_SEARCH) public void startContextualSearch(int);
field public static final String ACTION_LAUNCH_CONTEXTUAL_SEARCH = "android.app.contextualsearch.action.LAUNCH_CONTEXTUAL_SEARCH";
field public static final int ENTRYPOINT_LONG_PRESS_HOME = 2; // 0x2
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 962f4f738793..0d4668877c05 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -803,6 +803,14 @@ package android.app.contentsuggestions {
}
+package android.app.contextualsearch {
+
+ @FlaggedApi("android.app.contextualsearch.flags.enable_service") public final class CallbackToken implements android.os.Parcelable {
+ method @NonNull public android.os.IBinder getToken();
+ }
+
+}
+
package android.app.job {
public class JobParameters implements android.os.Parcelable {
diff --git a/core/java/android/app/contextualsearch/CallbackToken.java b/core/java/android/app/contextualsearch/CallbackToken.java
new file mode 100644
index 000000000000..0bbd1e546e5d
--- /dev/null
+++ b/core/java/android/app/contextualsearch/CallbackToken.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2024 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.contextualsearch;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.app.contextualsearch.flags.Flags;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.OutcomeReceiver;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelableException;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Used to share a single use token with the contextual search handling activity via the launch
+ * extras bundle.
+ * The caller can then use this token to get {@link ContextualSearchState} by calling
+ * {@link #getContextualSearchState}.
+ *
+ * @hide
+ */
+@FlaggedApi(Flags.FLAG_ENABLE_SERVICE)
+@SystemApi
+public final class CallbackToken implements Parcelable {
+ private static final boolean DEBUG = true;
+ private static final String TAG = CallbackToken.class.getSimpleName();
+ private final IBinder mToken;
+
+ private boolean mTokenUsed = false;
+
+ public CallbackToken() {
+ mToken = new Binder();
+ }
+
+ private CallbackToken(Parcel in) {
+ mToken = in.readStrongBinder();
+ }
+
+ /**
+ * Returns the {@link ContextualSearchState} to the handler via the provided callback. The
+ * method can only be invoked to provide the {@link OutcomeReceiver} once and all subsequent
+ * invocations of this method will result in {@link OutcomeReceiver#onError} being called with
+ * an {@link IllegalAccessException}.
+ *
+ * @param executor The executor which will be used to invoke the callback.
+ * @param callback The callback which will be used to return {@link ContextualSearchState}
+ * if/when it is available via {@link OutcomeReceiver#onResult}. It will also be
+ * used to return errors via {@link OutcomeReceiver#onError}.
+ */
+ public void getContextualSearchState(@NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<ContextualSearchState, Throwable> callback) {
+ if (DEBUG) Log.d(TAG, "getContextualSearchState for token:" + mToken);
+ if (mTokenUsed) {
+ callback.onError(new IllegalAccessException("Token already used."));
+ }
+ mTokenUsed = true;
+ try {
+ // Get the service from the system server.
+ IBinder b = ServiceManager.getService(Context.CONTEXTUAL_SEARCH_SERVICE);
+ IContextualSearchManager service = IContextualSearchManager.Stub.asInterface(b);
+ final CallbackWrapper wrapper = new CallbackWrapper(executor, callback);
+ // If the service is not null, hand over the call to the service.
+ if (service != null) {
+ service.getContextualSearchState(mToken, wrapper);
+ } else {
+ Log.w(TAG, "Failed to getContextualSearchState. Service null.");
+ }
+ } catch (RemoteException e) {
+ if (DEBUG) Log.d(TAG, "Failed to call getContextualSearchState", e);
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Return the token necessary for validating the caller of {@link #getContextualSearchState}.
+ *
+ * @hide
+ */
+ @TestApi
+ @NonNull
+ public IBinder getToken() {
+ return mToken;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeStrongBinder(mToken);
+ }
+
+ @NonNull
+ public static final Creator<CallbackToken> CREATOR = new Creator<>() {
+ @Override
+ public CallbackToken createFromParcel(Parcel in) {
+ return new CallbackToken(in);
+ }
+
+ @Override
+ public CallbackToken[] newArray(int size) {
+ return new CallbackToken[size];
+ }
+ };
+
+ private static class CallbackWrapper extends IContextualSearchCallback.Stub {
+ private final OutcomeReceiver<ContextualSearchState, Throwable> mCallback;
+ private final Executor mExecutor;
+
+ CallbackWrapper(@NonNull Executor callbackExecutor,
+ @NonNull OutcomeReceiver<ContextualSearchState, Throwable> callback) {
+ mCallback = callback;
+ mExecutor = callbackExecutor;
+ }
+
+ @Override
+ public void onResult(ContextualSearchState state) {
+ Binder.withCleanCallingIdentity(() -> {
+ if (DEBUG) Log.d(TAG, "onResult state:" + state);
+ mExecutor.execute(() -> mCallback.onResult(state));
+ });
+ }
+
+ @Override
+ public void onError(ParcelableException error) {
+ Binder.withCleanCallingIdentity(() -> {
+ if (DEBUG) Log.w(TAG, "onError", error);
+ mExecutor.execute(() -> mCallback.onError(error));
+ });
+ }
+ }
+}
diff --git a/core/java/android/app/contextualsearch/ContextualSearchManager.java b/core/java/android/app/contextualsearch/ContextualSearchManager.java
index 693de219e7d7..a894a0e27b95 100644
--- a/core/java/android/app/contextualsearch/ContextualSearchManager.java
+++ b/core/java/android/app/contextualsearch/ContextualSearchManager.java
@@ -18,37 +18,26 @@ package android.app.contextualsearch;
import static android.Manifest.permission.ACCESS_CONTEXTUAL_SEARCH;
-import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
-import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.contextualsearch.flags.Flags;
import android.content.Context;
-import android.os.Binder;
-import android.os.Bundle;
import android.os.IBinder;
-import android.os.OutcomeReceiver;
-import android.os.ParcelableException;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.concurrent.Executor;
/**
* {@link ContextualSearchManager} is a system service to facilitate contextual search experience on
* configured Android devices.
* <p>
- * This class lets
- * <ul>
- * <li> a caller start contextual search by calling {@link #startContextualSearch} method.
- * <li> a handler request {@link ContextualSearchState} by calling the
- * {@link #getContextualSearchState} method.
- * </ul>
+ * This class lets a caller start contextual search by calling {@link #startContextualSearch}
+ * method.
*
* @hide
*/
@@ -92,7 +81,7 @@ public class ContextualSearchManager {
/**
* Key to get the binder token from the extras of the activity launched by contextual search.
- * This token is needed to invoke {@link #getContextualSearchState} method.
+ * This token is needed to invoke {@link CallbackToken#getContextualSearchState} method.
* Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH.
*/
public static final String EXTRA_TOKEN = "android.app.contextualsearch.extra.TOKEN";
@@ -174,57 +163,4 @@ public class ContextualSearchManager {
e.rethrowFromSystemServer();
}
}
-
- /**
- * Returns the {@link ContextualSearchState} to the handler via the provided callback.
- *
- * @param token The caller is expected to get the token from the launch extras of the handling
- * activity using {@link Bundle#getIBinder} with {@link #EXTRA_TOKEN} key.
- * <br>
- * <b>Note</b> This token is for one time use only. Subsequent uses will invoke
- * callback's {@link OutcomeReceiver#onError}.
- * @param executor The executor which will be used to invoke the callback.
- * @param callback The callback which will be used to return {@link ContextualSearchState}
- * if/when it is available via {@link OutcomeReceiver#onResult}. It will also be
- * used to return errors via {@link OutcomeReceiver#onError}.
- */
- public void getContextualSearchState(@NonNull IBinder token,
- @NonNull @CallbackExecutor Executor executor,
- @NonNull OutcomeReceiver<ContextualSearchState, Throwable> callback) {
- if (DEBUG) Log.d(TAG, "getContextualSearchState for token:" + token);
- try {
- final CallbackWrapper wrapper = new CallbackWrapper(executor, callback);
- mService.getContextualSearchState(token, wrapper);
- } catch (RemoteException e) {
- if (DEBUG) Log.d(TAG, "Failed to getContextualSearchState", e);
- e.rethrowFromSystemServer();
- }
- }
-
- private static class CallbackWrapper extends IContextualSearchCallback.Stub {
- private final OutcomeReceiver<ContextualSearchState, Throwable> mCallback;
- private final Executor mExecutor;
-
- CallbackWrapper(@NonNull Executor callbackExecutor,
- @NonNull OutcomeReceiver<ContextualSearchState, Throwable> callback) {
- mCallback = callback;
- mExecutor = callbackExecutor;
- }
-
- @Override
- public void onResult(ContextualSearchState state) {
- Binder.withCleanCallingIdentity(() -> {
- if (DEBUG) Log.d(TAG, "onResult state:" + state);
- mExecutor.execute(() -> mCallback.onResult(state));
- });
- }
-
- @Override
- public void onError(ParcelableException error) {
- Binder.withCleanCallingIdentity(() -> {
- if (DEBUG) Log.w(TAG, "onError", error);
- mExecutor.execute(() -> mCallback.onError(error));
- });
- }
- }
}
diff --git a/core/java/android/app/contextualsearch/ContextualSearchState.java b/core/java/android/app/contextualsearch/ContextualSearchState.java
index 5c04bc8933c0..f01ae55d05b6 100644
--- a/core/java/android/app/contextualsearch/ContextualSearchState.java
+++ b/core/java/android/app/contextualsearch/ContextualSearchState.java
@@ -32,6 +32,10 @@ import androidx.annotation.NonNull;
* {@link ContextualSearchState} contains additional data a contextual search handler can request
* via {@link ContextualSearchManager#getContextualSearchState} method.
*
+ * It provides the caller of {@link ContextualSearchManager#getContextualSearchState} with an
+ * {@link AssistStructure}, {@link AssistContent} and a {@link Bundle} extras containing any
+ * relevant data added by th system server. When invoked via the Launcher, this bundle is empty.
+ *
* @hide
*/
@FlaggedApi(Flags.FLAG_ENABLE_SERVICE)
@@ -41,6 +45,12 @@ public final class ContextualSearchState implements Parcelable {
private final @Nullable AssistStructure mStructure;
private final @Nullable AssistContent mContent;
+ /**
+ * {@link ContextualSearchState} contains non-essential data which can be requested by the
+ * Contextual Search activity.
+ * The activity can request an instance of {@link ContextualSearchState} by calling
+ * {@link CallbackToken#getContextualSearchState} and passing a valid token as an argument.
+ */
public ContextualSearchState(@Nullable AssistStructure structure,
@Nullable AssistContent content, @NonNull Bundle extras) {
mStructure = structure;
diff --git a/core/java/android/app/contextualsearch/IContextualSearchManager.aidl b/core/java/android/app/contextualsearch/IContextualSearchManager.aidl
index 1735a7139e6f..9b0b8b775971 100644
--- a/core/java/android/app/contextualsearch/IContextualSearchManager.aidl
+++ b/core/java/android/app/contextualsearch/IContextualSearchManager.aidl
@@ -1,6 +1,5 @@
package android.app.contextualsearch;
-
import android.app.contextualsearch.IContextualSearchCallback;
/**
* @hide
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 324852248da0..c74d50a004bf 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -696,6 +696,8 @@ public final class Settings {
* Output: When a package data uri is passed as input, the activity result is set to
* {@link android.app.Activity#RESULT_OK} if the permission was granted to the app. Otherwise,
* the result is set to {@link android.app.Activity#RESULT_CANCELED}.
+ *
+ * @hide
*/
@FlaggedApi(Flags.FLAG_BACKUP_TASKS_SETTINGS_SCREEN)
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6431db9d174e..cfe6f732e54b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -7986,6 +7986,7 @@
content URI trigger and network constraint set.
<p>This is a special access permission that can be revoked by the system or the user.
<p>Protection level: signature|privileged|appop
+ @hide
-->
<permission android:name="android.permission.RUN_BACKUP_JOBS"
android:protectionLevel="signature|privileged|appop"/>
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/RemoteViewsFactory.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/RemoteViewsFactory.kt
index 3fb915226963..7bb08d2c26e8 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/RemoteViewsFactory.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/RemoteViewsFactory.kt
@@ -17,6 +17,8 @@
package com.android.credentialmanager.common.ui
import android.content.Context
+import android.util.Log
+import com.android.credentialmanager.common.Constants
import android.widget.RemoteViews
import androidx.core.content.ContextCompat
import com.android.credentialmanager.model.get.CredentialEntryInfo
@@ -29,7 +31,8 @@ class RemoteViewsFactory {
private const val SET_ADJUST_VIEW_BOUNDS_METHOD_NAME = "setAdjustViewBounds"
private const val SET_MAX_HEIGHT_METHOD_NAME = "setMaxHeight"
private const val SET_BACKGROUND_RESOURCE_METHOD_NAME = "setBackgroundResource"
- private const val BULLET_POINT = "\u2022"
+ private const val SEPARATOR = " " + "\u2022" + " "
+
// TODO(jbabs): RemoteViews#setViewPadding renders this as 8dp on the display. Debug why.
private const val END_ITEMS_PADDING = 28
@@ -43,20 +46,14 @@ class RemoteViewsFactory {
var layoutId: Int = com.android.credentialmanager.R.layout
.credman_dropdown_presentation_layout
val remoteViews = RemoteViews(context.packageName, layoutId)
- if (credentialEntryInfo.credentialType == CredentialType.UNKNOWN) {
- return remoteViews
- }
val displayName = credentialEntryInfo.displayName ?: credentialEntryInfo.userName
remoteViews.setTextViewText(android.R.id.text1, displayName)
- val secondaryText =
- if (credentialEntryInfo.displayName != null
- && (credentialEntryInfo.displayName != credentialEntryInfo.userName))
- (credentialEntryInfo.userName + " " + BULLET_POINT + " "
- + credentialEntryInfo.credentialTypeDisplayName
- + " " + BULLET_POINT + " " + credentialEntryInfo.providerDisplayName)
- else (credentialEntryInfo.credentialTypeDisplayName + " " + BULLET_POINT + " "
- + credentialEntryInfo.providerDisplayName)
- remoteViews.setTextViewText(android.R.id.text2, secondaryText)
+ val secondaryText = getSecondaryText(credentialEntryInfo)
+ if (secondaryText.isNullOrBlank()) {
+ Log.w(Constants.LOG_TAG, "Secondary text for dropdown is null")
+ } else {
+ remoteViews.setTextViewText(android.R.id.text2, secondaryText)
+ }
remoteViews.setImageViewIcon(android.R.id.icon1, icon);
remoteViews.setBoolean(
android.R.id.icon1, SET_ADJUST_VIEW_BOUNDS_METHOD_NAME, true);
@@ -88,6 +85,26 @@ class RemoteViewsFactory {
return remoteViews
}
+ /**
+ * Computes the secondary text for dropdown presentation based on available fields.
+ *
+ * <p> Format for secondary text is [username] . [credentialType] . [providerDisplayName]
+ * If display name and username are the same, we do not display username
+ * If credential type is missing as in the case with SiwG, we just display
+ * providerDisplayName. Both credential type and provider display name should not be empty.
+ */
+ private fun getSecondaryText(credentialEntryInfo: CredentialEntryInfo): String? {
+ return listOf(if (credentialEntryInfo.displayName != null
+ && (credentialEntryInfo.displayName != credentialEntryInfo.userName))
+ (credentialEntryInfo.userName) else null,
+ credentialEntryInfo.credentialTypeDisplayName,
+ credentialEntryInfo.providerDisplayName).filterNot { it.isNullOrBlank() }
+ .let { itemsToDisplay ->
+ if (itemsToDisplay.isEmpty()) null
+ else itemsToDisplay.joinToString(separator = SEPARATOR)
+ }
+ }
+
fun createMoreSignInOptionsPresentation(context: Context): RemoteViews {
var layoutId: Int = com.android.credentialmanager.R.layout
.credman_dropdown_bottom_sheet
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
index 1adb3359b17f..e7bfee34e76a 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/GridDragDropState.kt
@@ -34,10 +34,12 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
+import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.toOffset
import androidx.compose.ui.unit.toSize
@@ -235,6 +237,7 @@ fun Modifier.dragContainer(
}
/** Wrap LazyGrid item with additional modifier needed for drag and drop. */
+@OptIn(ExperimentalComposeUiApi::class)
@ExperimentalFoundationApi
@Composable
fun LazyGridItemScope.DraggableItem(
@@ -269,7 +272,11 @@ fun LazyGridItemScope.DraggableItem(
Box(modifier) {
Box(draggingModifier) { content(dragging) }
AnimatedVisibility(
- modifier = Modifier.matchParentSize(),
+ modifier =
+ Modifier.matchParentSize()
+ // Do not consume motion events in the highlighted item and pass them down to
+ // the content.
+ .pointerInteropFilter { false },
visible = (dragging || selected) && !dragDropState.isDraggingToRemove,
enter = fadeIn(),
exit = fadeOut()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 182798e097d3..53aee5da0793 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2520,18 +2520,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
String message = "";
switch (msg.what) {
case SHOW:
- // There is a potential race condition when SysUI starts up. CentralSurfaces
- // must invoke #registerCentralSurfaces on this class before any messages can be
- // processed. If this happens, repost the message with a small delay and try
- // again.
- if (mCentralSurfaces == null) {
- message = "DELAYING SHOW";
- Message newMsg = mHandler.obtainMessage(SHOW, (Bundle) msg.obj);
- mHandler.sendMessageDelayed(newMsg, 100);
- } else {
- message = "SHOW";
- handleShow((Bundle) msg.obj);
- }
+ message = "SHOW";
+ handleShow((Bundle) msg.obj);
break;
case HIDE:
message = "HIDE";
@@ -2618,18 +2608,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
Trace.endSection();
break;
case SYSTEM_READY:
- // There is a potential race condition when SysUI starts up. CentralSurfaces
- // must invoke #registerCentralSurfaces on this class before any messages can be
- // processed. If this happens, repost the message with a small delay and try
- // again.
- if (mCentralSurfaces == null) {
- message = "DELAYING SYSTEM_READY";
- Message newMsg = mHandler.obtainMessage(SYSTEM_READY);
- mHandler.sendMessageDelayed(newMsg, 100);
- } else {
- message = "SYSTEM_READY";
- handleSystemReady();
- }
+ message = "SYSTEM_READY";
+ handleSystemReady();
break;
}
Log.d(TAG, "KeyguardViewMediator queue processing message: " + message);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilder.java
index 80c3551b7de0..321b6084831e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputNotificationRebuilder.java
@@ -71,6 +71,15 @@ public class RemoteInputNotificationRebuilder {
@NonNull
public StatusBarNotification rebuildForCanceledSmartReplies(
NotificationEntry entry) {
+ return rebuildWithExistingReplies(entry);
+ }
+
+ /**
+ * Rebuilds to include any previously-added remote input replies.
+ * For when the app cancels a notification that has already been lifetime extended.
+ */
+ @NonNull
+ public StatusBarNotification rebuildWithExistingReplies(NotificationEntry entry) {
return rebuildWithRemoteInputInserted(entry, null /* remoteInputText */,
false /* showSpinner */, null /* mimeType */, null /* uri */);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt
index 28fff1519032..fe59d732cceb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt
@@ -127,6 +127,15 @@ class RemoteInputCoordinator @Inject constructor(
mSmartReplyController.stopSending(entry)
mNotifUpdater.onInternalNotificationUpdate(newSbn,
"Extending lifetime of notification with smart reply")
+ } else {
+ // The app may have re-cancelled a notification after it had already
+ // been lifetime extended.
+ // Rebuild the notification with the replies it already had to ensure
+ // those replies continue to be displayed.
+ val newSbn = mRebuilder.rebuildWithExistingReplies(entry)
+ mNotifUpdater.onInternalNotificationUpdate(newSbn,
+ "Extending lifetime of notification that has already been " +
+ "lifetime extended.")
}
} else {
// Notifications updated without FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index f76de04c0c18..710cdcd5fcde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -836,7 +836,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mLightRevealScrimViewModelLazy = lightRevealScrimViewModelLazy;
mLightRevealScrim = lightRevealScrim;
- // Based on teamfood flag, turn predictive back dispatch on at runtime.
if (predictiveBackSysui()) {
mContext.getApplicationInfo().setEnableOnBackInvokedCallback(true);
}
@@ -3060,6 +3059,9 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
public void onConfigChanged(Configuration newConfig) {
updateResources();
updateDisplaySize(); // populates mDisplayMetrics
+ if (predictiveBackSysui()) {
+ mContext.getApplicationInfo().setEnableOnBackInvokedCallback(true);
+ }
if (DEBUG) {
Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 272b48876a37..11ec417fc5f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -306,28 +306,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
@Test
@TestableLooper.RunWithLooper(setAsMainLooper = true)
- public void testRaceCondition_doNotRegisterCentralSurfacesImmediately() {
- create(false);
-
- // GIVEN central surfaces is not registered with KeyguardViewMediator, but a call to enable
- // keyguard comes in
- mViewMediator.onSystemReady();
- mViewMediator.setKeyguardEnabled(true);
- TestableLooper.get(this).processAllMessages();
-
- // If this step has been reached, then system ui has not crashed. Now register
- // CentralSurfaces
- assertFalse(mViewMediator.isShowingAndNotOccluded());
- register();
- TestableLooper.get(this).moveTimeForward(100);
- TestableLooper.get(this).processAllMessages();
-
- // THEN keyguard is shown
- assertTrue(mViewMediator.isShowingAndNotOccluded());
- }
-
- @Test
- @TestableLooper.RunWithLooper(setAsMainLooper = true)
public void onLockdown_showKeyguard_evenIfKeyguardIsNotEnabledExternally() {
// GIVEN keyguard is not enabled and isn't showing
mViewMediator.onSystemReady();
@@ -1206,11 +1184,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
}
private void createAndStartViewMediator(boolean orderUnlockAndWake) {
- create(orderUnlockAndWake);
- register();
- }
-
- private void create(boolean orderUnlockAndWake) {
mContext.getOrCreateTestableResources().addOverride(
com.android.internal.R.bool.config_orderUnlockAndWake, orderUnlockAndWake);
@@ -1262,9 +1235,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
mKeyguardInteractor,
mock(WindowManagerOcclusionManager.class));
mViewMediator.start();
- }
- private void register() {
mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null, null);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt
index 85b8b03a1b46..d3df48e9ef02 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt
@@ -98,6 +98,7 @@ class RemoteInputCoordinatorTest : SysuiTestCase() {
`when`(rebuilder.rebuildForCanceledSmartReplies(any())).thenReturn(sbn)
`when`(rebuilder.rebuildForRemoteInputReply(any())).thenReturn(sbn)
`when`(rebuilder.rebuildForSendingSmartReply(any(), any())).thenReturn(sbn)
+ `when`(rebuilder.rebuildWithExistingReplies(any())).thenReturn(sbn)
}
val remoteInputActiveExtender get() = coordinator.mRemoteInputActiveExtender
@@ -208,13 +209,30 @@ class RemoteInputCoordinatorTest : SysuiTestCase() {
it.onEntryUpdated(entry, true)
}
-
verify(rebuilder, times(1)).rebuildForCanceledSmartReplies(entry)
verify(smartReplyController, times(1)).stopSending(entry)
}
@Test
@EnableFlags(FLAG_LIFETIME_EXTENSION_REFACTOR)
+ fun testRepeatedUpdateTriggersRebuild() {
+ // Create notification with LIFETIME_EXTENDED_BY_DIRECT_REPLY flag.
+ val entry = NotificationEntryBuilder()
+ .setId(3)
+ .setTag("entry")
+ .setFlag(mContext, Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY, true)
+ .build()
+ `when`(remoteInputManager.shouldKeepForRemoteInputHistory(entry)).thenReturn(false)
+ `when`(remoteInputManager.shouldKeepForSmartReplyHistory(entry)).thenReturn(false)
+ collectionListeners.forEach {
+ it.onEntryUpdated(entry, true)
+ }
+
+ verify(rebuilder, times(1)).rebuildWithExistingReplies(entry)
+ }
+
+ @Test
+ @EnableFlags(FLAG_LIFETIME_EXTENSION_REFACTOR)
fun testLifetimeExtensionListenerClearsRemoteInputs() {
// Create notification with LIFETIME_EXTENDED_BY_DIRECT_REPLY flag.
val entry = NotificationEntryBuilder()
diff --git a/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java b/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
index b28bc1ffb611..16a99333796c 100644
--- a/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
+++ b/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
@@ -29,6 +29,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.app.ActivityOptions;
import android.app.admin.DevicePolicyManagerInternal;
+import android.app.contextualsearch.CallbackToken;
import android.app.contextualsearch.ContextualSearchManager;
import android.app.contextualsearch.ContextualSearchState;
import android.app.contextualsearch.IContextualSearchCallback;
@@ -164,7 +165,7 @@ public class ContextualSearchManagerService extends SystemService {
}
}
- private Intent getContextualSearchIntent(int entrypoint, IBinder mToken) {
+ private Intent getContextualSearchIntent(int entrypoint, CallbackToken mToken) {
final Intent launchIntent = getResolvedLaunchIntent();
if (launchIntent == null) {
return null;
@@ -256,14 +257,14 @@ public class ContextualSearchManagerService extends SystemService {
}
private class ContextualSearchManagerStub extends IContextualSearchManager.Stub {
- private @Nullable IBinder mToken;
+ private @Nullable CallbackToken mToken;
@Override
public void startContextualSearch(int entrypoint) {
synchronized (this) {
if (DEBUG_USER) Log.d(TAG, "startContextualSearch");
enforcePermission("startContextualSearch");
- mToken = new Binder();
+ mToken = new CallbackToken();
// We get the launch intent with the system server's identity because the system
// server has READ_FRAME_BUFFER permission to get the screenshot and because only
// the system server can invoke non-exported activities.
@@ -284,7 +285,7 @@ public class ContextualSearchManagerService extends SystemService {
if (DEBUG_USER) {
Log.i(TAG, "getContextualSearchState token: " + token + ", callback: " + callback);
}
- if (mToken == null || !mToken.equals(token)) {
+ if (mToken == null || !mToken.getToken().equals(token)) {
if (DEBUG_USER) {
Log.e(TAG, "getContextualSearchState: invalid token, returning error");
}