Merge "Skip provider switching dialog when app sets a preferred default." into udc-dev
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 3312294..9e59ee4 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2547,7 +2547,7 @@
.setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
new AppOpInfo.Builder(OP_TURN_SCREEN_ON, OPSTR_TURN_SCREEN_ON, "TURN_SCREEN_ON")
.setPermission(Manifest.permission.TURN_SCREEN_ON)
- .setDefaultMode(AppOpsManager.MODE_ERRORED).build(),
+ .setDefaultMode(AppOpsManager.MODE_DEFAULT).build(),
new AppOpInfo.Builder(OP_GET_ACCOUNTS, OPSTR_GET_ACCOUNTS, "GET_ACCOUNTS")
.setPermission(Manifest.permission.GET_ACCOUNTS)
.setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 63da0a2..d375760 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2916,6 +2916,14 @@
}
}
+ if (isStyle(CallStyle.class) & extras != null) {
+ Person callPerson = extras.getParcelable(EXTRA_CALL_PERSON);
+ if (callPerson != null) {
+ visitor.accept(callPerson.getIconUri());
+ }
+ visitIconUri(visitor, extras.getParcelable(EXTRA_VERIFICATION_ICON));
+ }
+
if (mBubbleMetadata != null) {
visitIconUri(visitor, mBubbleMetadata.getIcon());
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 74a69a6..307f306 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -12349,7 +12349,9 @@
null, new String[] { getType() },
new ClipData.Item(text, htmlText, null, stream));
setClipData(clipData);
- addFlags(FLAG_GRANT_READ_URI_PERMISSION);
+ if (stream != null) {
+ addFlags(FLAG_GRANT_READ_URI_PERMISSION);
+ }
return true;
}
} catch (ClassCastException e) {
@@ -12388,7 +12390,9 @@
}
setClipData(clipData);
- addFlags(FLAG_GRANT_READ_URI_PERMISSION);
+ if (streams != null) {
+ addFlags(FLAG_GRANT_READ_URI_PERMISSION);
+ }
return true;
}
} catch (ClassCastException e) {
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 048289f..960d10a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2628,6 +2628,15 @@
return Build.VERSION_CODES.CUR_DEVELOPMENT;
}
+ // STOPSHIP: hack for the pre-release SDK
+ if (platformSdkCodenames.length == 0
+ && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
+ targetCode)) {
+ Slog.w(TAG, "Package requires development platform " + targetCode
+ + ", returning current version " + Build.VERSION.SDK_INT);
+ return Build.VERSION.SDK_INT;
+ }
+
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
outError[0] = "Requires development platform " + targetCode
@@ -2699,6 +2708,15 @@
return Build.VERSION_CODES.CUR_DEVELOPMENT;
}
+ // STOPSHIP: hack for the pre-release SDK
+ if (platformSdkCodenames.length == 0
+ && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
+ minCode)) {
+ Slog.w(TAG, "Package requires min development platform " + minCode
+ + ", returning current version " + Build.VERSION.SDK_INT);
+ return Build.VERSION.SDK_INT;
+ }
+
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
outError[0] = "Requires development platform " + minCode
diff --git a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
index 3e1c5bb..8cc4cdb 100644
--- a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
@@ -316,6 +316,15 @@
return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
}
+ // STOPSHIP: hack for the pre-release SDK
+ if (platformSdkCodenames.length == 0
+ && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
+ minCode)) {
+ Slog.w(TAG, "Parsed package requires min development platform " + minCode
+ + ", returning current version " + Build.VERSION.SDK_INT);
+ return input.success(Build.VERSION.SDK_INT);
+ }
+
// Otherwise, we're looking at an incompatible pre-release SDK.
if (platformSdkCodenames.length > 0) {
return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
@@ -368,19 +377,27 @@
return input.success(targetVers);
}
+ // If it's a pre-release SDK and the codename matches this platform, it
+ // definitely targets this SDK.
+ if (matchTargetCode(platformSdkCodenames, targetCode)) {
+ return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
+ }
+
+ // STOPSHIP: hack for the pre-release SDK
+ if (platformSdkCodenames.length == 0
+ && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
+ targetCode)) {
+ Slog.w(TAG, "Parsed package requires development platform " + targetCode
+ + ", returning current version " + Build.VERSION.SDK_INT);
+ return input.success(Build.VERSION.SDK_INT);
+ }
+
try {
if (allowUnknownCodenames && UnboundedSdkLevel.isAtMost(targetCode)) {
return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
}
} catch (IllegalArgumentException e) {
- // isAtMost() throws it when encountering an older SDK codename
- return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, e.getMessage());
- }
-
- // If it's a pre-release SDK and the codename matches this platform, it
- // definitely targets this SDK.
- if (matchTargetCode(platformSdkCodenames, targetCode)) {
- return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
+ return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, "Bad package SDK");
}
// Otherwise, we're looking at an incompatible pre-release SDK.
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index a5e7086..b65c1a1 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -845,11 +845,7 @@
// Calling overScrollBy will call onOverScrolled, which
// calls onScrollChanged if applicable.
- if (overScrollBy(0, deltaY, 0, mScrollY, 0, range, 0, mOverscrollDistance, true)
- && !hasNestedScrollingParent()) {
- // Break our velocity if we hit a scroll barrier.
- mVelocityTracker.clear();
- }
+ overScrollBy(0, deltaY, 0, mScrollY, 0, range, 0, mOverscrollDistance, true);
final int scrolledDeltaY = mScrollY - oldY;
final int unconsumedY = deltaY - scrolledDeltaY;
@@ -894,6 +890,7 @@
mActivePointerId = INVALID_POINTER;
endDrag();
+ velocityTracker.clear();
}
break;
case MotionEvent.ACTION_CANCEL:
diff --git a/core/java/android/window/BackNavigationInfo.java b/core/java/android/window/BackNavigationInfo.java
index e0ee683..e44f436 100644
--- a/core/java/android/window/BackNavigationInfo.java
+++ b/core/java/android/window/BackNavigationInfo.java
@@ -94,26 +94,29 @@
@Nullable
private final IOnBackInvokedCallback mOnBackInvokedCallback;
private final boolean mPrepareRemoteAnimation;
+ private final boolean mAnimationCallback;
@Nullable
private final CustomAnimationInfo mCustomAnimationInfo;
/**
* Create a new {@link BackNavigationInfo} instance.
*
- * @param type The {@link BackTargetType} of the destination (what will be
- * @param onBackNavigationDone The callback to be called once the client is done with the
- * back preview.
- * @param onBackInvokedCallback The back callback registered by the current top level window.
+ * @param type The {@link BackTargetType} of the destination (what will be
+ * @param onBackNavigationDone The callback to be called once the client is done with the
+ * back preview.
+ * @param onBackInvokedCallback The back callback registered by the current top level window.
*/
private BackNavigationInfo(@BackTargetType int type,
@Nullable RemoteCallback onBackNavigationDone,
@Nullable IOnBackInvokedCallback onBackInvokedCallback,
boolean isPrepareRemoteAnimation,
+ boolean isAnimationCallback,
@Nullable CustomAnimationInfo customAnimationInfo) {
mType = type;
mOnBackNavigationDone = onBackNavigationDone;
mOnBackInvokedCallback = onBackInvokedCallback;
mPrepareRemoteAnimation = isPrepareRemoteAnimation;
+ mAnimationCallback = isAnimationCallback;
mCustomAnimationInfo = customAnimationInfo;
}
@@ -122,6 +125,7 @@
mOnBackNavigationDone = in.readTypedObject(RemoteCallback.CREATOR);
mOnBackInvokedCallback = IOnBackInvokedCallback.Stub.asInterface(in.readStrongBinder());
mPrepareRemoteAnimation = in.readBoolean();
+ mAnimationCallback = in.readBoolean();
mCustomAnimationInfo = in.readTypedObject(CustomAnimationInfo.CREATOR);
}
@@ -132,6 +136,7 @@
dest.writeTypedObject(mOnBackNavigationDone, flags);
dest.writeStrongInterface(mOnBackInvokedCallback);
dest.writeBoolean(mPrepareRemoteAnimation);
+ dest.writeBoolean(mAnimationCallback);
dest.writeTypedObject(mCustomAnimationInfo, flags);
}
@@ -159,7 +164,7 @@
}
/**
- * Return true if the core is preparing a back gesture nimation.
+ * Return true if the core is preparing a back gesture animation.
* @hide
*/
public boolean isPrepareRemoteAnimation() {
@@ -167,6 +172,14 @@
}
/**
+ * Return true if the callback is {@link OnBackAnimationCallback}.
+ * @hide
+ */
+ public boolean isAnimationCallback() {
+ return mAnimationCallback;
+ }
+
+ /**
* Callback to be called when the back preview is finished in order to notify the server that
* it can clean up the resources created for the animation.
* @hide
@@ -214,6 +227,8 @@
+ "mType=" + typeToString(mType) + " (" + mType + ")"
+ ", mOnBackNavigationDone=" + mOnBackNavigationDone
+ ", mOnBackInvokedCallback=" + mOnBackInvokedCallback
+ + ", mPrepareRemoteAnimation=" + mPrepareRemoteAnimation
+ + ", mAnimationCallback=" + mAnimationCallback
+ ", mCustomizeAnimationInfo=" + mCustomAnimationInfo
+ '}';
}
@@ -343,6 +358,7 @@
private IOnBackInvokedCallback mOnBackInvokedCallback = null;
private boolean mPrepareRemoteAnimation;
private CustomAnimationInfo mCustomAnimationInfo;
+ private boolean mAnimationCallback = false;
/**
* @see BackNavigationInfo#getType()
@@ -387,6 +403,7 @@
mCustomAnimationInfo.mWindowAnimations = windowAnimations;
return this;
}
+
/**
* Set resources ids for customize activity animation.
*/
@@ -402,12 +419,21 @@
}
/**
+ * @param isAnimationCallback whether the callback is {@link OnBackAnimationCallback}
+ */
+ public Builder setAnimationCallback(boolean isAnimationCallback) {
+ mAnimationCallback = isAnimationCallback;
+ return this;
+ }
+
+ /**
* Builds and returns an instance of {@link BackNavigationInfo}
*/
public BackNavigationInfo build() {
return new BackNavigationInfo(mType, mOnBackNavigationDone,
mOnBackInvokedCallback,
mPrepareRemoteAnimation,
+ mAnimationCallback,
mCustomAnimationInfo);
}
}
diff --git a/core/java/android/window/OnBackInvokedCallbackInfo.java b/core/java/android/window/OnBackInvokedCallbackInfo.java
index 6480da3..bb5fe96 100644
--- a/core/java/android/window/OnBackInvokedCallbackInfo.java
+++ b/core/java/android/window/OnBackInvokedCallbackInfo.java
@@ -28,15 +28,20 @@
@NonNull
private final IOnBackInvokedCallback mCallback;
private @OnBackInvokedDispatcher.Priority int mPriority;
+ private final boolean mIsAnimationCallback;
- public OnBackInvokedCallbackInfo(@NonNull IOnBackInvokedCallback callback, int priority) {
+ public OnBackInvokedCallbackInfo(@NonNull IOnBackInvokedCallback callback,
+ int priority,
+ boolean isAnimationCallback) {
mCallback = callback;
mPriority = priority;
+ mIsAnimationCallback = isAnimationCallback;
}
private OnBackInvokedCallbackInfo(@NonNull Parcel in) {
mCallback = IOnBackInvokedCallback.Stub.asInterface(in.readStrongBinder());
mPriority = in.readInt();
+ mIsAnimationCallback = in.readBoolean();
}
@Override
@@ -48,6 +53,7 @@
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeStrongInterface(mCallback);
dest.writeInt(mPriority);
+ dest.writeBoolean(mIsAnimationCallback);
}
public static final Creator<OnBackInvokedCallbackInfo> CREATOR =
@@ -77,9 +83,16 @@
return mPriority;
}
+ public boolean isAnimationCallback() {
+ return mIsAnimationCallback;
+ }
+
@Override
public String toString() {
return "OnBackInvokedCallbackInfo{"
- + "mCallback=" + mCallback + ", mPriority=" + mPriority + '}';
+ + "mCallback=" + mCallback
+ + ", mPriority=" + mPriority
+ + ", mIsAnimationCallback=" + mIsAnimationCallback
+ + '}';
}
}
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index 8066f50..51382a4 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -193,7 +193,10 @@
? ((ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback)
callback).getIOnBackInvokedCallback()
: new OnBackInvokedCallbackWrapper(callback);
- callbackInfo = new OnBackInvokedCallbackInfo(iCallback, priority);
+ callbackInfo = new OnBackInvokedCallbackInfo(
+ iCallback,
+ priority,
+ callback instanceof OnBackAnimationCallback);
}
mWindowSession.setOnBackInvokedCallbackInfo(mWindow, callbackInfo);
} catch (RemoteException e) {
diff --git a/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java b/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
index 2b08a55..853fe2f 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiSystemPropertiesFlags.java
@@ -77,6 +77,10 @@
/** Gating the removal of sorting-notifications-by-interruptiveness. */
public static final Flag NO_SORT_BY_INTERRUPTIVENESS =
devFlag("persist.sysui.notification.no_sort_by_interruptiveness");
+
+ /** Gating the logging of DND state change events. */
+ public static final Flag LOG_DND_STATE_EVENTS =
+ devFlag("persist.sysui.notification.log_dnd_state_events");
}
//// == End of flags. Everything below this line is the implementation. == ////
diff --git a/core/java/com/android/internal/inputmethod/InputMethodDebug.java b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
index 1b4afd6..bb8bdf5 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodDebug.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
@@ -255,6 +255,12 @@
return "HIDE_SOFT_INPUT_IMM_DEPRECATION";
case SoftInputShowHideReason.HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR:
return "HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR";
+ case SoftInputShowHideReason.SHOW_IME_SCREENSHOT_FROM_IMMS:
+ return "SHOW_IME_SCREENSHOT_FROM_IMMS";
+ case SoftInputShowHideReason.REMOVE_IME_SCREENSHOT_FROM_IMMS:
+ return "REMOVE_IME_SCREENSHOT_FROM_IMMS";
+ case SoftInputShowHideReason.HIDE_WHEN_INPUT_TARGET_INVISIBLE:
+ return "HIDE_WHEN_INPUT_TARGET_INVISIBLE";
default:
return "Unknown=" + reason;
}
diff --git a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
index ec9184b..6e9cd44 100644
--- a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
+++ b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
@@ -65,7 +65,10 @@
SoftInputShowHideReason.HIDE_SOFT_INPUT_IME_TOGGLE_SOFT_INPUT,
SoftInputShowHideReason.HIDE_SOFT_INPUT_EXTRACT_INPUT_CHANGED,
SoftInputShowHideReason.HIDE_SOFT_INPUT_IMM_DEPRECATION,
- SoftInputShowHideReason.HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR
+ SoftInputShowHideReason.HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR,
+ SoftInputShowHideReason.SHOW_IME_SCREENSHOT_FROM_IMMS,
+ SoftInputShowHideReason.REMOVE_IME_SCREENSHOT_FROM_IMMS,
+ SoftInputShowHideReason.HIDE_WHEN_INPUT_TARGET_INVISIBLE,
})
public @interface SoftInputShowHideReason {
/** Show soft input by {@link android.view.inputmethod.InputMethodManager#showSoftInput}. */
@@ -259,4 +262,20 @@
*/
int HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR =
ImeProtoEnums.REASON_HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR;
+
+ /**
+ * Shows ime screenshot by {@link com.android.server.inputmethod.InputMethodManagerService}.
+ */
+ int SHOW_IME_SCREENSHOT_FROM_IMMS = ImeProtoEnums.REASON_SHOW_IME_SCREENSHOT_FROM_IMMS;
+
+ /**
+ * Removes ime screenshot by {@link com.android.server.inputmethod.InputMethodManagerService}.
+ */
+ int REMOVE_IME_SCREENSHOT_FROM_IMMS = ImeProtoEnums.REASON_REMOVE_IME_SCREENSHOT_FROM_IMMS;
+
+ /**
+ * Hide soft input when the input target being removed or being obscured by an non-IME
+ * focusable overlay window.
+ */
+ int HIDE_WHEN_INPUT_TARGET_INVISIBLE = ImeProtoEnums.REASON_HIDE_WHEN_INPUT_TARGET_INVISIBLE;
}
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index bb3089b..325ebbe 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -458,6 +458,7 @@
optional float global_scale = 44;
repeated .android.graphics.RectProto keep_clear_areas = 45;
repeated .android.graphics.RectProto unrestricted_keep_clear_areas = 46;
+ repeated .android.view.InsetsSourceProto mergedLocalInsetsSources = 47;
}
message IdentifierProto {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9a54500..c928a82 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1036,9 +1036,9 @@
android:protectionLevel="dangerous" />
<!-- @SystemApi @hide Allows an application to communicate over satellite.
- Only granted if the application is a system app. -->
+ Only granted if the application is a system app or privileged app. -->
<permission android:name="android.permission.SATELLITE_COMMUNICATION"
- android:protectionLevel="internal|role" />
+ android:protectionLevel="role|signature|privileged" />
<!-- ====================================================================== -->
<!-- Permissions for accessing external storage -->
@@ -1466,6 +1466,9 @@
<!-- Allows an application to initiate a phone call without going through
the Dialer user interface for the user to confirm the call.
+ <p>
+ <em>Note: An app holding this permission can also call carrier MMI codes to change settings
+ such as call forwarding or call waiting preferences.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.CALL_PHONE"
@@ -2539,7 +2542,7 @@
<permission android:name="android.permission.TURN_SCREEN_ON"
android:label="@string/permlab_turnScreenOn"
android:description="@string/permdesc_turnScreenOn"
- android:protectionLevel="normal|appop" />
+ android:protectionLevel="signature|privileged|appop" />
<!-- ==================================================== -->
<!-- Permissions related to changing audio settings -->
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index c7395dd..a57a051 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -146,10 +146,6 @@
<bool name="config_enhanced_iwlan_handover_check">true</bool>
<java-symbol type="bool" name="config_enhanced_iwlan_handover_check" />
- <!-- Whether using the new SubscriptionManagerService or the old SubscriptionController -->
- <bool name="config_using_subscription_manager_service">true</bool>
- <java-symbol type="bool" name="config_using_subscription_manager_service" />
-
<!-- Whether asynchronously update the subscription database or not. Async mode increases
the performance, but sync mode reduces the chance of database/cache out-of-sync. -->
<bool name="config_subscription_database_async_update">true</bool>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 362d859..c6462f1 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1452,7 +1452,8 @@
without your intervention. This may result in unexpected charges or calls.
Note that this doesn\'t allow the app to call emergency numbers.
Malicious apps may cost you money by making calls without your
- confirmation.</string>
+ confirmation, or dial carrier codes which cause incoming calls to be
+ automatically forwarded to another number.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_accessImsCallService">access IMS call service</string>
@@ -5896,9 +5897,9 @@
<string name="resolver_cant_access_personal_apps_explanation">This content can\u2019t be opened with personal apps</string>
<!-- Error message. This text lets the user know that they need to turn on work apps in order to share or open content. There's also a button a user can tap to turn on the apps. [CHAR LIMIT=NONE] -->
- <string name="resolver_turn_on_work_apps">Work profile is paused</string>
- <!-- Button text. This button turns on a user's work profile so they can access their work apps and data. [CHAR LIMIT=NONE] -->
- <string name="resolver_switch_on_work">Tap to turn on</string>
+ <string name="resolver_turn_on_work_apps">Work apps are paused</string>
+ <!-- Button text. This button unpauses a user's work apps and data. [CHAR LIMIT=NONE] -->
+ <string name="resolver_switch_on_work">Unpause</string>
<!-- Error message. This text lets the user know that their current work apps don't support the specific content. [CHAR LIMIT=NONE] -->
<string name="resolver_no_work_apps_available">No work apps</string>
diff --git a/core/tests/coretests/res/drawable-nodpi/test_too_big.png b/core/tests/coretests/res/drawable-nodpi/test_too_big.png
new file mode 100644
index 0000000..3754072
--- /dev/null
+++ b/core/tests/coretests/res/drawable-nodpi/test_too_big.png
Binary files differ
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
index a53d57f..a102b3e 100644
--- a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
@@ -1127,6 +1127,31 @@
mActivityRule.runOnUiThread(() -> {});
}
+ @Test
+ public void restartValueAnimator() throws Throwable {
+ CountDownLatch latch = new CountDownLatch(1);
+ ValueAnimator.AnimatorUpdateListener listener = new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ if (((float) animation.getAnimatedValue()) != A1_START_VALUE) {
+ latch.countDown();
+ }
+ }
+ };
+ a1.addUpdateListener(listener);
+
+ mActivityRule.runOnUiThread(() -> {
+ a1.start();
+ });
+
+ // wait for a change in the value
+ assertTrue(latch.await(2, TimeUnit.SECONDS));
+
+ mActivityRule.runOnUiThread(() -> {
+ a1.start();
+ assertEquals(A1_START_VALUE, a1.getAnimatedValue());
+ });
+ }
class MyUpdateListener implements ValueAnimator.AnimatorUpdateListener {
boolean wasRunning = false;
long firstRunningFrameTime = -1;
diff --git a/core/tests/coretests/src/android/graphics/drawable/IconTest.java b/core/tests/coretests/src/android/graphics/drawable/IconTest.java
index 75390a2..5d92296 100644
--- a/core/tests/coretests/src/android/graphics/drawable/IconTest.java
+++ b/core/tests/coretests/src/android/graphics/drawable/IconTest.java
@@ -20,6 +20,7 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.RecordingCanvas;
import android.graphics.Region;
import android.os.Handler;
import android.os.HandlerThread;
@@ -371,6 +372,90 @@
}
}
+ private int getMaxWidth(int origWidth, int origHeight, int maxNumPixels) {
+ float aspRatio = (float) origWidth / (float) origHeight;
+ int newHeight = (int) Math.sqrt(maxNumPixels / aspRatio);
+ return (int) (newHeight * aspRatio);
+ }
+
+ private int getMaxHeight(int origWidth, int origHeight, int maxNumPixels) {
+ float aspRatio = (float) origWidth / (float) origHeight;
+ return (int) Math.sqrt(maxNumPixels / aspRatio);
+ }
+
+ @SmallTest
+ public void testScaleDownMaxSizeWithBitmap() throws Exception {
+ final int bmpWidth = 13_000;
+ final int bmpHeight = 10_000;
+ final int bmpBpp = 4;
+ final int maxNumPixels = RecordingCanvas.MAX_BITMAP_SIZE / bmpBpp;
+ final int maxWidth = getMaxWidth(bmpWidth, bmpHeight, maxNumPixels);
+ final int maxHeight = getMaxHeight(bmpWidth, bmpHeight, maxNumPixels);
+
+ final Bitmap bm = Bitmap.createBitmap(bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
+ final Icon ic = Icon.createWithBitmap(bm);
+ final Drawable drawable = ic.loadDrawable(mContext);
+
+ assertThat(drawable.getIntrinsicWidth()).isEqualTo(maxWidth);
+ assertThat(drawable.getIntrinsicHeight()).isEqualTo(maxHeight);
+ }
+
+ @SmallTest
+ public void testScaleDownMaxSizeWithAdaptiveBitmap() throws Exception {
+ final int bmpWidth = 20_000;
+ final int bmpHeight = 10_000;
+ final int bmpBpp = 4;
+ final int maxNumPixels = RecordingCanvas.MAX_BITMAP_SIZE / bmpBpp;
+ final int maxWidth = getMaxWidth(bmpWidth, bmpHeight, maxNumPixels);
+ final int maxHeight = getMaxHeight(bmpWidth, bmpHeight, maxNumPixels);
+
+ final Bitmap bm = Bitmap.createBitmap(bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888);
+ final Icon ic = Icon.createWithAdaptiveBitmap(bm);
+ final AdaptiveIconDrawable adaptiveDrawable = (AdaptiveIconDrawable) ic.loadDrawable(
+ mContext);
+ final Drawable drawable = adaptiveDrawable.getForeground();
+
+ assertThat(drawable.getIntrinsicWidth()).isEqualTo(maxWidth);
+ assertThat(drawable.getIntrinsicHeight()).isEqualTo(maxHeight);
+ }
+
+ @SmallTest
+ public void testScaleDownMaxSizeWithResource() throws Exception {
+ final Icon ic = Icon.createWithResource(getContext(), R.drawable.test_too_big);
+ final BitmapDrawable drawable = (BitmapDrawable) ic.loadDrawable(mContext);
+
+ assertThat(drawable.getBitmap().getByteCount()).isAtMost(RecordingCanvas.MAX_BITMAP_SIZE);
+ }
+
+ @SmallTest
+ public void testScaleDownMaxSizeWithFile() throws Exception {
+ final Bitmap bit1 = ((BitmapDrawable) getContext().getDrawable(R.drawable.test_too_big))
+ .getBitmap();
+ final File dir = getContext().getExternalFilesDir(null);
+ final File file1 = new File(dir, "file1-too-big.png");
+ bit1.compress(Bitmap.CompressFormat.PNG, 100,
+ new FileOutputStream(file1));
+
+ final Icon ic = Icon.createWithFilePath(file1.toString());
+ final BitmapDrawable drawable = (BitmapDrawable) ic.loadDrawable(mContext);
+
+ assertThat(drawable.getBitmap().getByteCount()).isAtMost(RecordingCanvas.MAX_BITMAP_SIZE);
+ }
+
+ @SmallTest
+ public void testScaleDownMaxSizeWithData() throws Exception {
+ final int bmpBpp = 4;
+ final Bitmap originalBits = ((BitmapDrawable) getContext().getDrawable(
+ R.drawable.test_too_big)).getBitmap();
+ final ByteArrayOutputStream ostream = new ByteArrayOutputStream(
+ originalBits.getWidth() * originalBits.getHeight() * bmpBpp);
+ originalBits.compress(Bitmap.CompressFormat.PNG, 100, ostream);
+ final byte[] pngdata = ostream.toByteArray();
+ final Icon ic = Icon.createWithData(pngdata, 0, pngdata.length);
+ final BitmapDrawable drawable = (BitmapDrawable) ic.loadDrawable(mContext);
+
+ assertThat(drawable.getBitmap().getByteCount()).isAtMost(RecordingCanvas.MAX_BITMAP_SIZE);
+ }
// ======== utils ========
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 8ece337..40cb7f2 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -518,6 +518,8 @@
<permission name="android.permission.LOG_FOREGROUND_RESOURCE_USE"/>
<!-- Permission required for CTS test - CtsVoiceInteractionTestCases -->
<permission name="android.permission.SOUND_TRIGGER_RUN_IN_BATTERY_SAVER"/>
+ <!-- Permission required for CTS test - SatelliteManagerTest -->
+ <permission name="android.permission.SATELLITE_COMMUNICATION"/>
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index a76d74e..708feeb 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -35,6 +35,7 @@
import android.graphics.BitmapFactory;
import android.graphics.BlendMode;
import android.graphics.PorterDuff;
+import android.graphics.RecordingCanvas;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
@@ -70,6 +71,7 @@
public final class Icon implements Parcelable {
private static final String TAG = "Icon";
+ private static final boolean DEBUG = false;
/**
* An icon that was created using {@link Icon#createWithBitmap(Bitmap)}.
@@ -361,15 +363,52 @@
}
/**
+ * Resizes image if size too large for Canvas to draw
+ * @param bitmap Bitmap to be resized if size > {@link RecordingCanvas.MAX_BITMAP_SIZE}
+ * @return resized bitmap
+ */
+ private Bitmap fixMaxBitmapSize(Bitmap bitmap) {
+ if (bitmap != null && bitmap.getByteCount() > RecordingCanvas.MAX_BITMAP_SIZE) {
+ int bytesPerPixel = bitmap.getRowBytes() / bitmap.getWidth();
+ int maxNumPixels = RecordingCanvas.MAX_BITMAP_SIZE / bytesPerPixel;
+ float aspRatio = (float) bitmap.getWidth() / (float) bitmap.getHeight();
+ int newHeight = (int) Math.sqrt(maxNumPixels / aspRatio);
+ int newWidth = (int) (newHeight * aspRatio);
+
+ if (DEBUG) {
+ Log.d(TAG,
+ "Image size too large: " + bitmap.getByteCount() + ". Resizing bitmap to: "
+ + newWidth + " " + newHeight);
+ }
+
+ return scaleDownIfNecessary(bitmap, newWidth, newHeight);
+ }
+ return bitmap;
+ }
+
+ /**
+ * Resizes BitmapDrawable if size too large for Canvas to draw
+ * @param drawable Drawable to be resized if size > {@link RecordingCanvas.MAX_BITMAP_SIZE}
+ * @return resized Drawable
+ */
+ private Drawable fixMaxBitmapSize(Resources res, Drawable drawable) {
+ if (drawable instanceof BitmapDrawable) {
+ Bitmap scaledBmp = fixMaxBitmapSize(((BitmapDrawable) drawable).getBitmap());
+ return new BitmapDrawable(res, scaledBmp);
+ }
+ return drawable;
+ }
+
+ /**
* Do the heavy lifting of loading the drawable, but stop short of applying any tint.
*/
private Drawable loadDrawableInner(Context context) {
switch (mType) {
case TYPE_BITMAP:
- return new BitmapDrawable(context.getResources(), getBitmap());
+ return new BitmapDrawable(context.getResources(), fixMaxBitmapSize(getBitmap()));
case TYPE_ADAPTIVE_BITMAP:
return new AdaptiveIconDrawable(null,
- new BitmapDrawable(context.getResources(), getBitmap()));
+ new BitmapDrawable(context.getResources(), fixMaxBitmapSize(getBitmap())));
case TYPE_RESOURCE:
if (getResources() == null) {
// figure out where to load resources from
@@ -400,7 +439,8 @@
}
}
try {
- return getResources().getDrawable(getResId(), context.getTheme());
+ return fixMaxBitmapSize(getResources(),
+ getResources().getDrawable(getResId(), context.getTheme()));
} catch (RuntimeException e) {
Log.e(TAG, String.format("Unable to load resource 0x%08x from pkg=%s",
getResId(),
@@ -409,21 +449,21 @@
}
break;
case TYPE_DATA:
- return new BitmapDrawable(context.getResources(),
- BitmapFactory.decodeByteArray(getDataBytes(), getDataOffset(), getDataLength())
- );
+ return new BitmapDrawable(context.getResources(), fixMaxBitmapSize(
+ BitmapFactory.decodeByteArray(getDataBytes(), getDataOffset(),
+ getDataLength())));
case TYPE_URI:
InputStream is = getUriInputStream(context);
if (is != null) {
return new BitmapDrawable(context.getResources(),
- BitmapFactory.decodeStream(is));
+ fixMaxBitmapSize(BitmapFactory.decodeStream(is)));
}
break;
case TYPE_URI_ADAPTIVE_BITMAP:
is = getUriInputStream(context);
if (is != null) {
return new AdaptiveIconDrawable(null, new BitmapDrawable(context.getResources(),
- BitmapFactory.decodeStream(is)));
+ fixMaxBitmapSize(BitmapFactory.decodeStream(is))));
}
break;
}
diff --git a/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml b/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
index dcce4698..ab64f9e 100644
--- a/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
@@ -67,7 +67,7 @@
<!-- Temporarily extending the background to show an edu text hint for opening the menu -->
<FrameLayout
- android:id="@+id/tv_pip_menu_edu_text_drawer_placeholder"
+ android:id="@+id/tv_pip_menu_edu_text_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/tv_pip"
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 713ace6..b6216b3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -623,11 +623,11 @@
* Removes PiP immediately.
*/
public void removePip() {
- if (!mPipTransitionState.isInPip() || mToken == null) {
+ if (!mPipTransitionState.isInPip() || mToken == null || mLeash == null) {
ProtoLog.wtf(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: Not allowed to removePip in current state"
- + " mState=%d mToken=%s", TAG, mPipTransitionState.getTransitionState(),
- mToken);
+ + " mState=%d mToken=%s mLeash=%s", TAG,
+ mPipTransitionState.getTransitionState(), mToken, mLeash);
return;
}
@@ -1532,6 +1532,9 @@
if (snapshotSurface != null) {
mSyncTransactionQueue.queue(wct);
mSyncTransactionQueue.runInSync(t -> {
+ // reset the pinch gesture
+ maybePerformFinishResizeCallback();
+
// Scale the snapshot from its pre-resize bounds to the post-resize bounds.
mSurfaceTransactionHelper.scale(t, snapshotSurface, preResizeBounds,
snapshotDest);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipAction.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipAction.java
index 222307f..5f6b3fe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipAction.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipAction.java
@@ -31,6 +31,12 @@
abstract class TvPipAction {
+ /**
+ * Extras key for adding a boolean to the {@link Notification.Action} to differentiate custom
+ * from system actions, most importantly to identify custom close actions.
+ **/
+ public static final String EXTRA_IS_PIP_CUSTOM_ACTION = "EXTRA_IS_PIP_CUSTOM_ACTION";
+
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"ACTION_"}, value = {
ACTION_FULLSCREEN,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipCustomAction.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipCustomAction.java
index bca27a5..977aad4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipCustomAction.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipCustomAction.java
@@ -86,7 +86,7 @@
Bundle extras = new Bundle();
extras.putCharSequence(Notification.EXTRA_PICTURE_CONTENT_DESCRIPTION,
mRemoteAction.getContentDescription());
- extras.putBoolean(Notification.EXTRA_CONTAINS_CUSTOM_VIEW, true);
+ extras.putBoolean(TvPipAction.EXTRA_IS_PIP_CUSTOM_ACTION, true);
builder.addExtras(extras);
builder.setSemanticAction(isCloseAction()
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuEduTextDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuEduTextDrawer.java
index 6eef225..f86f987 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuEduTextDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuEduTextDrawer.java
@@ -23,6 +23,7 @@
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE;
+import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.drawable.Drawable;
@@ -115,6 +116,10 @@
scheduleLifecycleEvents();
}
+ int getEduTextDrawerHeight() {
+ return getVisibility() == GONE ? 0 : getHeight();
+ }
+
private void scheduleLifecycleEvents() {
final int startScrollDelay = mContext.getResources().getInteger(
R.integer.pip_edu_text_start_scroll_delay);
@@ -226,20 +231,41 @@
.start();
// Start animation to close the drawer by animating its height to 0
- final ValueAnimator heightAnimation = ValueAnimator.ofInt(getHeight(), 0);
- heightAnimation.setDuration(eduTextSlideExitAnimationDuration);
- heightAnimation.setInterpolator(TvPipInterpolators.BROWSE);
- heightAnimation.addUpdateListener(animator -> {
+ final ValueAnimator heightAnimator = ValueAnimator.ofInt(getHeight(), 0);
+ heightAnimator.setDuration(eduTextSlideExitAnimationDuration);
+ heightAnimator.setInterpolator(TvPipInterpolators.BROWSE);
+ heightAnimator.addUpdateListener(animator -> {
final ViewGroup.LayoutParams params = getLayoutParams();
params.height = (int) animator.getAnimatedValue();
setLayoutParams(params);
- if (params.height == 0) {
- setVisibility(GONE);
+ });
+ heightAnimator.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(@NonNull Animator animator) {
+ }
+
+ @Override
+ public void onAnimationEnd(@NonNull Animator animator) {
+ onCloseEduTextAnimationEnd();
+ }
+
+ @Override
+ public void onAnimationCancel(@NonNull Animator animator) {
+ onCloseEduTextAnimationEnd();
+ }
+
+ @Override
+ public void onAnimationRepeat(@NonNull Animator animator) {
}
});
- heightAnimation.start();
+ heightAnimator.start();
- mListener.onCloseEduText();
+ mListener.onCloseEduTextAnimationStart();
+ }
+
+ public void onCloseEduTextAnimationEnd() {
+ setVisibility(GONE);
+ mListener.onCloseEduTextAnimationEnd();
}
/**
@@ -270,11 +296,8 @@
* A listener for edu text drawer event states.
*/
interface Listener {
- /**
- * The edu text closing impacts the size of the Picture-in-Picture window and influences
- * how it is positioned on the screen.
- */
- void onCloseEduText();
+ void onCloseEduTextAnimationStart();
+ void onCloseEduTextAnimationEnd();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
index 6eb719b..d076418 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
@@ -57,7 +57,8 @@
* A View that represents Pip Menu on TV. It's responsible for displaying the Pip menu actions from
* the TvPipActionsProvider as well as the buttons for manually moving the PiP.
*/
-public class TvPipMenuView extends FrameLayout implements TvPipActionsProvider.Listener {
+public class TvPipMenuView extends FrameLayout implements TvPipActionsProvider.Listener,
+ TvPipMenuEduTextDrawer.Listener {
private static final String TAG = "TvPipMenuView";
private final TvPipMenuView.Listener mListener;
@@ -76,6 +77,7 @@
private final View mDimLayer;
private final TvPipMenuEduTextDrawer mEduTextDrawer;
+ private final ViewGroup mEduTextContainer;
private final int mPipMenuOuterSpace;
private final int mPipMenuBorderWidth;
@@ -139,9 +141,9 @@
mPipMenuBorderWidth = context.getResources()
.getDimensionPixelSize(R.dimen.pip_menu_border_width);
- mEduTextDrawer = new TvPipMenuEduTextDrawer(mContext, mainHandler, mListener);
- ((FrameLayout) findViewById(R.id.tv_pip_menu_edu_text_drawer_placeholder))
- .addView(mEduTextDrawer);
+ mEduTextDrawer = new TvPipMenuEduTextDrawer(mContext, mainHandler, this);
+ mEduTextContainer = (ViewGroup) findViewById(R.id.tv_pip_menu_edu_text_container);
+ mEduTextContainer.addView(mEduTextDrawer);
}
void onPipTransitionToTargetBoundsStarted(Rect targetBounds) {
@@ -235,11 +237,13 @@
* pip menu when it gains focus.
*/
private void updatePipFrameBounds() {
- final ViewGroup.LayoutParams pipFrameParams = mPipFrameView.getLayoutParams();
- if (pipFrameParams != null) {
- pipFrameParams.width = mCurrentPipBounds.width() + 2 * mPipMenuBorderWidth;
- pipFrameParams.height = mCurrentPipBounds.height() + 2 * mPipMenuBorderWidth;
- mPipFrameView.setLayoutParams(pipFrameParams);
+ if (mPipFrameView.getVisibility() == VISIBLE) {
+ final ViewGroup.LayoutParams pipFrameParams = mPipFrameView.getLayoutParams();
+ if (pipFrameParams != null) {
+ pipFrameParams.width = mCurrentPipBounds.width() + 2 * mPipMenuBorderWidth;
+ pipFrameParams.height = mCurrentPipBounds.height() + 2 * mPipMenuBorderWidth;
+ mPipFrameView.setLayoutParams(pipFrameParams);
+ }
}
final ViewGroup.LayoutParams pipViewParams = mPipView.getLayoutParams();
@@ -262,7 +266,7 @@
Rect getPipMenuContainerBounds(Rect pipBounds) {
final Rect menuUiBounds = new Rect(pipBounds);
menuUiBounds.inset(-mPipMenuOuterSpace, -mPipMenuOuterSpace);
- menuUiBounds.bottom += mEduTextDrawer.getHeight();
+ menuUiBounds.bottom += mEduTextDrawer.getEduTextDrawerHeight();
return menuUiBounds;
}
@@ -406,6 +410,17 @@
}
@Override
+ public void onCloseEduTextAnimationStart() {
+ mListener.onCloseEduText();
+ }
+
+ @Override
+ public void onCloseEduTextAnimationEnd() {
+ mPipFrameView.setVisibility(GONE);
+ mEduTextContainer.setVisibility(GONE);
+ }
+
+ @Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == ACTION_UP) {
@@ -551,7 +566,7 @@
}
}
- interface Listener extends TvPipMenuEduTextDrawer.Listener {
+ interface Listener {
void onBackPress();
@@ -573,5 +588,11 @@
* has lost focus.
*/
void onPipWindowFocusChanged(boolean focused);
+
+ /**
+ * The edu text closing impacts the size of the Picture-in-Picture window and influences
+ * how it is positioned on the screen.
+ */
+ void onCloseEduText();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
index c9b3a1a..c4a0e9c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
@@ -32,6 +32,8 @@
Consts.TAG_WM_SHELL),
WM_SHELL_TRANSITIONS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
Consts.TAG_WM_SHELL),
+ WM_SHELL_RECENTS_TRANSITION(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
+ Consts.TAG_WM_SHELL),
WM_SHELL_DRAG_AND_DROP(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
Consts.TAG_WM_SHELL),
WM_SHELL_STARTING_WINDOW(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index a8b209f..b554872 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -47,7 +47,9 @@
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.util.TransitionUtil;
@@ -96,6 +98,8 @@
void startRecentsTransition(PendingIntent intent, Intent fillIn, Bundle options,
IApplicationThread appThread, IRecentsAnimationRunner listener) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsTransitionHandler.startRecentsTransition");
// only care about latest one.
mAnimApp = appThread;
WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -116,7 +120,7 @@
mixer.setRecentsTransition(transition);
}
if (transition == null) {
- controller.cancel();
+ controller.cancel("startRecentsTransition");
return;
}
controller.setTransition(transition);
@@ -127,6 +131,7 @@
public WindowContainerTransaction handleRequest(IBinder transition,
TransitionRequestInfo request) {
// do not directly handle requests. Only entry point should be via startRecentsTransition
+ Slog.e(TAG, "RecentsTransitionHandler.handleRequest: Unexpected transition request");
return null;
}
@@ -143,11 +148,17 @@
SurfaceControl.Transaction finishTransaction,
Transitions.TransitionFinishCallback finishCallback) {
final int controllerIdx = findController(transition);
- if (controllerIdx < 0) return false;
+ if (controllerIdx < 0) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsTransitionHandler.startAnimation: no controller found");
+ return false;
+ }
final RecentsController controller = mControllers.get(controllerIdx);
Transitions.setRunningRemoteTransitionDelegate(mAnimApp);
mAnimApp = null;
if (!controller.start(info, startTransaction, finishTransaction, finishCallback)) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsTransitionHandler.startAnimation: failed to start animation");
return false;
}
return true;
@@ -168,7 +179,7 @@
SurfaceControl.Transaction finishTransaction) {
final int idx = findController(transition);
if (idx < 0) return;
- mControllers.get(idx).cancel();
+ mControllers.get(idx).cancel("onTransitionConsumed");
}
/** There is only one of these and it gets reset on finish. */
@@ -213,27 +224,38 @@
RecentsController(IRecentsAnimationRunner listener) {
mListener = listener;
- mDeathHandler = () -> finish(mWillFinishToHome, false /* leaveHint */);
+ mDeathHandler = () -> {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.DeathRecipient: binder died");
+ finish(mWillFinishToHome, false /* leaveHint */);
+ };
try {
mListener.asBinder().linkToDeath(mDeathHandler, 0 /* flags */);
} catch (RemoteException e) {
+ Slog.e(TAG, "RecentsController: failed to link to death", e);
mListener = null;
}
}
void setTransition(IBinder transition) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.setTransition: id=%s", transition);
mTransition = transition;
}
- void cancel() {
+ void cancel(String reason) {
// restoring (to-home = false) involves submitting more WM changes, so by default, use
// toHome = true when canceling.
- cancel(true /* toHome */);
+ cancel(true /* toHome */, reason);
}
- void cancel(boolean toHome) {
+ void cancel(boolean toHome, String reason) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.cancel: toHome=%b reason=%s", toHome, reason);
if (mListener != null) {
try {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.cancel: calling onAnimationCanceled");
mListener.onAnimationCanceled(null, null);
} catch (RemoteException e) {
Slog.e(TAG, "Error canceling recents animation", e);
@@ -267,6 +289,8 @@
}
}
try {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.cancel: calling onAnimationCanceled with snapshots");
mListener.onAnimationCanceled(taskIds, snapshots);
} catch (RemoteException e) {
Slog.e(TAG, "Error canceling recents animation", e);
@@ -276,6 +300,7 @@
}
void cleanUp() {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "RecentsController.cleanup");
if (mListener != null && mDeathHandler != null) {
mListener.asBinder().unlinkToDeath(mDeathHandler, 0 /* flags */);
mDeathHandler = null;
@@ -299,6 +324,7 @@
boolean start(TransitionInfo info, SurfaceControl.Transaction t,
SurfaceControl.Transaction finishT, Transitions.TransitionFinishCallback finishCB) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "RecentsController.start");
if (mListener == null || mTransition == null) {
cleanUp();
return false;
@@ -358,6 +384,8 @@
info.getChanges().size() - i, info, t, mLeashMap);
apps.add(target);
if (TransitionUtil.isClosingType(change.getMode())) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ " adding pausing taskId=%d", taskInfo.taskId);
// raise closing (pausing) task to "above" layer so it isn't covered
t.setLayer(target.leash, info.getChanges().size() * 3 - i);
mPausingTasks.add(new TaskState(change, target.leash));
@@ -372,19 +400,23 @@
} else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
// do nothing
} else if (TransitionUtil.isOpeningType(change.getMode())) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ " adding opening taskId=%d", taskInfo.taskId);
mOpeningTasks.add(new TaskState(change, target.leash));
}
}
}
t.apply();
try {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.start: calling onAnimationStart");
mListener.onAnimationStart(this,
apps.toArray(new RemoteAnimationTarget[apps.size()]),
wallpapers.toArray(new RemoteAnimationTarget[wallpapers.size()]),
new Rect(0, 0, 0, 0), new Rect());
} catch (RemoteException e) {
Slog.e(TAG, "Error starting recents animation", e);
- cancel();
+ cancel("onAnimationStart() failed");
}
return true;
}
@@ -393,14 +425,19 @@
void merge(TransitionInfo info, SurfaceControl.Transaction t,
Transitions.TransitionFinishCallback finishCallback) {
if (mFinishCB == null) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.merge: skip, no finish callback");
// This was no-op'd (likely a repeated start) and we've already sent finish.
return;
}
if (info.getType() == TRANSIT_SLEEP) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.merge: transit_sleep");
// A sleep event means we need to stop animations immediately, so cancel here.
- cancel();
+ cancel("transit_sleep");
return;
}
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "RecentsController.merge");
ArrayList<TransitionInfo.Change> openingTasks = null;
ArrayList<TransitionInfo.Change> closingTasks = null;
mOpeningSeparateHome = false;
@@ -417,7 +454,7 @@
&& taskInfo.configuration.windowConfiguration.isAlwaysOnTop()) {
// Tasks that are always on top (e.g. bubbles), will handle their own transition
// as they are on top of everything else. So cancel the merge here.
- cancel();
+ cancel("task #" + taskInfo.taskId + " is always_on_top");
return;
}
hasTaskChange = hasTaskChange || taskInfo != null;
@@ -448,7 +485,7 @@
// Finish recents animation if the display is changed, so the default
// transition handler can play the animation such as rotation effect.
if (change.hasFlags(TransitionInfo.FLAG_IS_DISPLAY)) {
- cancel(mWillFinishToHome);
+ cancel(mWillFinishToHome, "display change");
return;
}
// Don't consider order-only changes as changing apps.
@@ -492,7 +529,10 @@
+ " something unexpected: " + change.getTaskInfo().taskId);
continue;
}
- mPausingTasks.add(mOpeningTasks.remove(openingIdx));
+ final TaskState openingTask = mOpeningTasks.remove(openingIdx);
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ " pausing opening taskId=%d", openingTask.mTaskInfo.taskId);
+ mPausingTasks.add(openingTask);
didMergeThings = true;
}
}
@@ -509,7 +549,10 @@
// Something is showing/opening a previously-pausing app.
appearedTargets[i] = TransitionUtil.newTarget(
change, layer, mPausingTasks.get(pausingIdx).mLeash);
- mOpeningTasks.add(mPausingTasks.remove(pausingIdx));
+ final TaskState pausingTask = mPausingTasks.remove(pausingIdx);
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ " opening pausing taskId=%d", pausingTask.mTaskInfo.taskId);
+ mOpeningTasks.add(pausingTask);
// Setup hides opening tasks initially, so make it visible again (since we
// are already showing it).
t.show(change.getLeash());
@@ -522,6 +565,8 @@
final int rootIdx = TransitionUtil.rootIndexFor(change, mInfo);
t.reparent(appearedTargets[i].leash, mInfo.getRoot(rootIdx).getLeash());
t.setLayer(appearedTargets[i].leash, layer);
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ " opening new taskId=%d", appearedTargets[i].taskId);
mOpeningTasks.add(new TaskState(change, appearedTargets[i].leash));
}
}
@@ -539,7 +584,7 @@
+ foundRecentsClosing);
if (foundRecentsClosing) {
mWillFinishToHome = false;
- cancel(false /* toHome */);
+ cancel(false /* toHome */, "didn't merge");
}
return;
}
@@ -549,6 +594,8 @@
info.releaseAnimSurfaces();
if (appearedTargets == null) return;
try {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.merge: calling onTasksAppeared");
mListener.onTasksAppeared(appearedTargets);
} catch (RemoteException e) {
Slog.e(TAG, "Error sending appeared tasks to recents animation", e);
@@ -572,6 +619,8 @@
@Override
public TaskSnapshot screenshotTask(int taskId) {
try {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.screenshotTask: taskId=%d", taskId);
return ActivityTaskManager.getService().takeTaskSnapshot(taskId);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to screenshot task", e);
@@ -582,12 +631,19 @@
@Override
public void setInputConsumerEnabled(boolean enabled) {
mExecutor.execute(() -> {
- if (mFinishCB == null || !enabled) return;
+ if (mFinishCB == null || !enabled) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.setInputConsumerEnabled: skip, cb?=%b enabled?=%b",
+ mFinishCB != null, enabled);
+ return;
+ }
// transient launches don't receive focus automatically. Since we are taking over
// the gesture now, take focus explicitly.
// This also moves recents back to top if the user gestured before a switch
// animation finished.
try {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.setInputConsumerEnabled: set focus to recents");
ActivityTaskManager.getService().setFocusedTask(mRecentsTaskId);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to set focused task", e);
@@ -602,6 +658,8 @@
@Override
public void setFinishTaskTransaction(int taskId,
PictureInPictureSurfaceTransaction finishTransaction, SurfaceControl overlay) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.setFinishTaskTransaction: taskId=%d", taskId);
mExecutor.execute(() -> {
if (mFinishCB == null) return;
mPipTransaction = finishTransaction;
@@ -619,6 +677,9 @@
Slog.e(TAG, "Duplicate call to finish");
return;
}
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.finishInner: toHome=%b userLeaveHint=%b willFinishToHome=%b",
+ toHome, sendUserLeaveHint, mWillFinishToHome);
final Transitions.TransitionFinishCallback finishCB = mFinishCB;
mFinishCB = null;
@@ -630,6 +691,7 @@
else wct.restoreTransientOrder(mRecentsTask);
}
if (!toHome && !mWillFinishToHome && mPausingTasks != null && mState == STATE_NORMAL) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, " returning to app");
// The gesture is returning to the pausing-task(s) rather than continuing with
// recents, so end the transition by moving the app back to the top (and also
// re-showing it's task).
@@ -642,6 +704,7 @@
wct.restoreTransientOrder(mRecentsTask);
}
} else if (toHome && mOpeningSeparateHome && mPausingTasks != null) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, " 3p launching home");
// Special situation where 3p launcher was changed during recents (this happens
// during tapltests...). Here we get both "return to home" AND "home opening".
// This is basically going home, but we have to restore the recents and home order.
@@ -660,6 +723,7 @@
wct.restoreTransientOrder(mRecentsTask);
}
} else {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, " normal finish");
// The general case: committing to recents, going home, or switching tasks.
for (int i = 0; i < mOpeningTasks.size(); ++i) {
t.show(mOpeningTasks.get(i).mTaskSurface);
@@ -716,6 +780,8 @@
*/
@Override
public void detachNavigationBarFromApp(boolean moveHomeToTop) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.detachNavigationBarFromApp");
mExecutor.execute(() -> {
if (mTransition == null) return;
try {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
index 1786d13..91c0a5b 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimationConfig.kt
@@ -19,17 +19,11 @@
val maxHeight: Float = 0f,
val pixelDensity: Float = 1f,
var color: Int = Color.WHITE,
- val opacity: Int = RIPPLE_DEFAULT_ALPHA,
- val sparkleStrength: Float = RIPPLE_SPARKLE_STRENGTH,
+ val opacity: Int = RippleShader.RIPPLE_DEFAULT_ALPHA,
+ val sparkleStrength: Float = RippleShader.RIPPLE_SPARKLE_STRENGTH,
// Null means it uses default fade parameter values.
val baseRingFadeParams: RippleShader.FadeParams? = null,
val sparkleRingFadeParams: RippleShader.FadeParams? = null,
val centerFillFadeParams: RippleShader.FadeParams? = null,
val shouldDistort: Boolean = true
-) {
- companion object {
- const val RIPPLE_SPARKLE_STRENGTH: Float = 0.3f
- const val RIPPLE_DEFAULT_COLOR: Int = 0xffffffff.toInt()
- const val RIPPLE_DEFAULT_ALPHA: Int = 115 // full opacity is 255.
- }
-}
+)
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
index b5b6037..7e56f4b 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
@@ -60,6 +60,10 @@
const val DEFAULT_CENTER_FILL_FADE_OUT_START = 0f
const val DEFAULT_CENTER_FILL_FADE_OUT_END = 0.6f
+ const val RIPPLE_SPARKLE_STRENGTH: Float = 0.3f
+ const val RIPPLE_DEFAULT_COLOR: Int = 0xffffffff.toInt()
+ const val RIPPLE_DEFAULT_ALPHA: Int = 115 // full opacity is 255.
+
private const val SHADER_UNIFORMS =
"""
uniform vec2 in_center;
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
index ef5ad43..b899127 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
@@ -72,9 +72,9 @@
this.rippleShape = rippleShape
rippleShader = RippleShader(rippleShape)
- rippleShader.color = RippleAnimationConfig.RIPPLE_DEFAULT_COLOR
+ rippleShader.color = RippleShader.RIPPLE_DEFAULT_COLOR
rippleShader.rawProgress = 0f
- rippleShader.sparkleStrength = RippleAnimationConfig.RIPPLE_SPARKLE_STRENGTH
+ rippleShader.sparkleStrength = RippleShader.RIPPLE_SPARKLE_STRENGTH
rippleShader.pixelDensity = resources.displayMetrics.density
ripplePaint.shader = rippleShader
@@ -209,7 +209,7 @@
*
* The alpha value of the color will be applied to the ripple. The alpha range is [0-255].
*/
- fun setColor(color: Int, alpha: Int = RippleAnimationConfig.RIPPLE_DEFAULT_ALPHA) {
+ fun setColor(color: Int, alpha: Int = RippleShader.RIPPLE_DEFAULT_ALPHA) {
rippleShader.color = ColorUtils.setAlphaComponent(color, alpha)
}
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
index 204bac8..450c616 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
@@ -316,9 +316,9 @@
),
CLOCK_VIBRANT(
CoreSpec(
- a1 = TonalSpec(HueSource(), ChromaBound(ChromaSource(), 30.0, Chroma.MAX_VALUE)),
- a2 = TonalSpec(HueAdd(20.0), ChromaBound(ChromaSource(), 30.0, Chroma.MAX_VALUE)),
- a3 = TonalSpec(HueAdd(60.0), ChromaBound(ChromaSource(), 30.0, Chroma.MAX_VALUE)),
+ a1 = TonalSpec(HueSource(), ChromaBound(ChromaSource(), 70.0, Chroma.MAX_VALUE)),
+ a2 = TonalSpec(HueAdd(20.0), ChromaBound(ChromaSource(), 70.0, Chroma.MAX_VALUE)),
+ a3 = TonalSpec(HueAdd(60.0), ChromaBound(ChromaSource(), 70.0, Chroma.MAX_VALUE)),
// Not Used
n1 = TonalSpec(HueSource(), ChromaConstant(0.0)),
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
index 5b0e290..461d390 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFaceListenModel.kt
@@ -41,10 +41,10 @@
var listeningForFaceAssistant: Boolean = false,
var occludingAppRequestingFaceAuth: Boolean = false,
var postureAllowsListening: Boolean = false,
- var primaryUser: Boolean = false,
var secureCameraLaunched: Boolean = false,
var supportsDetect: Boolean = false,
var switchingUser: Boolean = false,
+ var systemUser: Boolean = false,
var udfpsFingerDown: Boolean = false,
var userNotTrustedOrDetectionIsNeeded: Boolean = false,
) : KeyguardListenModel() {
@@ -69,11 +69,11 @@
keyguardGoingAway.toString(),
listeningForFaceAssistant.toString(),
occludingAppRequestingFaceAuth.toString(),
- primaryUser.toString(),
postureAllowsListening.toString(),
secureCameraLaunched.toString(),
supportsDetect.toString(),
switchingUser.toString(),
+ systemUser.toString(),
alternateBouncerShowing.toString(),
udfpsFingerDown.toString(),
userNotTrustedOrDetectionIsNeeded.toString(),
@@ -109,12 +109,11 @@
keyguardGoingAway = model.keyguardGoingAway
listeningForFaceAssistant = model.listeningForFaceAssistant
occludingAppRequestingFaceAuth = model.occludingAppRequestingFaceAuth
- primaryUser = model.primaryUser
postureAllowsListening = model.postureAllowsListening
secureCameraLaunched = model.secureCameraLaunched
supportsDetect = model.supportsDetect
switchingUser = model.switchingUser
- switchingUser = model.switchingUser
+ systemUser = model.systemUser
udfpsFingerDown = model.udfpsFingerDown
userNotTrustedOrDetectionIsNeeded = model.userNotTrustedOrDetectionIsNeeded
}
@@ -153,11 +152,11 @@
"keyguardGoingAway",
"listeningForFaceAssistant",
"occludingAppRequestingFaceAuth",
- "primaryUser",
"postureAllowsListening",
"secureCameraLaunched",
"supportsDetect",
"switchingUser",
+ "systemUser",
"udfpsBouncerShowing",
"udfpsFingerDown",
"userNotTrustedOrDetectionIsNeeded",
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt
index b8c0ccb..f2685c5 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt
@@ -41,11 +41,11 @@
var keyguardIsVisible: Boolean = false,
var keyguardOccluded: Boolean = false,
var occludingAppRequestingFp: Boolean = false,
- var primaryUser: Boolean = false,
var shouldListenSfpsState: Boolean = false,
var shouldListenForFingerprintAssistant: Boolean = false,
var strongerAuthRequired: Boolean = false,
var switchingUser: Boolean = false,
+ var systemUser: Boolean = false,
var udfps: Boolean = false,
var userDoesNotHaveTrust: Boolean = false,
) : KeyguardListenModel() {
@@ -72,11 +72,11 @@
keyguardIsVisible.toString(),
keyguardOccluded.toString(),
occludingAppRequestingFp.toString(),
- primaryUser.toString(),
shouldListenSfpsState.toString(),
shouldListenForFingerprintAssistant.toString(),
strongerAuthRequired.toString(),
switchingUser.toString(),
+ systemUser.toString(),
udfps.toString(),
userDoesNotHaveTrust.toString(),
)
@@ -112,11 +112,11 @@
keyguardIsVisible = model.keyguardIsVisible
keyguardOccluded = model.keyguardOccluded
occludingAppRequestingFp = model.occludingAppRequestingFp
- primaryUser = model.primaryUser
shouldListenSfpsState = model.shouldListenSfpsState
shouldListenForFingerprintAssistant = model.shouldListenForFingerprintAssistant
strongerAuthRequired = model.strongerAuthRequired
switchingUser = model.switchingUser
+ systemUser = model.systemUser
udfps = model.udfps
userDoesNotHaveTrust = model.userDoesNotHaveTrust
}
@@ -158,11 +158,11 @@
"keyguardIsVisible",
"keyguardOccluded",
"occludingAppRequestingFp",
- "primaryUser",
"shouldListenSidFingerprintState",
"shouldListenForFingerprintAssistant",
"strongAuthRequired",
"switchingUser",
+ "systemUser",
"underDisplayFingerprint",
"userDoesNotHaveTrust",
)
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 76e051e..693268d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -178,6 +178,7 @@
@Override
public void onUserInput() {
+ mKeyguardFaceAuthInteractor.onPrimaryBouncerUserInput();
mUpdateMonitor.cancelFaceAuth();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index ea04376..10c08bc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -297,7 +297,7 @@
private final Context mContext;
private final UserTracker mUserTracker;
private final KeyguardUpdateMonitorLogger mLogger;
- private final boolean mIsPrimaryUser;
+ private final boolean mIsSystemUser;
private final AuthController mAuthController;
private final UiEventLogger mUiEventLogger;
private final Set<Integer> mFaceAcquiredInfoIgnoreList;
@@ -2522,7 +2522,7 @@
updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE, FACE_AUTH_UPDATED_ON_KEYGUARD_INIT);
TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
- mIsPrimaryUser = mUserManager.isPrimaryUser();
+ mIsSystemUser = mUserManager.isSystemUser();
int user = mUserTracker.getUserId();
mUserIsUnlocked.put(user, mUserManager.isUserUnlocked(user));
mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled();
@@ -2968,7 +2968,7 @@
|| (mKeyguardOccluded && userDoesNotHaveTrust && mKeyguardShowing
&& (mOccludingAppRequestingFp || isUdfps || mAlternateBouncerShowing));
- // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
+ // Only listen if this KeyguardUpdateMonitor belongs to the system user. There is an
// instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
final boolean biometricEnabledForUser = mBiometricEnabledForUser.get(user);
final boolean userCanSkipBouncer = getUserCanSkipBouncer(user);
@@ -2977,7 +2977,7 @@
!mSwitchingUser
&& !fingerprintDisabledForUser
&& (!mKeyguardGoingAway || !mDeviceInteractive)
- && mIsPrimaryUser
+ && mIsSystemUser
&& biometricEnabledForUser
&& !isUserInLockdown(user);
final boolean strongerAuthRequired = !isUnlockingWithFingerprintAllowed();
@@ -3021,11 +3021,11 @@
isKeyguardVisible(),
mKeyguardOccluded,
mOccludingAppRequestingFp,
- mIsPrimaryUser,
shouldListenSideFpsState,
shouldListenForFingerprintAssistant,
strongerAuthRequired,
mSwitchingUser,
+ mIsSystemUser,
isUdfps,
userDoesNotHaveTrust));
@@ -3070,7 +3070,7 @@
final boolean shouldListenForFaceAssistant = shouldListenForFaceAssistant();
final boolean isUdfpsFingerDown = mAuthController.isUdfpsFingerDown();
final boolean isPostureAllowedForFaceAuth = doesPostureAllowFaceAuth(mPostureState);
- // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
+ // Only listen if this KeyguardUpdateMonitor belongs to the system user. There is an
// instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
final boolean shouldListen =
(mPrimaryBouncerFullyShown
@@ -3082,7 +3082,7 @@
|| mAlternateBouncerShowing)
&& !mSwitchingUser && !faceDisabledForUser && userNotTrustedOrDetectionIsNeeded
&& !mKeyguardGoingAway && biometricEnabledForUser
- && faceAuthAllowedOrDetectionIsNeeded && mIsPrimaryUser
+ && faceAuthAllowedOrDetectionIsNeeded && mIsSystemUser
&& (!mSecureCameraLaunched || mAlternateBouncerShowing)
&& faceAndFpNotAuthenticated
&& !mGoingToSleep
@@ -3108,10 +3108,10 @@
shouldListenForFaceAssistant,
mOccludingAppRequestingFace,
isPostureAllowedForFaceAuth,
- mIsPrimaryUser,
mSecureCameraLaunched,
supportsDetect,
mSwitchingUser,
+ mIsSystemUser,
isUdfpsFingerDown,
userNotTrustedOrDetectionIsNeeded));
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java
index b6ee4cb..3349fe5 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationSettingsController.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.content.res.Configuration;
import android.util.Range;
+import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
@@ -68,14 +69,18 @@
@NonNull Callback settingsControllerCallback,
SecureSettings secureSettings,
WindowMagnificationSettings windowMagnificationSettings) {
- mContext = context;
+ mContext = context.createWindowContext(
+ context.getDisplay(),
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ null);
+ mContext.setTheme(com.android.systemui.R.style.Theme_SystemUI);
mDisplayId = mContext.getDisplayId();
- mConfiguration = new Configuration(context.getResources().getConfiguration());
+ mConfiguration = new Configuration(mContext.getResources().getConfiguration());
mSettingsControllerCallback = settingsControllerCallback;
if (windowMagnificationSettings != null) {
mWindowMagnificationSettings = windowMagnificationSettings;
} else {
- mWindowMagnificationSettings = new WindowMagnificationSettings(context,
+ mWindowMagnificationSettings = new WindowMagnificationSettings(mContext,
mWindowMagnificationSettingsCallback,
sfVsyncFrameProvider, secureSettings);
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
index 71c5f24..6e8275f 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
@@ -559,7 +559,7 @@
final LayoutParams params = new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT,
- LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
+ LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSPARENT);
params.gravity = Gravity.TOP | Gravity.START;
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
index 98a3e4b..11ef749 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
@@ -34,7 +34,6 @@
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.surfaceeffects.ripple.RippleAnimationConfig;
import com.android.systemui.surfaceeffects.ripple.RippleShader;
import com.android.systemui.surfaceeffects.ripple.RippleShader.RippleShape;
import com.android.systemui.surfaceeffects.ripple.RippleView;
@@ -177,7 +176,7 @@
mRippleView.setBlur(6.5f, 2.5f);
} else {
mRippleView.setDuration(CIRCLE_RIPPLE_ANIMATION_DURATION);
- mRippleView.setColor(color, RippleAnimationConfig.RIPPLE_DEFAULT_ALPHA);
+ mRippleView.setColor(color, RippleShader.RIPPLE_DEFAULT_ALPHA);
}
OnAttachStateChangeListener listener = new OnAttachStateChangeListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
index 05ab01b..5f2178df 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
@@ -225,10 +225,17 @@
}
private fun observeFaceAuthResettingConditions() {
- // Clear auth status when keyguard is going away or when the user is switching.
- merge(keyguardRepository.isKeyguardGoingAway, userRepository.userSwitchingInProgress)
- .onEach { goingAwayOrUserSwitchingInProgress ->
- if (goingAwayOrUserSwitchingInProgress) {
+ // Clear auth status when keyguard is going away or when the user is switching or device
+ // starts going to sleep.
+ merge(
+ keyguardRepository.wakefulness.map {
+ WakefulnessModel.isSleepingOrStartingToSleep(it)
+ },
+ keyguardRepository.isKeyguardGoingAway,
+ userRepository.userSwitchingInProgress
+ )
+ .onEach { anyOfThemIsTrue ->
+ if (anyOfThemIsTrue) {
_isAuthenticated.value = false
retryCount = 0
halErrorRetryJob?.cancel()
@@ -248,8 +255,8 @@
"nonStrongBiometricIsNotAllowed",
faceDetectLog
),
- // We don't want to run face detect if it's not possible to authenticate with FP
- // from the bouncer. UDFPS is the only fp sensor type that won't support this.
+ // We don't want to run face detect if fingerprint can be used to unlock the device
+ // but it's not possible to authenticate with FP from the bouncer (UDFPS)
logAndObserve(
and(isUdfps(), deviceEntryFingerprintAuthRepository.isRunning).isFalse(),
"udfpsAuthIsNotPossibleAnymore",
@@ -306,7 +313,7 @@
logAndObserve(
combine(
keyguardInteractor.isSecureCameraActive,
- alternateBouncerInteractor.isVisible,
+ alternateBouncerInteractor.isVisible
) { a, b ->
!a || b
},
@@ -334,12 +341,12 @@
logAndObserve(isLockedOut.isFalse(), "isNotInLockOutState", faceAuthLog),
logAndObserve(
deviceEntryFingerprintAuthRepository.isLockedOut.isFalse(),
- "fpLockedOut",
+ "fpIsNotLockedOut",
faceAuthLog
),
logAndObserve(
trustRepository.isCurrentUserTrusted.isFalse(),
- "currentUserTrusted",
+ "currentUserIsNotTrusted",
faceAuthLog
),
logAndObserve(
@@ -347,11 +354,6 @@
"nonStrongBiometricIsAllowed",
faceAuthLog
),
- logAndObserve(
- userRepository.selectedUserInfo.map { it.isPrimary },
- "userIsPrimaryUser",
- faceAuthLog
- ),
)
.reduce(::and)
.distinctUntilChanged()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt
index 06ae11fe8..74ef7a5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt
@@ -59,6 +59,7 @@
fun onQsExpansionStared()
fun onNotificationPanelClicked()
fun onSwipeUpOnBouncer()
+ fun onPrimaryBouncerUserInput()
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt
index cad40aa..5005b6c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt
@@ -59,4 +59,5 @@
override fun onNotificationPanelClicked() {}
override fun onSwipeUpOnBouncer() {}
+ override fun onPrimaryBouncerUserInput() {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
index 20ebb71..6b515da 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
@@ -151,6 +151,10 @@
return featureFlags.isEnabled(Flags.FACE_AUTH_REFACTOR)
}
+ override fun onPrimaryBouncerUserInput() {
+ repository.cancel()
+ }
+
/** Provide the status of face authentication */
override val authenticationStatus = repository.authenticationStatus
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
index 5770f3e..ddce516 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModel.kt
@@ -47,6 +47,7 @@
duration = TO_LOCKSCREEN_DURATION,
onStep = { value -> -translatePx + value * translatePx },
interpolator = EMPHASIZED_DECELERATE,
+ onCancel = { 0f },
)
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index ed40eed..2962c14 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -291,7 +291,7 @@
when(mSessionTracker.getSessionId(SESSION_KEYGUARD)).thenReturn(mKeyguardInstanceId);
when(mUserManager.isUserUnlocked(anyInt())).thenReturn(true);
- when(mUserManager.isPrimaryUser()).thenReturn(true);
+ currentUserIsSystem();
when(mStrongAuthTracker.getStub()).thenReturn(mock(IStrongAuthTracker.Stub.class));
when(mStrongAuthTracker
.isUnlockingWithBiometricAllowed(anyBoolean() /* isClass3Biometric */))
@@ -960,7 +960,7 @@
public void requestFaceAuth_whenFaceAuthWasStarted_returnsTrue() throws RemoteException {
// This satisfies all the preconditions to run face auth.
keyguardNotGoingAway();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -1467,7 +1467,7 @@
// Preconditions for sfps auth to run
keyguardNotGoingAway();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -1503,7 +1503,7 @@
// GIVEN Preconditions for sfps auth to run
keyguardNotGoingAway();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -1532,7 +1532,7 @@
// GIVEN Preconditions for sfps auth to run
keyguardNotGoingAway();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -1684,7 +1684,7 @@
// Face auth should run when the following is true.
keyguardNotGoingAway();
occludingAppRequestsFaceAuth();
- currentUserIsPrimary();
+ currentUserIsSystem();
primaryAuthNotRequiredByStrongAuthTracker();
biometricsEnabledForCurrentUser();
currentUserDoesNotHaveTrust();
@@ -1705,7 +1705,7 @@
// Face auth should run when the following is true.
bouncerFullyVisibleAndNotGoingToSleep();
keyguardNotGoingAway();
- currentUserIsPrimary();
+ currentUserIsSystem();
primaryAuthNotRequiredByStrongAuthTracker();
biometricsEnabledForCurrentUser();
currentUserDoesNotHaveTrust();
@@ -1728,7 +1728,7 @@
// Face auth should run when the following is true.
bouncerFullyVisibleAndNotGoingToSleep();
keyguardNotGoingAway();
- currentUserIsPrimary();
+ currentUserIsSystem();
primaryAuthNotRequiredByStrongAuthTracker();
biometricsEnabledForCurrentUser();
currentUserDoesNotHaveTrust();
@@ -1749,7 +1749,7 @@
public void testShouldListenForFace_whenUserIsNotPrimary_returnsFalse() throws RemoteException {
cleanupKeyguardUpdateMonitor();
// This disables face auth
- when(mUserManager.isPrimaryUser()).thenReturn(false);
+ when(mUserManager.isSystemUser()).thenReturn(false);
mKeyguardUpdateMonitor =
new TestableKeyguardUpdateMonitor(mContext);
@@ -1773,7 +1773,7 @@
// Face auth should run when the following is true.
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
- currentUserIsPrimary();
+ currentUserIsSystem();
biometricsEnabledForCurrentUser();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
@@ -1791,7 +1791,7 @@
throws RemoteException {
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -1813,7 +1813,7 @@
// Face auth should run when the following is true.
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -1833,7 +1833,7 @@
throws RemoteException {
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -1854,7 +1854,7 @@
// Face auth should run when the following is true.
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -1876,7 +1876,7 @@
throws RemoteException {
// Face auth should run when the following is true.
keyguardNotGoingAway();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -1896,7 +1896,7 @@
throws RemoteException {
// Face auth should run when the following is true.
keyguardNotGoingAway();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -1915,7 +1915,7 @@
public void testShouldListenForFace_whenKeyguardIsAwake_returnsTrue() throws RemoteException {
// Preconditions for face auth to run
keyguardNotGoingAway();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -1940,7 +1940,7 @@
public void testShouldListenForFace_whenUdfpsFingerDown_returnsTrue() throws RemoteException {
// Preconditions for face auth to run
keyguardNotGoingAway();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -1959,7 +1959,7 @@
throws RemoteException {
// Preconditions for face auth to run
keyguardNotGoingAway();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -1977,7 +1977,7 @@
throws RemoteException {
// Preconditions for face auth to run
keyguardNotGoingAway();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -2002,7 +2002,7 @@
throws RemoteException {
// Preconditions for face auth to run
keyguardNotGoingAway();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -2324,7 +2324,7 @@
throws RemoteException {
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -2455,7 +2455,7 @@
mKeyguardUpdateMonitor.mConfigFaceAuthSupportedPosture = DEVICE_POSTURE_CLOSED;
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -2479,7 +2479,7 @@
mKeyguardUpdateMonitor.mConfigFaceAuthSupportedPosture = DEVICE_POSTURE_UNKNOWN;
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
- currentUserIsPrimary();
+ currentUserIsSystem();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
@@ -2877,8 +2877,8 @@
new FaceManager.AuthenticationResult(null, null, mCurrentUserId, false));
}
- private void currentUserIsPrimary() {
- when(mUserManager.isPrimaryUser()).thenReturn(true);
+ private void currentUserIsSystem() {
+ when(mUserManager.isSystemUser()).thenReturn(true);
}
private void biometricsNotDisabledThroughDevicePolicyManager() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index a76d03b..fa40fc4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -72,7 +72,6 @@
import java.io.PrintWriter
import java.io.StringWriter
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.launch
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.TestScope
@@ -542,14 +541,6 @@
}
@Test
- fun authenticateDoesNotRunWhenCurrentUserIsNotPrimary() =
- testScope.runTest {
- testGatingCheckForFaceAuth {
- launch { fakeUserRepository.setSelectedUserInfo(secondaryUser) }
- }
- }
-
- @Test
fun authenticateDoesNotRunWhenSecureCameraIsActive() =
testScope.runTest {
testGatingCheckForFaceAuth {
@@ -653,6 +644,58 @@
}
@Test
+ fun isAuthenticatedIsResetToFalseWhenDeviceStartsGoingToSleep() =
+ testScope.runTest {
+ initCollectors()
+ allPreconditionsToRunFaceAuthAreTrue()
+
+ triggerFaceAuth(false)
+
+ authenticationCallback.value.onAuthenticationSucceeded(
+ mock(FaceManager.AuthenticationResult::class.java)
+ )
+
+ assertThat(authenticated()).isTrue()
+
+ keyguardRepository.setWakefulnessModel(
+ WakefulnessModel(
+ WakefulnessState.STARTING_TO_SLEEP,
+ isWakingUpOrAwake = false,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.POWER_BUTTON
+ )
+ )
+
+ assertThat(authenticated()).isFalse()
+ }
+
+ @Test
+ fun isAuthenticatedIsResetToFalseWhenDeviceGoesToSleep() =
+ testScope.runTest {
+ initCollectors()
+ allPreconditionsToRunFaceAuthAreTrue()
+
+ triggerFaceAuth(false)
+
+ authenticationCallback.value.onAuthenticationSucceeded(
+ mock(FaceManager.AuthenticationResult::class.java)
+ )
+
+ assertThat(authenticated()).isTrue()
+
+ keyguardRepository.setWakefulnessModel(
+ WakefulnessModel(
+ WakefulnessState.ASLEEP,
+ isWakingUpOrAwake = false,
+ lastWakeReason = WakeSleepReason.POWER_BUTTON,
+ lastSleepReason = WakeSleepReason.POWER_BUTTON
+ )
+ )
+
+ assertThat(authenticated()).isFalse()
+ }
+
+ @Test
fun isAuthenticatedIsResetToFalseWhenUserIsSwitching() =
testScope.runTest {
initCollectors()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
index 3d1d2f4..5da1a84 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
@@ -279,6 +279,23 @@
}
@Test
+ fun faceAuthIsCancelledWhenUserInputOnPrimaryBouncer() =
+ testScope.runTest {
+ underTest.start()
+
+ underTest.onSwipeUpOnBouncer()
+
+ runCurrent()
+ assertThat(faceAuthRepository.isAuthRunning.value).isTrue()
+
+ underTest.onPrimaryBouncerUserInput()
+
+ runCurrent()
+
+ assertThat(faceAuthRepository.isAuthRunning.value).isFalse()
+ }
+
+ @Test
fun faceAuthIsRequestedWhenSwipeUpOnBouncer() =
testScope.runTest {
underTest.start()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
index 0c4e845..efa5f0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt
@@ -92,6 +92,21 @@
job.cancel()
}
+ @Test
+ fun lockscreenTranslationYResettedAfterJobCancelled() =
+ runTest(UnconfinedTestDispatcher()) {
+ val values = mutableListOf<Float>()
+
+ val pixels = 100
+ val job =
+ underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
+ repository.sendTransitionStep(step(0.5f, TransitionState.CANCELED))
+
+ assertThat(values.last()).isEqualTo(0f)
+
+ job.cancel()
+ }
+
private fun step(
value: Float,
state: TransitionState = TransitionState.RUNNING
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index b042c30..ff72476 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -397,7 +397,7 @@
setUpPipes();
mAgent = mBackupManagerService.bindToAgentSynchronous(mTargetApp,
FullBackup.KEY_VALUE_DATA_TOKEN.equals(info.domain)
- ? ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL
+ ? ApplicationThreadConstants.BACKUP_MODE_RESTORE
: ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL,
mBackupEligibilityRules.getBackupDestination());
mAgentPackage = pkg;
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 1656b6f..77990af 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -677,7 +677,7 @@
// Good to go! Set up and bind the agent...
mAgent = backupManagerService.bindToAgentSynchronous(
mCurrentPackage.applicationInfo,
- ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL,
+ ApplicationThreadConstants.BACKUP_MODE_RESTORE,
mBackupEligibilityRules.getBackupDestination());
if (mAgent == null) {
Slog.w(TAG, "Can't find backup agent for " + packageName);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 81dc346..1f80aec 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4603,8 +4603,7 @@
boolean isRestrictedBackupMode = false;
if (backupTarget != null && backupTarget.appInfo.packageName.equals(processName)) {
isRestrictedBackupMode = backupTarget.appInfo.uid >= FIRST_APPLICATION_UID
- && ((backupTarget.backupMode == BackupRecord.RESTORE)
- || (backupTarget.backupMode == BackupRecord.RESTORE_FULL)
+ && ((backupTarget.backupMode == BackupRecord.RESTORE_FULL)
|| (backupTarget.backupMode == BackupRecord.BACKUP_FULL));
}
@@ -13394,7 +13393,8 @@
BackupRecord r = new BackupRecord(app, backupMode, targetUserId, backupDestination);
ComponentName hostingName =
- (backupMode == ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL)
+ (backupMode == ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL
+ || backupMode == ApplicationThreadConstants.BACKUP_MODE_RESTORE)
? new ComponentName(app.packageName, app.backupAgentName)
: new ComponentName("android", "FullBackupAgent");
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index a3163e0..02c4770 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -2284,8 +2284,8 @@
synchronized (VolumeStreamState.class) {
mStreamStates[AudioSystem.STREAM_DTMF]
.setAllIndexes(mStreamStates[dtmfStreamAlias], caller);
- mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
- System.VOLUME_SETTINGS_INT[a11yStreamAlias];
+ mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setSettingName(
+ System.VOLUME_SETTINGS_INT[a11yStreamAlias]);
mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
mStreamStates[a11yStreamAlias], caller);
}
@@ -7700,7 +7700,7 @@
private int mPublicStreamType = AudioSystem.STREAM_MUSIC;
private AudioAttributes mAudioAttributes = AudioProductStrategy.getDefaultAttributes();
private boolean mIsMuted = false;
- private final String mSettingName;
+ private String mSettingName;
// No API in AudioSystem to get a device from strategy or from attributes.
// Need a valid public stream type to use current API getDeviceForStream
@@ -8029,15 +8029,19 @@
}
private void persistVolumeGroup(int device) {
- if (mUseFixedVolume) {
+ // No need to persist the index if the volume group is backed up
+ // by a public stream type as this is redundant
+ if (mUseFixedVolume || mHasValidStreamType) {
return;
}
if (DEBUG_VOL) {
Log.v(TAG, "persistVolumeGroup: storing index " + getIndex(device) + " for group "
+ mAudioVolumeGroup.name()
+ ", device " + AudioSystem.getOutputDeviceName(device)
- + " and User=" + getCurrentUserId());
+ + " and User=" + getCurrentUserId()
+ + " mSettingName: " + mSettingName);
}
+
boolean success = mSettings.putSystemIntForUser(mContentResolver,
getSettingNameForDevice(device),
getIndex(device),
@@ -8100,6 +8104,14 @@
return mSettingName + "_" + AudioSystem.getOutputDeviceName(device);
}
+ void setSettingName(String settingName) {
+ mSettingName = settingName;
+ }
+
+ String getSettingName() {
+ return mSettingName;
+ }
+
private void dump(PrintWriter pw) {
pw.println("- VOLUME GROUP " + mAudioVolumeGroup.name() + ":");
pw.print(" Muted: ");
@@ -8242,6 +8254,9 @@
*/
public void setVolumeGroupState(VolumeGroupState volumeGroupState) {
mVolumeGroupState = volumeGroupState;
+ if (mVolumeGroupState != null) {
+ mVolumeGroupState.setSettingName(mVolumeIndexSettingName);
+ }
}
/**
* Update the minimum index that can be used without MODIFY_AUDIO_SETTINGS permission
@@ -8315,6 +8330,17 @@
return (mVolumeIndexSettingName != null && !mVolumeIndexSettingName.isEmpty());
}
+ void setSettingName(String settingName) {
+ mVolumeIndexSettingName = settingName;
+ if (mVolumeGroupState != null) {
+ mVolumeGroupState.setSettingName(mVolumeIndexSettingName);
+ }
+ }
+
+ String getSettingName() {
+ return mVolumeIndexSettingName;
+ }
+
public void readSettings() {
synchronized (mSettingsLock) {
synchronized (VolumeStreamState.class) {
@@ -8989,7 +9015,7 @@
if (streamState.hasValidSettingsName()) {
mSettings.putSystemIntForUser(mContentResolver,
streamState.getSettingNameForDevice(device),
- (streamState.getIndex(device) + 5)/ 10,
+ (streamState.getIndex(device) + 5) / 10,
UserHandle.USER_CURRENT);
}
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 85b4034..5d92c7f 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -119,7 +119,6 @@
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.text.TextUtils;
-import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
import android.util.IntArray;
@@ -298,11 +297,10 @@
mDisplayWindowPolicyControllers = new SparseArray<>();
/**
- * Map of every internal primary display device {@link HighBrightnessModeMetadata}s indexed by
- * {@link DisplayDevice#mUniqueId}.
+ * Provides {@link HighBrightnessModeMetadata}s for {@link DisplayDevice}s.
*/
- public final ArrayMap<String, HighBrightnessModeMetadata> mHighBrightnessModeMetadataMap =
- new ArrayMap<>();
+ private final HighBrightnessModeMetadataMapper mHighBrightnessModeMetadataMapper =
+ new HighBrightnessModeMetadataMapper();
// List of all currently registered display adapters.
private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
@@ -1823,19 +1821,14 @@
DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
- final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
- if (device == null) {
- Slog.wtf(TAG, "Display Device is null in DisplayManagerService for display: "
- + display.getDisplayIdLocked());
- return;
- }
-
final int leadDisplayId = display.getLeadDisplayIdLocked();
updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
- final String uniqueId = device.getUniqueId();
- HighBrightnessModeMetadata hbmMetadata = mHighBrightnessModeMetadataMap.get(uniqueId);
- dpc.onDisplayChanged(hbmMetadata, leadDisplayId);
+ HighBrightnessModeMetadata hbmMetadata =
+ mHighBrightnessModeMetadataMapper.getHighBrightnessModeMetadataLocked(display);
+ if (hbmMetadata != null) {
+ dpc.onDisplayChanged(hbmMetadata, leadDisplayId);
+ }
}
}
@@ -1922,19 +1915,14 @@
final int displayId = display.getDisplayIdLocked();
final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
- final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
- if (device == null) {
- Slog.wtf(TAG, "Display Device is null in DisplayManagerService for display: "
- + display.getDisplayIdLocked());
- return;
- }
-
final int leadDisplayId = display.getLeadDisplayIdLocked();
updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
- final String uniqueId = device.getUniqueId();
- HighBrightnessModeMetadata hbmMetadata = mHighBrightnessModeMetadataMap.get(uniqueId);
- dpc.onDisplayChanged(hbmMetadata, leadDisplayId);
+ HighBrightnessModeMetadata hbmMetadata =
+ mHighBrightnessModeMetadataMapper.getHighBrightnessModeMetadataLocked(display);
+ if (hbmMetadata != null) {
+ dpc.onDisplayChanged(hbmMetadata, leadDisplayId);
+ }
}
}
@@ -3073,26 +3061,6 @@
mLogicalDisplayMapper.forEachLocked(this::addDisplayPowerControllerLocked);
}
- private HighBrightnessModeMetadata getHighBrightnessModeMetadata(LogicalDisplay display) {
- final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
- if (device == null) {
- Slog.wtf(TAG, "Display Device is null in DisplayPowerController for display: "
- + display.getDisplayIdLocked());
- return null;
- }
-
- final String uniqueId = device.getUniqueId();
-
- if (mHighBrightnessModeMetadataMap.containsKey(uniqueId)) {
- return mHighBrightnessModeMetadataMap.get(uniqueId);
- }
-
- // HBM Time info not present. Create a new one for this physical display.
- HighBrightnessModeMetadata hbmInfo = new HighBrightnessModeMetadata();
- mHighBrightnessModeMetadataMap.put(uniqueId, hbmInfo);
- return hbmInfo;
- }
-
@RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
private void addDisplayPowerControllerLocked(LogicalDisplay display) {
if (mPowerHandler == null) {
@@ -3113,7 +3081,13 @@
// We also need to pass a mapping of the HighBrightnessModeTimeInfoMap to
// displayPowerController, so the hbm info can be correctly associated
// with the corresponding displaydevice.
- HighBrightnessModeMetadata hbmMetadata = getHighBrightnessModeMetadata(display);
+ HighBrightnessModeMetadata hbmMetadata =
+ mHighBrightnessModeMetadataMapper.getHighBrightnessModeMetadataLocked(display);
+ if (hbmMetadata == null) {
+ Slog.wtf(TAG, "High Brightness Mode Metadata is null in DisplayManagerService for "
+ + "display: " + display.getDisplayIdLocked());
+ return;
+ }
if (DeviceConfig.getBoolean("display_manager",
"use_newly_structured_display_power_controller", true)) {
displayPowerController = new DisplayPowerController2(
diff --git a/services/core/java/com/android/server/display/HighBrightnessModeMetadataMapper.java b/services/core/java/com/android/server/display/HighBrightnessModeMetadataMapper.java
new file mode 100644
index 0000000..76702d3
--- /dev/null
+++ b/services/core/java/com/android/server/display/HighBrightnessModeMetadataMapper.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 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.display;
+
+import android.util.ArrayMap;
+import android.util.Slog;
+
+/**
+ * Provides {@link HighBrightnessModeMetadata}s for {@link DisplayDevice}s. This class should only
+ * be accessed from the display thread.
+ */
+class HighBrightnessModeMetadataMapper {
+
+ private static final String TAG = "HighBrightnessModeMetadataMapper";
+
+ /**
+ * Map of every internal primary display device {@link HighBrightnessModeMetadata}s indexed by
+ * {@link DisplayDevice#mUniqueId}.
+ */
+ private final ArrayMap<String, HighBrightnessModeMetadata> mHighBrightnessModeMetadataMap =
+ new ArrayMap<>();
+
+ HighBrightnessModeMetadata getHighBrightnessModeMetadataLocked(LogicalDisplay display) {
+ final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
+ if (device == null) {
+ Slog.wtf(TAG, "Display Device is null in DisplayPowerController for display: "
+ + display.getDisplayIdLocked());
+ return null;
+ }
+
+ final String uniqueId = device.getUniqueId();
+
+ if (mHighBrightnessModeMetadataMap.containsKey(uniqueId)) {
+ return mHighBrightnessModeMetadataMap.get(uniqueId);
+ }
+
+ // HBM Time info not present. Create a new one for this physical display.
+ HighBrightnessModeMetadata hbmInfo = new HighBrightnessModeMetadata();
+ mHighBrightnessModeMetadataMap.put(uniqueId, hbmInfo);
+ return hbmInfo;
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 9eedc4e..f47c4b2 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -682,7 +682,6 @@
@ServiceThreadOnly
private void launchDeviceDiscovery() {
assertRunOnServiceThread();
- clearDeviceInfoList();
DeviceDiscoveryAction action = new DeviceDiscoveryAction(this,
new DeviceDiscoveryCallback() {
@Override
@@ -691,13 +690,6 @@
mService.getHdmiCecNetwork().addCecDevice(info);
}
- // Since we removed all devices when it starts and
- // device discovery action does not poll local devices,
- // we should put device info of local device manually here
- for (HdmiCecLocalDevice device : mService.getAllCecLocalDevices()) {
- mService.getHdmiCecNetwork().addCecDevice(device.getDeviceInfo());
- }
-
mSelectRequestBuffer.process();
resetSelectRequestBuffer();
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 805ff66..75fe63a 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1267,6 +1267,7 @@
// It's now safe to flush existing local devices from mCecController since they were
// already moved to 'localDevices'.
clearCecLocalDevices();
+ mHdmiCecNetwork.clearDeviceList();
allocateLogicalAddress(localDevices, initiatedBy);
}
@@ -1303,6 +1304,7 @@
HdmiControlManager.POWER_STATUS_ON, getCecVersion());
localDevice.setDeviceInfo(deviceInfo);
mHdmiCecNetwork.addLocalDevice(deviceType, localDevice);
+ mHdmiCecNetwork.addCecDevice(localDevice.getDeviceInfo());
mCecController.addLogicalAddress(logicalAddress);
allocatedDevices.add(localDevice);
}
diff --git a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
index 0ae1e80..a1b67e1 100644
--- a/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
+++ b/services/core/java/com/android/server/inputmethod/DefaultImeVisibilityApplier.java
@@ -18,14 +18,19 @@
import static android.view.inputmethod.ImeTracker.DEBUG_IME_VISIBILITY;
+import static com.android.internal.inputmethod.SoftInputShowHideReason.REMOVE_IME_SCREENSHOT_FROM_IMMS;
+import static com.android.internal.inputmethod.SoftInputShowHideReason.SHOW_IME_SCREENSHOT_FROM_IMMS;
import static com.android.server.EventLogTags.IMF_HIDE_IME;
import static com.android.server.EventLogTags.IMF_SHOW_IME;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME_EXPLICIT;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME_NOT_ALWAYS;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_REMOVE_IME_SNAPSHOT;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_SHOW_IME;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_SHOW_IME_IMPLICIT;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_SHOW_IME_SNAPSHOT;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.IBinder;
import android.os.ResultReceiver;
@@ -38,6 +43,7 @@
import com.android.internal.inputmethod.InputMethodDebug;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.server.LocalServices;
+import com.android.server.wm.ImeTargetVisibilityPolicy;
import com.android.server.wm.WindowManagerInternal;
import java.util.Objects;
@@ -56,10 +62,14 @@
private final WindowManagerInternal mWindowManagerInternal;
+ @NonNull
+ private final ImeTargetVisibilityPolicy mImeTargetVisibilityPolicy;
+
DefaultImeVisibilityApplier(InputMethodManagerService service) {
mService = service;
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
+ mImeTargetVisibilityPolicy = LocalServices.getService(ImeTargetVisibilityPolicy.class);
}
@GuardedBy("ImfLock.class")
@@ -162,8 +172,37 @@
mService.showCurrentInputLocked(windowToken, statsToken,
InputMethodManager.SHOW_IMPLICIT, null, reason);
break;
+ case STATE_SHOW_IME_SNAPSHOT:
+ showImeScreenshot(windowToken, mService.getDisplayIdToShowImeLocked(), null);
+ break;
+ case STATE_REMOVE_IME_SNAPSHOT:
+ removeImeScreenshot(mService.getDisplayIdToShowImeLocked());
+ break;
default:
throw new IllegalArgumentException("Invalid IME visibility state: " + state);
}
}
+
+ @GuardedBy("ImfLock.class")
+ @Override
+ public boolean showImeScreenshot(@NonNull IBinder imeTarget, int displayId,
+ @Nullable ImeTracker.Token statsToken) {
+ if (mImeTargetVisibilityPolicy.showImeScreenshot(imeTarget, displayId)) {
+ mService.onShowHideSoftInputRequested(false /* show */, imeTarget,
+ SHOW_IME_SCREENSHOT_FROM_IMMS, statsToken);
+ return true;
+ }
+ return false;
+ }
+
+ @GuardedBy("ImfLock.class")
+ @Override
+ public boolean removeImeScreenshot(int displayId) {
+ if (mImeTargetVisibilityPolicy.removeImeScreenshot(displayId)) {
+ mService.onShowHideSoftInputRequested(false /* show */, mService.mCurFocusedWindow,
+ REMOVE_IME_SCREENSHOT_FROM_IMMS, null);
+ return true;
+ }
+ return false;
+ }
}
diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java
index f03e985..27f6a89 100644
--- a/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java
+++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityApplier.java
@@ -16,6 +16,7 @@
package com.android.server.inputmethod;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.IBinder;
import android.os.ResultReceiver;
@@ -76,4 +77,27 @@
// TODO: add a method in WindowManagerInternal to call DC#updateImeInputAndControlTarget
// here to end up updating IME layering after IMMS#attachNewInputLocked called.
}
+
+ /**
+ * Shows the IME screenshot and attach it to the given IME target window.
+ *
+ * @param windowToken The token of a window to show the IME screenshot.
+ * @param displayId The unique id to identify the display
+ * @param statsToken A token that tracks the progress of an IME request.
+ * @return {@code true} if success, {@code false} otherwise.
+ */
+ default boolean showImeScreenshot(@NonNull IBinder windowToken, int displayId,
+ @Nullable ImeTracker.Token statsToken) {
+ return false;
+ }
+
+ /**
+ * Removes the IME screenshot on the given display.
+ *
+ * @param displayId The target display of showing IME screenshot.
+ * @return {@code true} if success, {@code false} otherwise.
+ */
+ default boolean removeImeScreenshot(int displayId) {
+ return false;
+ }
}
diff --git a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
index 61fe654..19d6fa0 100644
--- a/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
+++ b/services/core/java/com/android/server/inputmethod/ImeVisibilityStateComputer.java
@@ -29,6 +29,8 @@
import static android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import static com.android.internal.inputmethod.InputMethodDebug.softInputModeToString;
+import static com.android.internal.inputmethod.SoftInputShowHideReason.REMOVE_IME_SCREENSHOT_FROM_IMMS;
+import static com.android.internal.inputmethod.SoftInputShowHideReason.SHOW_IME_SCREENSHOT_FROM_IMMS;
import static com.android.server.inputmethod.InputMethodManagerService.computeImeDisplayIdForTarget;
import android.accessibilityservice.AccessibilityService;
@@ -49,6 +51,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.server.LocalServices;
+import com.android.server.wm.ImeTargetChangeListener;
import com.android.server.wm.WindowManagerInternal;
import java.io.PrintWriter;
@@ -99,6 +102,18 @@
*/
private boolean mInputShown;
+ /**
+ * Set if we called
+ * {@link com.android.server.wm.ImeTargetVisibilityPolicy#showImeScreenshot(IBinder, int)}.
+ */
+ private boolean mRequestedImeScreenshot;
+
+ /** The window token of the current visible IME layering target overlay. */
+ private IBinder mCurVisibleImeLayeringOverlay;
+
+ /** The window token of the current visible IME input target. */
+ private IBinder mCurVisibleImeInputTarget;
+
/** Represent the invalid IME visibility state */
public static final int STATE_INVALID = -1;
@@ -122,6 +137,10 @@
public static final int STATE_HIDE_IME_NOT_ALWAYS = 6;
public static final int STATE_SHOW_IME_IMPLICIT = 7;
+
+ /** State to handle removing an IME preview surface when necessary. */
+ public static final int STATE_REMOVE_IME_SNAPSHOT = 8;
+
@IntDef({
STATE_INVALID,
STATE_HIDE_IME,
@@ -132,6 +151,7 @@
STATE_HIDE_IME_EXPLICIT,
STATE_HIDE_IME_NOT_ALWAYS,
STATE_SHOW_IME_IMPLICIT,
+ STATE_REMOVE_IME_SNAPSHOT,
})
@interface VisibilityState {}
@@ -172,6 +192,24 @@
mWindowManagerInternal = wmService;
mImeDisplayValidator = imeDisplayValidator;
mPolicy = imePolicy;
+ mWindowManagerInternal.setInputMethodTargetChangeListener(new ImeTargetChangeListener() {
+ @Override
+ public void onImeTargetOverlayVisibilityChanged(IBinder overlayWindowToken,
+ boolean visible, boolean removed) {
+ mCurVisibleImeLayeringOverlay = (visible && !removed) ? overlayWindowToken : null;
+ }
+
+ @Override
+ public void onImeInputTargetVisibilityChanged(IBinder imeInputTarget,
+ boolean visibleRequested, boolean removed) {
+ mCurVisibleImeInputTarget = (visibleRequested && !removed) ? imeInputTarget : null;
+ if (mCurVisibleImeInputTarget == null && mCurVisibleImeLayeringOverlay != null) {
+ mService.onApplyImeVisibilityFromComputer(imeInputTarget,
+ new ImeVisibilityResult(STATE_HIDE_IME_EXPLICIT,
+ SoftInputShowHideReason.HIDE_WHEN_INPUT_TARGET_INVISIBLE));
+ }
+ }
+ });
}
/**
@@ -453,6 +491,21 @@
return null;
}
+ @VisibleForTesting
+ ImeVisibilityResult onInteractiveChanged(IBinder windowToken, boolean interactive) {
+ final ImeTargetWindowState state = getWindowStateOrNull(windowToken);
+ if (state != null && state.isRequestedImeVisible() && mInputShown && !interactive) {
+ mRequestedImeScreenshot = true;
+ return new ImeVisibilityResult(STATE_SHOW_IME_SNAPSHOT, SHOW_IME_SCREENSHOT_FROM_IMMS);
+ }
+ if (interactive && mRequestedImeScreenshot) {
+ mRequestedImeScreenshot = false;
+ return new ImeVisibilityResult(STATE_REMOVE_IME_SNAPSHOT,
+ REMOVE_IME_SCREENSHOT_FROM_IMMS);
+ }
+ return null;
+ }
+
IBinder getWindowTokenFrom(IBinder requestImeToken) {
for (IBinder windowToken : mRequestWindowStateMap.keySet()) {
final ImeTargetWindowState state = mRequestWindowStateMap.get(windowToken);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 2433211..c70d555 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -4847,6 +4847,14 @@
}
}
+ void onApplyImeVisibilityFromComputer(IBinder windowToken,
+ @NonNull ImeVisibilityResult result) {
+ synchronized (ImfLock.class) {
+ mVisibilityApplier.applyImeVisibility(windowToken, null, result.getState(),
+ result.getReason());
+ }
+ }
+
@GuardedBy("ImfLock.class")
void setEnabledSessionLocked(SessionState session) {
if (mEnabledSession != session) {
@@ -5083,6 +5091,14 @@
return;
}
if (mImePlatformCompatUtils.shouldUseSetInteractiveProtocol(getCurMethodUidLocked())) {
+ // Handle IME visibility when interactive changed before finishing the input to
+ // ensure we preserve the last state as possible.
+ final ImeVisibilityResult imeVisRes = mVisibilityStateComputer.onInteractiveChanged(
+ mCurFocusedWindow, interactive);
+ if (imeVisRes != null) {
+ mVisibilityApplier.applyImeVisibility(mCurFocusedWindow, null,
+ imeVisRes.getState(), imeVisRes.getReason());
+ }
// Eligible IME processes use new "setInteractive" protocol.
mCurClient.mClient.setInteractive(mIsInteractive, mInFullscreenMode);
} else {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ebcbfed..07891f3 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -10796,7 +10796,8 @@
static final String FLAG_SEPARATOR = "\\|";
private final ArraySet<ManagedServiceInfo> mLightTrimListeners = new ArraySet<>();
- ArrayMap<Pair<ComponentName, Integer>, NotificationListenerFilter>
+ @GuardedBy("mRequestedNotificationListeners")
+ private final ArrayMap<Pair<ComponentName, Integer>, NotificationListenerFilter>
mRequestedNotificationListeners = new ArrayMap<>();
private final boolean mIsHeadlessSystemUserMode;
@@ -10914,9 +10915,11 @@
@Override
public void onUserRemoved(int user) {
super.onUserRemoved(user);
- for (int i = mRequestedNotificationListeners.size() - 1; i >= 0; i--) {
- if (mRequestedNotificationListeners.keyAt(i).second == user) {
- mRequestedNotificationListeners.removeAt(i);
+ synchronized (mRequestedNotificationListeners) {
+ for (int i = mRequestedNotificationListeners.size() - 1; i >= 0; i--) {
+ if (mRequestedNotificationListeners.keyAt(i).second == user) {
+ mRequestedNotificationListeners.removeAt(i);
+ }
}
}
}
@@ -10925,31 +10928,34 @@
public void onPackagesChanged(boolean removingPackage, String[] pkgList, int[] uidList) {
super.onPackagesChanged(removingPackage, pkgList, uidList);
- // Since the default behavior is to allow everything, we don't need to explicitly
- // handle package add or update. they will be added to the xml file on next boot or
- // when the user tries to change the settings.
- if (removingPackage) {
- for (int i = 0; i < pkgList.length; i++) {
- String pkg = pkgList[i];
- int userId = UserHandle.getUserId(uidList[i]);
- for (int j = mRequestedNotificationListeners.size() - 1; j >= 0; j--) {
- Pair<ComponentName, Integer> key = mRequestedNotificationListeners.keyAt(j);
- if (key.second == userId && key.first.getPackageName().equals(pkg)) {
- mRequestedNotificationListeners.removeAt(j);
+ synchronized (mRequestedNotificationListeners) {
+ // Since the default behavior is to allow everything, we don't need to explicitly
+ // handle package add or update. they will be added to the xml file on next boot or
+ // when the user tries to change the settings.
+ if (removingPackage) {
+ for (int i = 0; i < pkgList.length; i++) {
+ String pkg = pkgList[i];
+ int userId = UserHandle.getUserId(uidList[i]);
+ for (int j = mRequestedNotificationListeners.size() - 1; j >= 0; j--) {
+ Pair<ComponentName, Integer> key =
+ mRequestedNotificationListeners.keyAt(j);
+ if (key.second == userId && key.first.getPackageName().equals(pkg)) {
+ mRequestedNotificationListeners.removeAt(j);
+ }
}
}
}
- }
- // clean up anything in the disallowed pkgs list
- for (int i = 0; i < pkgList.length; i++) {
- String pkg = pkgList[i];
- int userId = UserHandle.getUserId(uidList[i]);
- for (int j = mRequestedNotificationListeners.size() - 1; j >= 0; j--) {
- NotificationListenerFilter nlf = mRequestedNotificationListeners.valueAt(j);
+ // clean up anything in the disallowed pkgs list
+ for (int i = 0; i < pkgList.length; i++) {
+ String pkg = pkgList[i];
+ for (int j = mRequestedNotificationListeners.size() - 1; j >= 0; j--) {
+ NotificationListenerFilter nlf =
+ mRequestedNotificationListeners.valueAt(j);
- VersionedPackage ai = new VersionedPackage(pkg, uidList[i]);
- nlf.removePackage(ai);
+ VersionedPackage ai = new VersionedPackage(pkg, uidList[i]);
+ nlf.removePackage(ai);
+ }
}
}
}
@@ -10997,7 +11003,9 @@
}
NotificationListenerFilter nlf =
new NotificationListenerFilter(approved, disallowedPkgs);
- mRequestedNotificationListeners.put(Pair.create(cn, userId), nlf);
+ synchronized (mRequestedNotificationListeners) {
+ mRequestedNotificationListeners.put(Pair.create(cn, userId), nlf);
+ }
}
}
}
@@ -11005,72 +11013,81 @@
@Override
protected void writeExtraXmlTags(TypedXmlSerializer out) throws IOException {
out.startTag(null, TAG_REQUESTED_LISTENERS);
- for (Pair<ComponentName, Integer> listener : mRequestedNotificationListeners.keySet()) {
- NotificationListenerFilter nlf = mRequestedNotificationListeners.get(listener);
- out.startTag(null, TAG_REQUESTED_LISTENER);
- XmlUtils.writeStringAttribute(
- out, ATT_COMPONENT, listener.first.flattenToString());
- XmlUtils.writeIntAttribute(out, ATT_USER_ID, listener.second);
+ synchronized (mRequestedNotificationListeners) {
+ for (Pair<ComponentName, Integer> listener :
+ mRequestedNotificationListeners.keySet()) {
+ NotificationListenerFilter nlf = mRequestedNotificationListeners.get(listener);
+ out.startTag(null, TAG_REQUESTED_LISTENER);
+ XmlUtils.writeStringAttribute(
+ out, ATT_COMPONENT, listener.first.flattenToString());
+ XmlUtils.writeIntAttribute(out, ATT_USER_ID, listener.second);
- out.startTag(null, TAG_APPROVED);
- XmlUtils.writeIntAttribute(out, ATT_TYPES, nlf.getTypes());
- out.endTag(null, TAG_APPROVED);
+ out.startTag(null, TAG_APPROVED);
+ XmlUtils.writeIntAttribute(out, ATT_TYPES, nlf.getTypes());
+ out.endTag(null, TAG_APPROVED);
- for (VersionedPackage ai : nlf.getDisallowedPackages()) {
- if (!TextUtils.isEmpty(ai.getPackageName())) {
- out.startTag(null, TAG_DISALLOWED);
- XmlUtils.writeStringAttribute(out, ATT_PKG, ai.getPackageName());
- XmlUtils.writeIntAttribute(out, ATT_UID, ai.getVersionCode());
- out.endTag(null, TAG_DISALLOWED);
+ for (VersionedPackage ai : nlf.getDisallowedPackages()) {
+ if (!TextUtils.isEmpty(ai.getPackageName())) {
+ out.startTag(null, TAG_DISALLOWED);
+ XmlUtils.writeStringAttribute(out, ATT_PKG, ai.getPackageName());
+ XmlUtils.writeIntAttribute(out, ATT_UID, ai.getVersionCode());
+ out.endTag(null, TAG_DISALLOWED);
+ }
}
- }
- out.endTag(null, TAG_REQUESTED_LISTENER);
+ out.endTag(null, TAG_REQUESTED_LISTENER);
+ }
}
out.endTag(null, TAG_REQUESTED_LISTENERS);
}
- protected @Nullable NotificationListenerFilter getNotificationListenerFilter(
+ @Nullable protected NotificationListenerFilter getNotificationListenerFilter(
Pair<ComponentName, Integer> pair) {
- return mRequestedNotificationListeners.get(pair);
+ synchronized (mRequestedNotificationListeners) {
+ return mRequestedNotificationListeners.get(pair);
+ }
}
protected void setNotificationListenerFilter(Pair<ComponentName, Integer> pair,
NotificationListenerFilter nlf) {
- mRequestedNotificationListeners.put(pair, nlf);
+ synchronized (mRequestedNotificationListeners) {
+ mRequestedNotificationListeners.put(pair, nlf);
+ }
}
@Override
protected void ensureFilters(ServiceInfo si, int userId) {
- Pair listener = Pair.create(si.getComponentName(), userId);
- NotificationListenerFilter existingNlf =
- mRequestedNotificationListeners.get(listener);
- if (si.metaData != null) {
- if (existingNlf == null) {
- // no stored filters for this listener; see if they provided a default
- if (si.metaData.containsKey(META_DATA_DEFAULT_FILTER_TYPES)) {
- String typeList =
- si.metaData.get(META_DATA_DEFAULT_FILTER_TYPES).toString();
- if (typeList != null) {
- int types = getTypesFromStringList(typeList);
- NotificationListenerFilter nlf =
- new NotificationListenerFilter(types, new ArraySet<>());
- mRequestedNotificationListeners.put(listener, nlf);
+ Pair<ComponentName, Integer> listener = Pair.create(si.getComponentName(), userId);
+ synchronized (mRequestedNotificationListeners) {
+ NotificationListenerFilter existingNlf =
+ mRequestedNotificationListeners.get(listener);
+ if (si.metaData != null) {
+ if (existingNlf == null) {
+ // no stored filters for this listener; see if they provided a default
+ if (si.metaData.containsKey(META_DATA_DEFAULT_FILTER_TYPES)) {
+ String typeList =
+ si.metaData.get(META_DATA_DEFAULT_FILTER_TYPES).toString();
+ if (typeList != null) {
+ int types = getTypesFromStringList(typeList);
+ NotificationListenerFilter nlf =
+ new NotificationListenerFilter(types, new ArraySet<>());
+ mRequestedNotificationListeners.put(listener, nlf);
+ }
}
}
- }
- // also check the types they never want bridged
- if (si.metaData.containsKey(META_DATA_DISABLED_FILTER_TYPES)) {
- int neverBridge = getTypesFromStringList(si.metaData.get(
- META_DATA_DISABLED_FILTER_TYPES).toString());
- if (neverBridge != 0) {
- NotificationListenerFilter nlf =
- mRequestedNotificationListeners.getOrDefault(
- listener, new NotificationListenerFilter());
- nlf.setTypes(nlf.getTypes() & ~neverBridge);
- mRequestedNotificationListeners.put(listener, nlf);
+ // also check the types they never want bridged
+ if (si.metaData.containsKey(META_DATA_DISABLED_FILTER_TYPES)) {
+ int neverBridge = getTypesFromStringList(si.metaData.get(
+ META_DATA_DISABLED_FILTER_TYPES).toString());
+ if (neverBridge != 0) {
+ NotificationListenerFilter nlf =
+ mRequestedNotificationListeners.getOrDefault(
+ listener, new NotificationListenerFilter());
+ nlf.setTypes(nlf.getTypes() & ~neverBridge);
+ mRequestedNotificationListeners.put(listener, nlf);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/pm/VerifyingSession.java b/services/core/java/com/android/server/pm/VerifyingSession.java
index 5015985..7198de2 100644
--- a/services/core/java/com/android/server/pm/VerifyingSession.java
+++ b/services/core/java/com/android/server/pm/VerifyingSession.java
@@ -353,11 +353,10 @@
PackageInfoLite pkgLite,
PackageVerificationState verificationState) {
- // TODO: http://b/22976637
- // Apps installed for "all" users use the device owner to verify the app
+ // Apps installed for "all" users use the current user to verify the app
UserHandle verifierUser = getUser();
if (verifierUser == UserHandle.ALL) {
- verifierUser = UserHandle.SYSTEM;
+ verifierUser = UserHandle.of(mPm.mUserManager.getCurrentUserId());
}
final int verifierUserId = verifierUser.getIdentifier();
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index a757d90..f71f3b1 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -397,9 +397,21 @@
/** Returns {@code true} if the incoming activity can belong to this transition. */
boolean canCoalesce(ActivityRecord r) {
- return mLastLaunchedActivity.mDisplayContent == r.mDisplayContent
- && mLastLaunchedActivity.getTask().getBounds().equals(r.getTask().getBounds())
- && mLastLaunchedActivity.getWindowingMode() == r.getWindowingMode();
+ if (mLastLaunchedActivity.mDisplayContent != r.mDisplayContent
+ || mLastLaunchedActivity.getWindowingMode() != r.getWindowingMode()) {
+ return false;
+ }
+ // The current task should be non-null because it is just launched. While the
+ // last task can be cleared when starting activity with FLAG_ACTIVITY_CLEAR_TASK.
+ final Task lastTask = mLastLaunchedActivity.getTask();
+ final Task currentTask = r.getTask();
+ if (lastTask != null && currentTask != null) {
+ if (lastTask == currentTask) {
+ return true;
+ }
+ return lastTask.getBounds().equals(currentTask.getBounds());
+ }
+ return mLastLaunchedActivity.isUid(r.launchedFromUid);
}
/** @return {@code true} if the activity matches a launched activity in this transition. */
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 2160ce1..c6a2e0e 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2821,6 +2821,27 @@
}
}
+ @Override
+ void waitForSyncTransactionCommit(ArraySet<WindowContainer> wcAwaitingCommit) {
+ super.waitForSyncTransactionCommit(wcAwaitingCommit);
+ if (mStartingData != null) {
+ mStartingData.mWaitForSyncTransactionCommit = true;
+ }
+ }
+
+ @Override
+ void onSyncTransactionCommitted(SurfaceControl.Transaction t) {
+ super.onSyncTransactionCommitted(t);
+ if (mStartingData == null) {
+ return;
+ }
+ mStartingData.mWaitForSyncTransactionCommit = false;
+ if (mStartingData.mRemoveAfterTransaction) {
+ mStartingData.mRemoveAfterTransaction = false;
+ removeStartingWindowAnimation(mStartingData.mPrepareRemoveAnimation);
+ }
+ }
+
void removeStartingWindowAnimation(boolean prepareAnimation) {
mTransferringSplashScreenState = TRANSFER_SPLASH_SCREEN_IDLE;
if (task != null) {
@@ -2843,6 +2864,12 @@
final WindowState startingWindow = mStartingWindow;
final boolean animate;
if (mStartingData != null) {
+ if (mStartingData.mWaitForSyncTransactionCommit
+ || mTransitionController.inCollectingTransition(startingWindow)) {
+ mStartingData.mRemoveAfterTransaction = true;
+ mStartingData.mPrepareRemoveAnimation = prepareAnimation;
+ return;
+ }
animate = prepareAnimation && mStartingData.needRevealAnimation()
&& mStartingWindow.isVisibleByPolicy();
ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s"
@@ -2863,18 +2890,7 @@
this);
return;
}
-
- if (animate && mTransitionController.inCollectingTransition(startingWindow)) {
- // Defer remove starting window after transition start.
- // The surface of app window could really show after the transition finish.
- startingWindow.mSyncTransaction.addTransactionCommittedListener(Runnable::run, () -> {
- synchronized (mAtmService.mGlobalLock) {
- surface.remove(true);
- }
- });
- } else {
- surface.remove(animate);
- }
+ surface.remove(animate);
}
/**
diff --git a/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java b/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
index 5f56af7..1208b6ef 100644
--- a/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
+++ b/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
@@ -99,13 +99,15 @@
}
public void forEachConnection(Consumer<T> consumer) {
+ final ArraySet<T> connections;
synchronized (mActivity) {
if (mConnections == null || mConnections.isEmpty()) {
return;
}
- for (int i = mConnections.size() - 1; i >= 0; i--) {
- consumer.accept(mConnections.valueAt(i));
- }
+ connections = new ArraySet<>(mConnections);
+ }
+ for (int i = connections.size() - 1; i >= 0; i--) {
+ consumer.accept(connections.valueAt(i));
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index c5e75fa..a27f3e4 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2926,8 +2926,7 @@
// If the matching task is already in the adjacent task of the launch target. Adjust to use
// the adjacent task as its launch target. So the existing task will be launched into the
// closer one and won't be reparent redundantly.
- final Task adjacentTargetTask = mTargetRootTask.getAdjacentTaskFragment() != null
- ? mTargetRootTask.getAdjacentTaskFragment().asTask() : null;
+ final Task adjacentTargetTask = mTargetRootTask.getAdjacentTask();
if (adjacentTargetTask != null && intentActivity.isDescendantOf(adjacentTargetTask)) {
mTargetRootTask = adjacentTargetTask;
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index abf66bc..f93afe8 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2008,7 +2008,8 @@
return;
}
- if (r.isState(RESUMED) && r == mRootWindowContainer.getTopResumedActivity()) {
+ if ((touchedActivity == null || r == touchedActivity) && r.isState(RESUMED)
+ && r == mRootWindowContainer.getTopResumedActivity()) {
setLastResumedActivityUncheckLocked(r, "setFocusedTask-alreadyTop");
return;
}
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 597c8bf..805bff2 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -1030,12 +1030,11 @@
canPromote = false;
}
- // If the current window container is task and it have adjacent task, it means
- // both tasks will open or close app toghther but we want get their opening or
- // closing animation target independently so do not promote.
+ // If the current window container is a task with adjacent task set, the both
+ // adjacent tasks will be opened or closed together. To get their opening or
+ // closing animation target independently, skip promoting their animation targets.
if (current.asTask() != null
- && current.asTask().getAdjacentTaskFragment() != null
- && current.asTask().getAdjacentTaskFragment().asTask() != null) {
+ && current.asTask().getAdjacentTask() != null) {
canPromote = false;
}
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 11d84ff..0c196d7 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -227,6 +227,7 @@
backType = BackNavigationInfo.TYPE_CALLBACK;
}
infoBuilder.setOnBackInvokedCallback(callbackInfo.getCallback());
+ infoBuilder.setAnimationCallback(callbackInfo.isAnimationCallback());
mNavigationMonitor.startMonitor(window, navigationObserver);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c2bc459..bad64d3 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -656,6 +656,14 @@
*/
private InputTarget mLastImeInputTarget;
+
+ /**
+ * Tracks the windowToken of the input method input target and the corresponding
+ * {@link WindowContainerListener} for monitoring changes (e.g. the requested visibility
+ * change).
+ */
+ private @Nullable Pair<IBinder, WindowContainerListener> mImeTargetTokenListenerPair;
+
/**
* This controls the visibility and animation of the input method window.
*/
@@ -4267,7 +4275,38 @@
@VisibleForTesting
void setImeInputTarget(InputTarget target) {
+ if (mImeTargetTokenListenerPair != null) {
+ // Unregister the listener before changing to the new IME input target.
+ final WindowToken oldToken = mTokenMap.get(mImeTargetTokenListenerPair.first);
+ if (oldToken != null) {
+ oldToken.unregisterWindowContainerListener(mImeTargetTokenListenerPair.second);
+ }
+ mImeTargetTokenListenerPair = null;
+ }
mImeInputTarget = target;
+ // Notify listeners about IME input target window visibility by the target change.
+ if (target != null) {
+ // TODO(b/276743705): Let InputTarget register the visibility change of the hierarchy.
+ final WindowState targetWin = target.getWindowState();
+ if (targetWin != null) {
+ mImeTargetTokenListenerPair = new Pair<>(targetWin.mToken.token,
+ new WindowContainerListener() {
+ @Override
+ public void onVisibleRequestedChanged(boolean isVisibleRequested) {
+ // Notify listeners for IME input target window visibility change
+ // requested by the parent container.
+ mWmService.dispatchImeInputTargetVisibilityChanged(
+ targetWin.mClient.asBinder(), isVisibleRequested,
+ targetWin.mActivityRecord != null
+ && targetWin.mActivityRecord.finishing);
+ }
+ });
+ targetWin.mToken.registerWindowContainerListener(
+ mImeTargetTokenListenerPair.second);
+ mWmService.dispatchImeInputTargetVisibilityChanged(targetWin.mClient.asBinder(),
+ targetWin.isVisible() /* visible */, false /* removed */);
+ }
+ }
if (refreshImeSecureFlag(getPendingTransaction())) {
mWmService.requestTraversal();
}
@@ -4433,6 +4472,10 @@
}
private void attachImeScreenshotOnTarget(WindowState imeTarget) {
+ attachImeScreenshotOnTarget(imeTarget, false);
+ }
+
+ private void attachImeScreenshotOnTarget(WindowState imeTarget, boolean hideImeWindow) {
final SurfaceControl.Transaction t = getPendingTransaction();
// Remove the obsoleted IME snapshot first in case the new snapshot happens to
// override the current one before the transition finish and the surface never be
@@ -4441,6 +4484,11 @@
mImeScreenshot = new ImeScreenshot(
mWmService.mSurfaceControlFactory.apply(null), imeTarget);
mImeScreenshot.attachAndShow(t);
+ if (mInputMethodWindow != null && hideImeWindow) {
+ // Hide the IME window when deciding to show IME snapshot on demand.
+ // InsetsController will make IME visible again before animating it.
+ mInputMethodWindow.hide(false, false);
+ }
}
/**
@@ -4458,7 +4506,7 @@
*/
@VisibleForTesting
void showImeScreenshot(WindowState imeTarget) {
- attachImeScreenshotOnTarget(imeTarget);
+ attachImeScreenshotOnTarget(imeTarget, true /* hideImeWindow */);
}
/**
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 339b6ec..747819e9 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.view.Display.TYPE_INTERNAL;
import static android.view.InsetsFrameProvider.SOURCE_ARBITRARY_RECTANGLE;
import static android.view.InsetsFrameProvider.SOURCE_CONTAINER_BOUNDS;
@@ -2208,16 +2207,15 @@
private int updateSystemBarsLw(WindowState win, int disableFlags) {
final TaskDisplayArea defaultTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
- final boolean multiWindowTaskVisible =
+ final boolean adjacentTasksVisible =
defaultTaskDisplayArea.getRootTask(task -> task.isVisible()
- && task.getTopLeafTask().getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW)
+ && task.getTopLeafTask().getAdjacentTask() != null)
!= null;
final boolean freeformRootTaskVisible =
defaultTaskDisplayArea.isRootTaskVisible(WINDOWING_MODE_FREEFORM);
- // We need to force showing system bars when the multi-window or freeform root task is
- // visible.
- mForceShowSystemBars = multiWindowTaskVisible || freeformRootTaskVisible;
+ // We need to force showing system bars when adjacent tasks or freeform roots visible.
+ mForceShowSystemBars = adjacentTasksVisible || freeformRootTaskVisible;
// We need to force the consumption of the system bars if they are force shown or if they
// are controlled by a remote insets controller.
mForceConsumeSystemBars = mForceShowSystemBars
@@ -2238,7 +2236,7 @@
int appearance = APPEARANCE_OPAQUE_NAVIGATION_BARS | APPEARANCE_OPAQUE_STATUS_BARS;
appearance = configureStatusBarOpacity(appearance);
- appearance = configureNavBarOpacity(appearance, multiWindowTaskVisible,
+ appearance = configureNavBarOpacity(appearance, adjacentTasksVisible,
freeformRootTaskVisible);
// Show immersive mode confirmation if needed.
diff --git a/services/core/java/com/android/server/wm/ImeTargetChangeListener.java b/services/core/java/com/android/server/wm/ImeTargetChangeListener.java
new file mode 100644
index 0000000..8bc445b
--- /dev/null
+++ b/services/core/java/com/android/server/wm/ImeTargetChangeListener.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 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.wm;
+
+import android.annotation.NonNull;
+import android.os.IBinder;
+
+/**
+ * Callback the IME targeting window visibility change state for
+ * {@link com.android.server.inputmethod.InputMethodManagerService} to manage the IME surface
+ * visibility and z-ordering.
+ */
+public interface ImeTargetChangeListener {
+ /**
+ * Called when a non-IME-focusable overlay window being the IME layering target (e.g. a
+ * window with {@link android.view.WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} and
+ * {@link android.view.WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM} flags)
+ * has changed its window visibility.
+ *
+ * @param overlayWindowToken the window token of the overlay window.
+ * @param visible the visibility of the overlay window, {@code true} means visible
+ * and {@code false} otherwise.
+ * @param removed Whether the IME target overlay window has being removed.
+ */
+ default void onImeTargetOverlayVisibilityChanged(@NonNull IBinder overlayWindowToken,
+ boolean visible, boolean removed) {
+ }
+
+ /**
+ * Called when the visibility of IME input target window has changed.
+ *
+ * @param imeInputTarget the window token of the IME input target window.
+ * @param visible the new window visibility made by {@param imeInputTarget}. visible is
+ * {@code true} when switching to the new visible IME input target
+ * window and started input, or the same input target relayout to
+ * visible from invisible. In contrast, visible is {@code false} when
+ * closing the input target, or the same input target relayout to
+ * invisible from visible.
+ * @param removed Whether the IME input target window has being removed.
+ */
+ default void onImeInputTargetVisibilityChanged(@NonNull IBinder imeInputTarget, boolean visible,
+ boolean removed) {
+ }
+}
diff --git a/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java b/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java
index 71dd917..1d9f24c 100644
--- a/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java
+++ b/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java
@@ -19,6 +19,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.IBinder;
import android.view.WindowManager;
@@ -36,16 +37,15 @@
* @param displayId A unique id to identify the display.
* @return {@code true} if success, {@code false} otherwise.
*/
- public abstract boolean showImeScreenShot(IBinder imeTarget, int displayId);
+ public abstract boolean showImeScreenshot(@NonNull IBinder imeTarget, int displayId);
/**
- * Updates the IME parent for target window.
+ * Removes the IME screenshot on the given display.
*
- * @param imeTarget The target window to update the IME parent.
- * @param displayId A unique id to identify the display.
+ * @param displayId The target display of showing IME screenshot.
* @return {@code true} if success, {@code false} otherwise.
*/
- public abstract boolean updateImeParent(IBinder imeTarget, int displayId);
+ public abstract boolean removeImeScreenshot(int displayId);
/**
* Called when {@link DisplayContent#computeImeParent()} to check if it's valid to keep
diff --git a/services/core/java/com/android/server/wm/StartingData.java b/services/core/java/com/android/server/wm/StartingData.java
index 300a894..cff86ad 100644
--- a/services/core/java/com/android/server/wm/StartingData.java
+++ b/services/core/java/com/android/server/wm/StartingData.java
@@ -41,6 +41,26 @@
/** Whether the starting window is drawn. */
boolean mIsDisplayed;
+ /**
+ * For Shell transition.
+ * There will be a transition happen on attached activity, do not remove starting window during
+ * this period, because the transaction to show app window may not apply before remove starting
+ * window.
+ * Note this isn't equal to transition playing, the period should be
+ * Sync finishNow -> Start transaction apply.
+ */
+ boolean mWaitForSyncTransactionCommit;
+
+ /**
+ * For Shell transition.
+ * This starting window should be removed after applying the start transaction of transition,
+ * which ensures the app window has shown.
+ */
+ boolean mRemoveAfterTransaction;
+
+ /** Whether to prepare the removal animation. */
+ boolean mPrepareRemoveAnimation;
+
protected StartingData(WindowManagerService service, int typeParams) {
mService = service;
mTypeParams = typeParams;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 9363eb5..5c33e64 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2362,6 +2362,22 @@
return parentTask == null ? null : parentTask.getCreatedByOrganizerTask();
}
+ /** @return the first adjacent task of this task or its parent. */
+ @Nullable
+ Task getAdjacentTask() {
+ final TaskFragment adjacentTaskFragment = getAdjacentTaskFragment();
+ if (adjacentTaskFragment != null && adjacentTaskFragment.asTask() != null) {
+ return adjacentTaskFragment.asTask();
+ }
+
+ final WindowContainer parent = getParent();
+ if (parent == null || parent.asTask() == null) {
+ return null;
+ }
+
+ return parent.asTask().getAdjacentTask();
+ }
+
// TODO(task-merge): Figure out what's the right thing to do for places that used it.
boolean isRootTask() {
return getRootTask() == this;
@@ -2747,7 +2763,7 @@
Rect outSurfaceInsets) {
// If this task has its adjacent task, it means they should animate together. Use display
// bounds for them could move same as full screen task.
- if (getAdjacentTaskFragment() != null && getAdjacentTaskFragment().asTask() != null) {
+ if (getAdjacentTask() != null) {
super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
return;
}
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index b0a879e..e80cbb3 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -1081,12 +1081,12 @@
if (sourceTask != null && sourceTask == candidateTask) {
// Do nothing when task that is getting opened is same as the source.
} else if (sourceTask != null
- && mLaunchAdjacentFlagRootTask.getAdjacentTaskFragment() != null
+ && mLaunchAdjacentFlagRootTask.getAdjacentTask() != null
&& (sourceTask == mLaunchAdjacentFlagRootTask
|| sourceTask.isDescendantOf(mLaunchAdjacentFlagRootTask))) {
// If the adjacent launch is coming from the same root, launch to
// adjacent root instead.
- return mLaunchAdjacentFlagRootTask.getAdjacentTaskFragment().asTask();
+ return mLaunchAdjacentFlagRootTask.getAdjacentTask();
} else {
return mLaunchAdjacentFlagRootTask;
}
@@ -1095,10 +1095,8 @@
for (int i = mLaunchRootTasks.size() - 1; i >= 0; --i) {
if (mLaunchRootTasks.get(i).contains(windowingMode, activityType)) {
final Task launchRootTask = mLaunchRootTasks.get(i).task;
- final TaskFragment adjacentTaskFragment = launchRootTask != null
- ? launchRootTask.getAdjacentTaskFragment() : null;
- final Task adjacentRootTask =
- adjacentTaskFragment != null ? adjacentTaskFragment.asTask() : null;
+ final Task adjacentRootTask = launchRootTask != null
+ ? launchRootTask.getAdjacentTask() : null;
if (sourceTask != null && adjacentRootTask != null
&& (sourceTask == adjacentRootTask
|| sourceTask.isDescendantOf(adjacentRootTask))) {
@@ -1116,16 +1114,14 @@
// A pinned task relaunching should be handled by its task organizer. Skip fallback
// launch target of a pinned task from source task.
|| candidateTask.getWindowingMode() != WINDOWING_MODE_PINNED)) {
- Task launchTarget = sourceTask.getCreatedByOrganizerTask();
- if (launchTarget != null && launchTarget.getAdjacentTaskFragment() != null) {
- if (candidateTask != null) {
- final Task candidateRoot = candidateTask.getCreatedByOrganizerTask();
- if (candidateRoot != null && candidateRoot != launchTarget
- && launchTarget == candidateRoot.getAdjacentTaskFragment()) {
- launchTarget = candidateRoot;
- }
+ final Task adjacentTarget = sourceTask.getAdjacentTask();
+ if (adjacentTarget != null) {
+ if (candidateTask != null
+ && (candidateTask == adjacentTarget
+ || candidateTask.isDescendantOf(adjacentTarget))) {
+ return adjacentTarget;
}
- return launchTarget;
+ return sourceTask.getCreatedByOrganizerTask();
}
}
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 184293e..5626aa7 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -681,6 +681,7 @@
final StartingWindowRemovalInfo removalInfo = new StartingWindowRemovalInfo();
removalInfo.taskId = task.mTaskId;
removalInfo.playRevealAnimation = prepareAnimation
+ && task.getDisplayContent() != null
&& task.getDisplayInfo().state == Display.STATE_ON;
final boolean playShiftUpAnimation = !task.inMultiWindowMode();
final ActivityRecord topActivity = task.topActivityContainsStartingWindow();
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 969afe5..4922523 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -848,6 +848,16 @@
}
/**
+ * Sets by the {@link com.android.server.inputmethod.InputMethodManagerService} to monitor
+ * the visibility change of the IME targeted windows.
+ *
+ * @see ImeTargetChangeListener#onImeTargetOverlayVisibilityChanged
+ * @see ImeTargetChangeListener#onImeInputTargetVisibilityChanged
+ */
+ public abstract void setInputMethodTargetChangeListener(
+ @NonNull ImeTargetChangeListener listener);
+
+ /**
* Moves the {@link WindowToken} {@code binder} to the display specified by {@code displayId}.
*/
public abstract void moveWindowTokenToDisplay(IBinder binder, int displayId);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 99d0ea8..62b3c7c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -723,6 +723,9 @@
boolean mHardKeyboardAvailable;
WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
+
+ @Nullable ImeTargetChangeListener mImeTargetChangeListener;
+
SettingsObserver mSettingsObserver;
final EmbeddedWindowController mEmbeddedWindowController;
final AnrController mAnrController;
@@ -1807,6 +1810,10 @@
if (imMayMove) {
displayContent.computeImeTarget(true /* updateImeTarget */);
+ if (win.isImeOverlayLayeringTarget()) {
+ dispatchImeTargetOverlayVisibilityChanged(client.asBinder(),
+ win.isVisibleRequestedOrAdding(), false /* removed */);
+ }
}
// Don't do layout here, the window must call
@@ -2328,6 +2335,8 @@
winAnimator.mSurfaceController.setSecure(win.isSecureLocked());
}
+ final boolean wasVisible = win.isVisible();
+
win.mRelayoutCalled = true;
win.mInRelayout = true;
@@ -2336,7 +2345,6 @@
"Relayout %s: oldVis=%d newVis=%d. %s", win, oldVisibility,
viewVisibility, new RuntimeException().fillInStackTrace());
-
win.setDisplayLayoutNeeded();
win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
@@ -2501,6 +2509,18 @@
}
win.mInRelayout = false;
+ final boolean winVisibleChanged = win.isVisible() != wasVisible;
+ if (win.isImeOverlayLayeringTarget() && winVisibleChanged) {
+ dispatchImeTargetOverlayVisibilityChanged(client.asBinder(),
+ win.isVisible(), false /* removed */);
+ }
+ // Notify listeners about IME input target window visibility change.
+ final boolean isImeInputTarget = win.getDisplayContent().getImeInputTarget() == win;
+ if (isImeInputTarget && winVisibleChanged) {
+ dispatchImeInputTargetVisibilityChanged(win.mClient.asBinder(),
+ win.isVisible() /* visible */, false /* removed */);
+ }
+
if (outSyncIdBundle != null) {
final int maybeSyncSeqId;
if (USE_BLAST_SYNC && win.useBLASTSync() && viewVisibility == View.VISIBLE
@@ -3325,6 +3345,30 @@
});
}
+ void dispatchImeTargetOverlayVisibilityChanged(@NonNull IBinder token, boolean visible,
+ boolean removed) {
+ if (mImeTargetChangeListener != null) {
+ if (DEBUG_INPUT_METHOD) {
+ Slog.d(TAG, "onImeTargetOverlayVisibilityChanged, win=" + mWindowMap.get(token)
+ + "visible=" + visible + ", removed=" + removed);
+ }
+ mH.post(() -> mImeTargetChangeListener.onImeTargetOverlayVisibilityChanged(token,
+ visible, removed));
+ }
+ }
+
+ void dispatchImeInputTargetVisibilityChanged(@NonNull IBinder token, boolean visible,
+ boolean removed) {
+ if (mImeTargetChangeListener != null) {
+ if (DEBUG_INPUT_METHOD) {
+ Slog.d(TAG, "onImeInputTargetVisibilityChanged, win=" + mWindowMap.get(token)
+ + "visible=" + visible + ", removed=" + removed);
+ }
+ mH.post(() -> mImeTargetChangeListener.onImeInputTargetVisibilityChanged(token,
+ visible, removed));
+ }
+ }
+
@Override
public void setSwitchingUser(boolean switching) {
if (!checkCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
@@ -8262,13 +8306,19 @@
}
return null;
}
+
+ @Override
+ public void setInputMethodTargetChangeListener(@NonNull ImeTargetChangeListener listener) {
+ synchronized (mGlobalLock) {
+ mImeTargetChangeListener = listener;
+ }
+ }
}
private final class ImeTargetVisibilityPolicyImpl extends ImeTargetVisibilityPolicy {
- // TODO(b/258048231): Track IME visibility change in bugreport when invocations.
@Override
- public boolean showImeScreenShot(@NonNull IBinder imeTarget, int displayId) {
+ public boolean showImeScreenshot(@NonNull IBinder imeTarget, int displayId) {
synchronized (mGlobalLock) {
final WindowState imeTargetWindow = mWindowMap.get(imeTarget);
if (imeTargetWindow == null) {
@@ -8284,24 +8334,18 @@
return true;
}
}
-
- // TODO(b/258048231): Track IME visibility change in bugreport when invocations.
@Override
- public boolean updateImeParent(@NonNull IBinder imeTarget, int displayId) {
+ public boolean removeImeScreenshot(int displayId) {
synchronized (mGlobalLock) {
- final WindowState imeTargetWindow = mWindowMap.get(imeTarget);
- if (imeTargetWindow == null) {
- return false;
- }
final DisplayContent dc = mRoot.getDisplayContent(displayId);
if (dc == null) {
- Slog.w(TAG, "Invalid displayId:" + displayId + ", fail to update ime parent");
+ Slog.w(TAG, "Invalid displayId:" + displayId
+ + ", fail to remove ime screenshot");
return false;
}
-
- dc.updateImeParent();
- return true;
+ dc.removeImeSurfaceImmediately();
}
+ return true;
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index d1618e9..a299592 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -166,6 +166,7 @@
import static com.android.server.wm.WindowStateProto.IS_READY_FOR_DISPLAY;
import static com.android.server.wm.WindowStateProto.IS_VISIBLE;
import static com.android.server.wm.WindowStateProto.KEEP_CLEAR_AREAS;
+import static com.android.server.wm.WindowStateProto.MERGED_LOCAL_INSETS_SOURCES;
import static com.android.server.wm.WindowStateProto.PENDING_SEAMLESS_ROTATION;
import static com.android.server.wm.WindowStateProto.REMOVED;
import static com.android.server.wm.WindowStateProto.REMOVE_ON_EXIT;
@@ -353,6 +354,7 @@
// overlay window is hidden because the owning app is suspended
private boolean mHiddenWhileSuspended;
private boolean mAppOpVisibility = true;
+
boolean mPermanentlyHidden; // the window should never be shown again
// This is a non-system overlay window that is currently force hidden.
private boolean mForceHideNonSystemOverlayWindow;
@@ -2349,6 +2351,10 @@
}
super.removeImmediately();
+ if (isImeOverlayLayeringTarget()) {
+ mWmService.dispatchImeTargetOverlayVisibilityChanged(mClient.asBinder(),
+ false /* visible */, true /* removed */);
+ }
final DisplayContent dc = getDisplayContent();
if (isImeLayeringTarget()) {
// Remove the attached IME screenshot surface.
@@ -2359,6 +2365,8 @@
dc.computeImeTarget(true /* updateImeTarget */);
}
if (dc.getImeInputTarget() == this && !inRelaunchingActivity()) {
+ mWmService.dispatchImeInputTargetVisibilityChanged(mClient.asBinder(),
+ false /* visible */, true /* removed */);
dc.updateImeInputAndControlTarget(null);
}
@@ -4027,6 +4035,11 @@
for (Rect r : mUnrestrictedKeepClearAreas) {
r.dumpDebug(proto, UNRESTRICTED_KEEP_CLEAR_AREAS);
}
+ if (mMergedLocalInsetsSources != null) {
+ for (int i = 0; i < mMergedLocalInsetsSources.size(); ++i) {
+ mMergedLocalInsetsSources.valueAt(i).dumpDebug(proto, MERGED_LOCAL_INSETS_SOURCES);
+ }
+ }
proto.end(token);
}
@@ -5493,6 +5506,14 @@
return getDisplayContent().getImeTarget(IME_TARGET_LAYERING) == this;
}
+ /**
+ * Whether the window is non-focusable IME overlay layering target.
+ */
+ boolean isImeOverlayLayeringTarget() {
+ return isImeLayeringTarget()
+ && (mAttrs.flags & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
+ }
+
WindowState getImeLayeringTarget() {
final InsetsControlTarget target = getDisplayContent().getImeTarget(IME_TARGET_LAYERING);
return target != null ? target.getWindow() : null;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BundlePolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/BundlePolicySerializer.java
index ee73f8a..82f9aad 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BundlePolicySerializer.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BundlePolicySerializer.java
@@ -17,50 +17,28 @@
package com.android.server.devicepolicy;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.admin.BundlePolicyValue;
import android.app.admin.PackagePolicyKey;
import android.app.admin.PolicyKey;
import android.os.Bundle;
-import android.os.Environment;
import android.os.Parcelable;
-import android.util.AtomicFile;
-import android.util.Slog;
-import android.util.Xml;
+import android.util.Log;
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
-import libcore.io.IoUtils;
-
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Objects;
-// TODO(b/266704763): clean this up and stop creating separate files for each value, the code here
-// is copied from UserManagerService, however it doesn't currently handle setting different
-// restrictions for the same package in different users, it also will not remove the files for
-// outdated restrictions, this will all get fixed when we save it as part of the policies file
-// rather than in its own files.
final class BundlePolicySerializer extends PolicySerializer<Bundle> {
private static final String TAG = "BundlePolicySerializer";
- private static final String ATTR_FILE_NAME = "file-name";
-
- private static final String RESTRICTIONS_FILE_PREFIX = "AppRestrictions_";
- private static final String XML_SUFFIX = ".xml";
-
- private static final String TAG_RESTRICTIONS = "restrictions";
private static final String TAG_ENTRY = "entry";
private static final String TAG_VALUE = "value";
private static final String ATTR_KEY = "key";
@@ -83,62 +61,26 @@
throw new IllegalArgumentException("policyKey is not of type "
+ "PackagePolicyKey");
}
- String packageName = ((PackagePolicyKey) policyKey).getPackageName();
- String fileName = packageToRestrictionsFileName(packageName, value);
- writeApplicationRestrictionsLAr(fileName, value);
- serializer.attribute(/* namespace= */ null, ATTR_FILE_NAME, fileName);
+ writeBundle(value, serializer);
}
- @Nullable
@Override
BundlePolicyValue readFromXml(TypedXmlPullParser parser) {
- String fileName = parser.getAttributeValue(/* namespace= */ null, ATTR_FILE_NAME);
-
- return new BundlePolicyValue(readApplicationRestrictions(fileName));
- }
-
- private static String packageToRestrictionsFileName(String packageName, Bundle restrictions) {
- return RESTRICTIONS_FILE_PREFIX + packageName + Objects.hash(restrictions) + XML_SUFFIX;
- }
-
- @GuardedBy("mAppRestrictionsLock")
- private static Bundle readApplicationRestrictions(String fileName) {
- AtomicFile restrictionsFile =
- new AtomicFile(new File(Environment.getDataSystemDirectory(), fileName));
- return readApplicationRestrictions(restrictionsFile);
- }
-
- @VisibleForTesting
- @GuardedBy("mAppRestrictionsLock")
- static Bundle readApplicationRestrictions(AtomicFile restrictionsFile) {
- final Bundle restrictions = new Bundle();
- final ArrayList<String> values = new ArrayList<>();
- if (!restrictionsFile.getBaseFile().exists()) {
- return restrictions;
- }
-
- FileInputStream fis = null;
+ Bundle bundle = new Bundle();
+ ArrayList<String> values = new ArrayList<>();
try {
- fis = restrictionsFile.openRead();
- final TypedXmlPullParser parser = Xml.resolvePullParser(fis);
- XmlUtils.nextElement(parser);
- if (parser.getEventType() != XmlPullParser.START_TAG) {
- Slog.e(TAG, "Unable to read restrictions file "
- + restrictionsFile.getBaseFile());
- return restrictions;
+ final int outerDepth = parser.getDepth();
+ while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+ readBundle(bundle, values, parser);
}
- while (parser.next() != XmlPullParser.END_DOCUMENT) {
- readEntry(restrictions, values, parser);
- }
- } catch (IOException | XmlPullParserException e) {
- Slog.w(TAG, "Error parsing " + restrictionsFile.getBaseFile(), e);
- } finally {
- IoUtils.closeQuietly(fis);
+ } catch (XmlPullParserException | IOException e) {
+ Log.e(TAG, "Error parsing Bundle policy.", e);
+ return null;
}
- return restrictions;
+ return new BundlePolicyValue(bundle);
}
- private static void readEntry(Bundle restrictions, ArrayList<String> values,
+ private static void readBundle(Bundle restrictions, ArrayList<String> values,
TypedXmlPullParser parser) throws XmlPullParserException, IOException {
int type = parser.getEventType();
if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_ENTRY)) {
@@ -186,37 +128,11 @@
Bundle childBundle = new Bundle();
int outerDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
- readEntry(childBundle, values, parser);
+ readBundle(childBundle, values, parser);
}
return childBundle;
}
- private static void writeApplicationRestrictionsLAr(String fileName, Bundle restrictions) {
- AtomicFile restrictionsFile = new AtomicFile(
- new File(Environment.getDataSystemDirectory(), fileName));
- writeApplicationRestrictionsLAr(restrictions, restrictionsFile);
- }
-
- static void writeApplicationRestrictionsLAr(Bundle restrictions, AtomicFile restrictionsFile) {
- FileOutputStream fos = null;
- try {
- fos = restrictionsFile.startWrite();
- final TypedXmlSerializer serializer = Xml.resolveSerializer(fos);
- serializer.startDocument(null, true);
- serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-
- serializer.startTag(null, TAG_RESTRICTIONS);
- writeBundle(restrictions, serializer);
- serializer.endTag(null, TAG_RESTRICTIONS);
-
- serializer.endDocument();
- restrictionsFile.finishWrite(fos);
- } catch (Exception e) {
- restrictionsFile.failWrite(fos);
- Slog.e(TAG, "Error writing application restrictions list", e);
- }
- }
-
private static void writeBundle(Bundle restrictions, TypedXmlSerializer serializer)
throws IOException {
for (String key : restrictions.keySet()) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 18fcafa..7e5d5aa 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -11053,7 +11053,6 @@
}
if (!isPermissionCheckFlagEnabled() && !isPolicyEngineForFinanceFlagEnabled()) {
- // TODO: Figure out if something like this needs to be restored for policy engine
final ComponentName profileOwner = getProfileOwnerAsUser(userId);
if (profileOwner == null) {
return false;
@@ -11640,7 +11639,7 @@
caller.getUserId());
}
setBackwardsCompatibleAppRestrictions(
- packageName, restrictions, caller.getUserHandle());
+ caller, packageName, restrictions, caller.getUserHandle());
} else {
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
&& (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
@@ -11661,17 +11660,28 @@
}
/**
- * Set app restrictions in user manager to keep backwards compatibility for the old
- * getApplicationRestrictions API.
+ * Set app restrictions in user manager for DPC callers only to keep backwards compatibility
+ * for the old getApplicationRestrictions API.
*/
private void setBackwardsCompatibleAppRestrictions(
- String packageName, Bundle restrictions, UserHandle userHandle) {
- Bundle restrictionsToApply = restrictions == null || restrictions.isEmpty()
- ? getAppRestrictionsSetByAnyAdmin(packageName, userHandle)
- : restrictions;
- mInjector.binderWithCleanCallingIdentity(() -> {
- mUserManager.setApplicationRestrictions(packageName, restrictionsToApply, userHandle);
- });
+ CallerIdentity caller, String packageName, Bundle restrictions, UserHandle userHandle) {
+ if ((caller.hasAdminComponent() && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
+ || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_APP_RESTRICTIONS))) {
+ Bundle restrictionsToApply = restrictions == null || restrictions.isEmpty()
+ ? getAppRestrictionsSetByAnyAdmin(packageName, userHandle)
+ : restrictions;
+ mInjector.binderWithCleanCallingIdentity(() -> {
+ mUserManager.setApplicationRestrictions(packageName, restrictionsToApply,
+ userHandle);
+ });
+ } else {
+ // Notify package of changes via an intent - only sent to explicitly registered
+ // receivers. Sending here because For DPCs, this is being sent in UMS.
+ final Intent changeIntent = new Intent(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);
+ changeIntent.setPackage(packageName);
+ changeIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mContext.sendBroadcastAsUser(changeIntent, userHandle);
+ }
}
private Bundle getAppRestrictionsSetByAnyAdmin(String packageName, UserHandle userHandle) {
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
index 7d4f87d..a6ada4d 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/DefaultImeVisibilityApplierTest.java
@@ -38,6 +38,7 @@
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
+import android.view.Display;
import android.view.inputmethod.InputMethodManager;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -144,6 +145,26 @@
}
}
+ @Test
+ public void testShowImeScreenshot() {
+ synchronized (ImfLock.class) {
+ mVisibilityApplier.showImeScreenshot(mWindowToken, Display.DEFAULT_DISPLAY,
+ null /* statsToken */);
+ }
+
+ verify(mMockImeTargetVisibilityPolicy).showImeScreenshot(eq(mWindowToken),
+ eq(Display.DEFAULT_DISPLAY));
+ }
+
+ @Test
+ public void testRemoveImeScreenshot() {
+ synchronized (ImfLock.class) {
+ mVisibilityApplier.removeImeScreenshot(Display.DEFAULT_DISPLAY);
+ }
+
+ verify(mMockImeTargetVisibilityPolicy).removeImeScreenshot(eq(Display.DEFAULT_DISPLAY));
+ }
+
private InputBindResult startInputOrWindowGainedFocus(IBinder windowToken, int softInputMode) {
return mInputMethodManagerService.startInputOrWindowGainedFocus(
StartInputReason.WINDOW_FOCUS_GAIN /* startInputReason */,
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
index 2a256f2..3871e1d 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/ImeVisibilityStateComputerTest.java
@@ -24,7 +24,15 @@
import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.internal.inputmethod.SoftInputShowHideReason.HIDE_WHEN_INPUT_TARGET_INVISIBLE;
+import static com.android.internal.inputmethod.SoftInputShowHideReason.REMOVE_IME_SCREENSHOT_FROM_IMMS;
+import static com.android.internal.inputmethod.SoftInputShowHideReason.SHOW_IME_SCREENSHOT_FROM_IMMS;
import static com.android.server.inputmethod.ImeVisibilityStateComputer.ImeTargetWindowState;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.ImeVisibilityResult;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_HIDE_IME_EXPLICIT;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_REMOVE_IME_SNAPSHOT;
+import static com.android.server.inputmethod.ImeVisibilityStateComputer.STATE_SHOW_IME_SNAPSHOT;
import static com.android.server.inputmethod.InputMethodManagerService.FALLBACK_DISPLAY_ID;
import static com.android.server.inputmethod.InputMethodManagerService.ImeDisplayValidator;
@@ -37,11 +45,13 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.android.server.wm.ImeTargetChangeListener;
import com.android.server.wm.WindowManagerInternal;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
/**
* Test the behavior of {@link ImeVisibilityStateComputer} and {@link ImeVisibilityApplier} when
@@ -53,6 +63,7 @@
@RunWith(AndroidJUnit4.class)
public class ImeVisibilityStateComputerTest extends InputMethodManagerServiceTestBase {
private ImeVisibilityStateComputer mComputer;
+ private ImeTargetChangeListener mListener;
private int mImeDisplayPolicy = DISPLAY_IME_POLICY_LOCAL;
@Before
@@ -69,7 +80,11 @@
return displayId -> mImeDisplayPolicy;
}
};
+ ArgumentCaptor<ImeTargetChangeListener> captor = ArgumentCaptor.forClass(
+ ImeTargetChangeListener.class);
+ verify(mMockWindowManagerInternal).setInputMethodTargetChangeListener(captor.capture());
mComputer = new ImeVisibilityStateComputer(mInputMethodManagerService, injector);
+ mListener = captor.getValue();
}
@Test
@@ -196,6 +211,53 @@
lastState.isRequestedImeVisible());
}
+ @Test
+ public void testOnInteractiveChanged() {
+ mComputer.getOrCreateWindowState(mWindowToken);
+ // Precondition: ensure IME has shown before hiding request.
+ mComputer.requestImeVisibility(mWindowToken, true);
+ mComputer.setInputShown(true);
+
+ // No need any visibility change When initially shows IME on the device was interactive.
+ ImeVisibilityStateComputer.ImeVisibilityResult result = mComputer.onInteractiveChanged(
+ mWindowToken, true /* interactive */);
+ assertThat(result).isNull();
+
+ // Show the IME screenshot to capture the last IME visible state when the device inactive.
+ result = mComputer.onInteractiveChanged(mWindowToken, false /* interactive */);
+ assertThat(result).isNotNull();
+ assertThat(result.getState()).isEqualTo(STATE_SHOW_IME_SNAPSHOT);
+ assertThat(result.getReason()).isEqualTo(SHOW_IME_SCREENSHOT_FROM_IMMS);
+
+ // Remove the IME screenshot when the device became interactive again.
+ result = mComputer.onInteractiveChanged(mWindowToken, true /* interactive */);
+ assertThat(result).isNotNull();
+ assertThat(result.getState()).isEqualTo(STATE_REMOVE_IME_SNAPSHOT);
+ assertThat(result.getReason()).isEqualTo(REMOVE_IME_SCREENSHOT_FROM_IMMS);
+ }
+
+ @Test
+ public void testOnApplyImeVisibilityFromComputer() {
+ final IBinder testImeTargetOverlay = new Binder();
+ final IBinder testImeInputTarget = new Binder();
+
+ // Simulate a test IME layering target overlay fully occluded the IME input target.
+ mListener.onImeTargetOverlayVisibilityChanged(testImeTargetOverlay, true, false);
+ mListener.onImeInputTargetVisibilityChanged(testImeInputTarget, false, false);
+ final ArgumentCaptor<IBinder> targetCaptor = ArgumentCaptor.forClass(IBinder.class);
+ final ArgumentCaptor<ImeVisibilityResult> resultCaptor = ArgumentCaptor.forClass(
+ ImeVisibilityResult.class);
+ verify(mInputMethodManagerService).onApplyImeVisibilityFromComputer(targetCaptor.capture(),
+ resultCaptor.capture());
+ final IBinder imeInputTarget = targetCaptor.getValue();
+ final ImeVisibilityResult result = resultCaptor.getValue();
+
+ // Verify the computer will callback hiding IME state to IMMS.
+ assertThat(imeInputTarget).isEqualTo(testImeInputTarget);
+ assertThat(result.getState()).isEqualTo(STATE_HIDE_IME_EXPLICIT);
+ assertThat(result.getReason()).isEqualTo(HIDE_WHEN_INPUT_TARGET_INVISIBLE);
+ }
+
private ImeTargetWindowState initImeTargetWindowState(IBinder windowToken) {
final ImeTargetWindowState state = new ImeTargetWindowState(SOFT_INPUT_STATE_UNCHANGED,
0, true, true, true);
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
index 90691a7..c80ecbf 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
@@ -62,6 +62,7 @@
import com.android.server.SystemService;
import com.android.server.input.InputManagerInternal;
import com.android.server.pm.UserManagerInternal;
+import com.android.server.wm.ImeTargetVisibilityPolicy;
import com.android.server.wm.WindowManagerInternal;
import org.junit.After;
@@ -113,6 +114,7 @@
@Mock protected IInputMethod mMockInputMethod;
@Mock protected IBinder mMockInputMethodBinder;
@Mock protected IInputManager mMockIInputManager;
+ @Mock protected ImeTargetVisibilityPolicy mMockImeTargetVisibilityPolicy;
protected Context mContext;
protected MockitoSession mMockingSession;
@@ -166,6 +168,8 @@
.when(() -> LocalServices.getService(DisplayManagerInternal.class));
doReturn(mMockUserManagerInternal)
.when(() -> LocalServices.getService(UserManagerInternal.class));
+ doReturn(mMockImeTargetVisibilityPolicy)
+ .when(() -> LocalServices.getService(ImeTargetVisibilityPolicy.class));
doReturn(mMockIInputMethodManager)
.when(() -> ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE));
doReturn(mMockIPlatformCompat)
@@ -218,6 +222,7 @@
false);
mInputMethodManagerService = new InputMethodManagerService(mContext, mServiceThread,
mMockInputMethodBindingController);
+ spyOn(mInputMethodManagerService);
// Start a InputMethodManagerService.Lifecycle to publish and manage the lifecycle of
// InputMethodManagerService, which is closer to the real situation.
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/HighBrightnessModeMetadataMapperTest.java b/services/tests/mockingservicestests/src/com/android/server/display/HighBrightnessModeMetadataMapperTest.java
new file mode 100644
index 0000000..d9fbba5
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/display/HighBrightnessModeMetadataMapperTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 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.display;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class HighBrightnessModeMetadataMapperTest {
+
+ private HighBrightnessModeMetadataMapper mHighBrightnessModeMetadataMapper;
+
+ @Before
+ public void setUp() {
+ mHighBrightnessModeMetadataMapper = new HighBrightnessModeMetadataMapper();
+ }
+
+ @Test
+ public void testGetHighBrightnessModeMetadata() {
+ // Display device is null
+ final LogicalDisplay display = mock(LogicalDisplay.class);
+ when(display.getPrimaryDisplayDeviceLocked()).thenReturn(null);
+ assertNull(mHighBrightnessModeMetadataMapper.getHighBrightnessModeMetadataLocked(display));
+
+ // No HBM metadata stored for this display yet
+ final DisplayDevice device = mock(DisplayDevice.class);
+ when(display.getPrimaryDisplayDeviceLocked()).thenReturn(device);
+ HighBrightnessModeMetadata hbmMetadata =
+ mHighBrightnessModeMetadataMapper.getHighBrightnessModeMetadataLocked(display);
+ assertTrue(hbmMetadata.getHbmEventQueue().isEmpty());
+ assertTrue(hbmMetadata.getRunningStartTimeMillis() < 0);
+
+ // Modify the metadata
+ long startTimeMillis = 100;
+ long endTimeMillis = 200;
+ long setTime = 300;
+ hbmMetadata.addHbmEvent(new HbmEvent(startTimeMillis, endTimeMillis));
+ hbmMetadata.setRunningStartTimeMillis(setTime);
+ hbmMetadata =
+ mHighBrightnessModeMetadataMapper.getHighBrightnessModeMetadataLocked(display);
+ assertEquals(1, hbmMetadata.getHbmEventQueue().size());
+ assertEquals(startTimeMillis,
+ hbmMetadata.getHbmEventQueue().getFirst().getStartTimeMillis());
+ assertEquals(endTimeMillis, hbmMetadata.getHbmEventQueue().getFirst().getEndTimeMillis());
+ assertEquals(setTime, hbmMetadata.getRunningStartTimeMillis());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index aca96ad..aad373f 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -445,14 +445,14 @@
+ " <library \n"
+ " name=\"foo\"\n"
+ " file=\"" + mFooJar + "\"\n"
- + " on-bootclasspath-before=\"Q\"\n"
+ + " on-bootclasspath-before=\"A\"\n"
+ " on-bootclasspath-since=\"W\"\n"
+ " />\n\n"
+ " </permissions>";
parseSharedLibraries(contents);
assertFooIsOnlySharedLibrary();
SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
- assertThat(entry.onBootclasspathBefore).isEqualTo("Q");
+ assertThat(entry.onBootclasspathBefore).isEqualTo("A");
assertThat(entry.onBootclasspathSince).isEqualTo("W");
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
index 90d1488..4406d83 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
@@ -71,10 +71,10 @@
import android.testing.TestableContext;
import android.util.ArraySet;
import android.util.Pair;
-import com.android.modules.utils.TypedXmlPullParser;
-import com.android.modules.utils.TypedXmlSerializer;
import android.util.Xml;
+import com.android.modules.utils.TypedXmlPullParser;
+import com.android.modules.utils.TypedXmlSerializer;
import com.android.server.UiServiceTestCase;
import com.google.common.collect.ImmutableList;
@@ -92,6 +92,7 @@
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
public class NotificationListenersTest extends UiServiceTestCase {
@@ -626,6 +627,58 @@
.onNotificationChannelGroupModification(anyString(), any(), any(), anyInt());
}
+ @Test
+ public void testNotificationListenerFilter_threadSafety() throws Exception {
+ testThreadSafety(() -> {
+ mListeners.setNotificationListenerFilter(
+ new Pair<>(new ComponentName("pkg1", "cls1"), 0),
+ new NotificationListenerFilter());
+ mListeners.setNotificationListenerFilter(
+ new Pair<>(new ComponentName("pkg2", "cls2"), 10),
+ new NotificationListenerFilter());
+ mListeners.setNotificationListenerFilter(
+ new Pair<>(new ComponentName("pkg3", "cls3"), 11),
+ new NotificationListenerFilter());
+
+ mListeners.onUserRemoved(10);
+ mListeners.onPackagesChanged(true, new String[]{"pkg1", "pkg2"}, new int[]{0, 0});
+ }, 20, 50);
+ }
+
+ /**
+ * Helper method to test the thread safety of some operations.
+ *
+ * <p>Runs the supplied {@code operationToTest}, {@code nRunsPerThread} times,
+ * concurrently using {@code nThreads} threads, and waits for all of them to finish.
+ */
+ private static void testThreadSafety(Runnable operationToTest, int nThreads,
+ int nRunsPerThread) throws InterruptedException {
+ final CountDownLatch startLatch = new CountDownLatch(1);
+ final CountDownLatch doneLatch = new CountDownLatch(nThreads);
+
+ for (int i = 0; i < nThreads; i++) {
+ Runnable threadRunnable = () -> {
+ try {
+ startLatch.await();
+ for (int j = 0; j < nRunsPerThread; j++) {
+ operationToTest.run();
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } finally {
+ doneLatch.countDown();
+ }
+ };
+ new Thread(threadRunnable, "Test Thread #" + i).start();
+ }
+
+ // Ready set go
+ startLatch.countDown();
+
+ // Wait for all test threads to be done.
+ doneLatch.await();
+ }
+
private ManagedServices.ManagedServiceInfo getParcelingListener(
final NotificationChannelGroup toParcel)
throws RemoteException {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 9cfdaa7..dd9f3cb 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -5447,6 +5447,29 @@
}
@Test
+ public void testVisitUris_callStyle() {
+ Icon personIcon = Icon.createWithContentUri("content://media/person");
+ Icon verificationIcon = Icon.createWithContentUri("content://media/verification");
+ Person callingPerson = new Person.Builder().setName("Someone")
+ .setIcon(personIcon)
+ .build();
+ PendingIntent hangUpIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
+ PendingIntent.FLAG_IMMUTABLE);
+ Notification n = new Notification.Builder(mContext, "a")
+ .setStyle(Notification.CallStyle.forOngoingCall(callingPerson, hangUpIntent)
+ .setVerificationIcon(verificationIcon))
+ .setContentTitle("Calling...")
+ .setSmallIcon(android.R.drawable.sym_def_app_icon)
+ .build();
+
+ Consumer<Uri> visitor = (Consumer<Uri>) spy(Consumer.class);
+ n.visitUris(visitor);
+
+ verify(visitor, times(1)).accept(eq(personIcon.getUri()));
+ verify(visitor, times(1)).accept(eq(verificationIcon.getUri()));
+ }
+
+ @Test
public void testVisitUris_audioContentsString() throws Exception {
final Uri audioContents = Uri.parse("content://com.example/audio");
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 4e001fe..37c4b37 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -28,6 +28,7 @@
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
@@ -501,6 +502,12 @@
onActivityLaunched(mTrampolineActivity);
mActivityMetricsLogger.notifyActivityLaunching(mTopActivity.intent,
mTrampolineActivity /* caller */, mTrampolineActivity.getUid());
+
+ // Simulate a corner case that the trampoline activity is removed by CLEAR_TASK.
+ // The 2 launch events can still be coalesced to one by matching the uid.
+ mTrampolineActivity.takeFromHistory();
+ assertNull(mTrampolineActivity.getTask());
+
notifyActivityLaunched(START_SUCCESS, mTopActivity);
transitToDrawnAndVerifyOnLaunchFinished(mTopActivity);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 8f2b470..0033e3e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2399,7 +2399,10 @@
holder.addConnection(connection);
assertTrue(holder.isActivityVisible());
final int[] count = new int[1];
- final Consumer<Object> c = conn -> count[0]++;
+ final Consumer<Object> c = conn -> {
+ count[0]++;
+ assertFalse(Thread.holdsLock(activity));
+ };
holder.forEachConnection(c);
assertEquals(1, count[0]);
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index 17ae215..6d7f2c1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -232,11 +232,36 @@
IOnBackInvokedCallback callback = createOnBackInvokedCallback();
window.setOnBackInvokedCallbackInfo(
- new OnBackInvokedCallbackInfo(callback, OnBackInvokedDispatcher.PRIORITY_DEFAULT));
+ new OnBackInvokedCallbackInfo(
+ callback,
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT,
+ /* isAnimationCallback = */ false));
BackNavigationInfo backNavigationInfo = startBackNavigation();
assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull();
assertThat(backNavigationInfo.getType()).isEqualTo(BackNavigationInfo.TYPE_CALLBACK);
+ assertThat(backNavigationInfo.isAnimationCallback()).isEqualTo(false);
+ assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(callback);
+ }
+
+ @Test
+ public void backInfoWithAnimationCallback() {
+ WindowState window = createWindow(null, WindowManager.LayoutParams.TYPE_WALLPAPER,
+ "Wallpaper");
+ addToWindowMap(window, true);
+ makeWindowVisibleAndDrawn(window);
+
+ IOnBackInvokedCallback callback = createOnBackInvokedCallback();
+ window.setOnBackInvokedCallbackInfo(
+ new OnBackInvokedCallbackInfo(
+ callback,
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT,
+ /* isAnimationCallback = */ true));
+
+ BackNavigationInfo backNavigationInfo = startBackNavigation();
+ assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull();
+ assertThat(backNavigationInfo.getType()).isEqualTo(BackNavigationInfo.TYPE_CALLBACK);
+ assertThat(backNavigationInfo.isAnimationCallback()).isEqualTo(true);
assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(callback);
}
@@ -364,7 +389,10 @@
IOnBackInvokedCallback callback = createOnBackInvokedCallback();
window.setOnBackInvokedCallbackInfo(
- new OnBackInvokedCallbackInfo(callback, OnBackInvokedDispatcher.PRIORITY_DEFAULT));
+ new OnBackInvokedCallbackInfo(
+ callback,
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT,
+ /* isAnimationCallback = */ false));
BackNavigationInfo backNavigationInfo = startBackNavigation();
assertThat(backNavigationInfo).isNull();
@@ -450,14 +478,20 @@
private IOnBackInvokedCallback withSystemCallback(Task task) {
IOnBackInvokedCallback callback = createOnBackInvokedCallback();
task.getTopMostActivity().getTopChild().setOnBackInvokedCallbackInfo(
- new OnBackInvokedCallbackInfo(callback, OnBackInvokedDispatcher.PRIORITY_SYSTEM));
+ new OnBackInvokedCallbackInfo(
+ callback,
+ OnBackInvokedDispatcher.PRIORITY_SYSTEM,
+ /* isAnimationCallback = */ false));
return callback;
}
private IOnBackInvokedCallback withAppCallback(Task task) {
IOnBackInvokedCallback callback = createOnBackInvokedCallback();
task.getTopMostActivity().getTopChild().setOnBackInvokedCallbackInfo(
- new OnBackInvokedCallbackInfo(callback, OnBackInvokedDispatcher.PRIORITY_DEFAULT));
+ new OnBackInvokedCallbackInfo(
+ callback,
+ OnBackInvokedDispatcher.PRIORITY_DEFAULT,
+ /* isAnimationCallback = */ false));
return callback;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index 2065540..a8fc25f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -84,12 +84,14 @@
}
@Test
- public void testControlsForDispatch_multiWindowTaskVisible() {
+ public void testControlsForDispatch_adjacentTasksVisible() {
addStatusBar();
addNavigationBar();
- final WindowState win = createWindow(null, WINDOWING_MODE_MULTI_WINDOW,
- ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app");
+ final Task task1 = createTask(mDisplayContent);
+ final Task task2 = createTask(mDisplayContent);
+ task1.setAdjacentTaskFragment(task2);
+ final WindowState win = createAppWindow(task1, WINDOWING_MODE_MULTI_WINDOW, "app");
final InsetsSourceControl[] controls = addWindowAndGetControlsForDispatch(win);
// The app must not control any system bars.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index 49d8da1..9d597b1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -586,6 +586,15 @@
// Making the activity0 be the focused activity and ensure the focused app is updated.
activity0.moveFocusableActivityToTop("test");
assertEquals(activity0, mDisplayContent.mFocusedApp);
+
+ // Moving activity1 to top and make both the two activities resumed.
+ activity1.moveFocusableActivityToTop("test");
+ activity0.setState(RESUMED, "test");
+ activity1.setState(RESUMED, "test");
+
+ // Verifies that the focus app can be updated to an Activity in the adjacent TF
+ mAtm.setFocusedTask(task.mTaskId, activity0);
+ assertEquals(activity0, mDisplayContent.mFocusedApp);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 766e74c..460a603 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -20,6 +20,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.InsetsSource.ID_IME;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_270;
@@ -85,17 +86,25 @@
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.InputConfig;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
+import android.util.MergedConfiguration;
import android.view.Gravity;
+import android.view.IWindow;
+import android.view.IWindowSessionCallback;
import android.view.InputWindowHandle;
import android.view.InsetsSource;
+import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.SurfaceControl;
+import android.view.View;
+import android.view.WindowInsets;
import android.view.WindowManager;
+import android.window.ClientWindowFrames;
import android.window.ITaskFragmentOrganizer;
import android.window.TaskFragmentOrganizer;
@@ -1280,4 +1289,118 @@
assertEquals(new ArraySet(Arrays.asList(expectedArea1, expectedArea2)),
new ArraySet(unrestrictedKeepClearAreas));
}
+
+ @Test
+ public void testImeTargetChangeListener_OnImeInputTargetVisibilityChanged() {
+ final TestImeTargetChangeListener listener = new TestImeTargetChangeListener();
+ mWm.mImeTargetChangeListener = listener;
+
+ final WindowState imeTarget = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
+ createActivityRecord(mDisplayContent), "imeTarget");
+
+ imeTarget.mActivityRecord.setVisibleRequested(true);
+ makeWindowVisible(imeTarget);
+ mDisplayContent.setImeInputTarget(imeTarget);
+ waitHandlerIdle(mWm.mH);
+
+ assertThat(listener.mImeTargetToken).isEqualTo(imeTarget.mClient.asBinder());
+ assertThat(listener.mIsRemoved).isFalse();
+ assertThat(listener.mIsVisibleForImeInputTarget).isTrue();
+
+ imeTarget.mActivityRecord.setVisibleRequested(false);
+ waitHandlerIdle(mWm.mH);
+
+ assertThat(listener.mImeTargetToken).isEqualTo(imeTarget.mClient.asBinder());
+ assertThat(listener.mIsRemoved).isFalse();
+ assertThat(listener.mIsVisibleForImeInputTarget).isFalse();
+
+ imeTarget.removeImmediately();
+ assertThat(listener.mImeTargetToken).isEqualTo(imeTarget.mClient.asBinder());
+ assertThat(listener.mIsRemoved).isTrue();
+ assertThat(listener.mIsVisibleForImeInputTarget).isFalse();
+ }
+
+ @SetupWindows(addWindows = {W_INPUT_METHOD})
+ @Test
+ public void testImeTargetChangeListener_OnImeTargetOverlayVisibilityChanged() {
+ final TestImeTargetChangeListener listener = new TestImeTargetChangeListener();
+ mWm.mImeTargetChangeListener = listener;
+
+ // Scenario 1: test addWindow/relayoutWindow to add Ime layering overlay window as visible.
+ final WindowToken windowToken = createTestWindowToken(TYPE_APPLICATION_OVERLAY,
+ mDisplayContent);
+ final IWindow client = new TestIWindow();
+ final Session session = new Session(mWm, new IWindowSessionCallback.Stub() {
+ @Override
+ public void onAnimatorScaleChanged(float v) throws RemoteException {
+
+ }
+ });
+ final ClientWindowFrames outFrames = new ClientWindowFrames();
+ final MergedConfiguration outConfig = new MergedConfiguration();
+ final SurfaceControl outSurfaceControl = new SurfaceControl();
+ final InsetsState outInsetsState = new InsetsState();
+ final InsetsSourceControl.Array outControls = new InsetsSourceControl.Array();
+ final Bundle outBundle = new Bundle();
+ final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+ TYPE_APPLICATION_OVERLAY);
+ params.setTitle("imeLayeringTargetOverlay");
+ params.token = windowToken.token;
+ params.flags = FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM;
+
+ mWm.addWindow(session, client, params, View.VISIBLE, DEFAULT_DISPLAY,
+ 0 /* userUd */, WindowInsets.Type.defaultVisible(), null, new InsetsState(),
+ new InsetsSourceControl.Array(), new Rect(), new float[1]);
+ mWm.relayoutWindow(session, client, params, 100, 200, View.VISIBLE, 0, 0, 0,
+ outFrames, outConfig, outSurfaceControl, outInsetsState, outControls, outBundle);
+ waitHandlerIdle(mWm.mH);
+
+ final WindowState imeLayeringTargetOverlay = mDisplayContent.getWindow(
+ w -> w.mClient.asBinder() == client.asBinder());
+ assertThat(imeLayeringTargetOverlay.isVisible()).isTrue();
+ assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder());
+ assertThat(listener.mIsRemoved).isFalse();
+ assertThat(listener.mIsVisibleForImeTargetOverlay).isTrue();
+
+ // Scenario 2: test relayoutWindow to let the Ime layering target overlay window invisible.
+ mWm.relayoutWindow(session, client, params, 100, 200, View.GONE, 0, 0, 0,
+ outFrames, outConfig, outSurfaceControl, outInsetsState, outControls, outBundle);
+ waitHandlerIdle(mWm.mH);
+
+ assertThat(imeLayeringTargetOverlay.isVisible()).isFalse();
+ assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder());
+ assertThat(listener.mIsRemoved).isFalse();
+ assertThat(listener.mIsVisibleForImeTargetOverlay).isFalse();
+
+ // Scenario 3: test removeWindow to remove the Ime layering target overlay window.
+ mWm.removeWindow(session, client);
+ waitHandlerIdle(mWm.mH);
+
+ assertThat(listener.mImeTargetToken).isEqualTo(client.asBinder());
+ assertThat(listener.mIsRemoved).isTrue();
+ assertThat(listener.mIsVisibleForImeTargetOverlay).isFalse();
+ }
+
+ private static class TestImeTargetChangeListener implements ImeTargetChangeListener {
+ private IBinder mImeTargetToken;
+ private boolean mIsRemoved;
+ private boolean mIsVisibleForImeTargetOverlay;
+ private boolean mIsVisibleForImeInputTarget;
+
+ @Override
+ public void onImeTargetOverlayVisibilityChanged(IBinder overlayWindowToken, boolean visible,
+ boolean removed) {
+ mImeTargetToken = overlayWindowToken;
+ mIsVisibleForImeTargetOverlay = visible;
+ mIsRemoved = removed;
+ }
+
+ @Override
+ public void onImeInputTargetVisibilityChanged(IBinder imeInputTarget,
+ boolean visibleRequested, boolean removed) {
+ mImeTargetToken = imeInputTarget;
+ mIsVisibleForImeInputTarget = visibleRequested;
+ mIsRemoved = removed;
+ }
+ }
}
diff --git a/telephony/OWNERS b/telephony/OWNERS
index 025869d..3158ad8 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -11,12 +11,6 @@
amruthr@google.com
sasindran@google.com
-# Temporarily reduced the owner during refactoring
-per-file SubscriptionManager.java=set noparent
-per-file SubscriptionManager.java=jackyu@google.com,amruthr@google.com
-per-file SubscriptionInfo.java=set noparent
-per-file SubscriptionInfo.java=jackyu@google.com,amruthr@google.com
-
# Requiring TL ownership for new carrier config keys.
per-file CarrierConfigManager.java=set noparent
per-file CarrierConfigManager.java=amruthr@google.com,tgunn@google.com,rgreenwalt@google.com,satk@google.com
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 905a90c..caafce2 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -331,8 +331,8 @@
* Same as {@link #checkCallingOrSelfReadSubscriberIdentifiers(Context, int, String, String,
* String)} except this allows an additional parameter reportFailure. Caller may not want to
* report a failure when this is an internal/intermediate check, for example,
- * SubscriptionController calls this with an INVALID_SUBID to check if caller has the required
- * permissions to bypass carrier privilege checks.
+ * SubscriptionManagerService calls this with an INVALID_SUBID to check if caller has the
+ * required permissions to bypass carrier privilege checks.
* @param reportFailure Indicates if failure should be reported.
*/
public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 559faf9..64e4356 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -91,8 +91,7 @@
import java.util.stream.Collectors;
/**
- * SubscriptionManager is the application interface to SubscriptionController
- * and provides information about the current Telephony Subscriptions.
+ * Subscription manager provides the mobile subscription information.
*/
@SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
@@ -119,13 +118,12 @@
public static final int DEFAULT_SUBSCRIPTION_ID = Integer.MAX_VALUE;
/**
- * Indicates the caller wants the default phone id.
- * Used in SubscriptionController and Phone but do we really need it???
+ * Indicates the default phone id.
* @hide
*/
public static final int DEFAULT_PHONE_INDEX = Integer.MAX_VALUE;
- /** Indicates the caller wants the default slot id. NOT used remove? */
+ /** Indicates the default slot index. */
/** @hide */
public static final int DEFAULT_SIM_SLOT_INDEX = Integer.MAX_VALUE;
@@ -141,29 +139,10 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final Uri CONTENT_URI = SimInfo.CONTENT_URI;
- private static final String CACHE_KEY_DEFAULT_SUB_ID_PROPERTY =
- "cache_key.telephony.get_default_sub_id";
-
- private static final String CACHE_KEY_DEFAULT_DATA_SUB_ID_PROPERTY =
- "cache_key.telephony.get_default_data_sub_id";
-
- private static final String CACHE_KEY_DEFAULT_SMS_SUB_ID_PROPERTY =
- "cache_key.telephony.get_default_sms_sub_id";
-
- private static final String CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY =
- "cache_key.telephony.get_active_data_sub_id";
-
- private static final String CACHE_KEY_SLOT_INDEX_PROPERTY =
- "cache_key.telephony.get_slot_index";
-
/** The IPC cache key shared by all subscription manager service cacheable properties. */
private static final String CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY =
"cache_key.telephony.subscription_manager_service";
- /** The temporarily cache key to indicate whether subscription manager service is enabled. */
- private static final String CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY =
- "cache_key.telephony.subscription_manager_service_enabled";
-
/** @hide */
public static final String GET_SIM_SPECIFIC_SETTINGS_METHOD_NAME = "getSimSpecificSettings";
@@ -273,83 +252,41 @@
}
}
- private static VoidPropertyInvalidatedCache<Integer> sDefaultSubIdCache =
- new VoidPropertyInvalidatedCache<>(ISub::getDefaultSubId,
- CACHE_KEY_DEFAULT_SUB_ID_PROPERTY,
- INVALID_SUBSCRIPTION_ID);
-
private static VoidPropertyInvalidatedCache<Integer> sGetDefaultSubIdCache =
new VoidPropertyInvalidatedCache<>(ISub::getDefaultSubId,
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_SUBSCRIPTION_ID);
- private static VoidPropertyInvalidatedCache<Integer> sDefaultDataSubIdCache =
- new VoidPropertyInvalidatedCache<>(ISub::getDefaultDataSubId,
- CACHE_KEY_DEFAULT_DATA_SUB_ID_PROPERTY,
- INVALID_SUBSCRIPTION_ID);
-
private static VoidPropertyInvalidatedCache<Integer> sGetDefaultDataSubIdCache =
new VoidPropertyInvalidatedCache<>(ISub::getDefaultDataSubId,
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_SUBSCRIPTION_ID);
- private static VoidPropertyInvalidatedCache<Integer> sDefaultSmsSubIdCache =
- new VoidPropertyInvalidatedCache<>(ISub::getDefaultSmsSubId,
- CACHE_KEY_DEFAULT_SMS_SUB_ID_PROPERTY,
- INVALID_SUBSCRIPTION_ID);
-
private static VoidPropertyInvalidatedCache<Integer> sGetDefaultSmsSubIdCache =
new VoidPropertyInvalidatedCache<>(ISub::getDefaultSmsSubId,
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_SUBSCRIPTION_ID);
- private static VoidPropertyInvalidatedCache<Integer> sActiveDataSubIdCache =
- new VoidPropertyInvalidatedCache<>(ISub::getActiveDataSubscriptionId,
- CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY,
- INVALID_SUBSCRIPTION_ID);
-
private static VoidPropertyInvalidatedCache<Integer> sGetActiveDataSubscriptionIdCache =
new VoidPropertyInvalidatedCache<>(ISub::getActiveDataSubscriptionId,
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_SUBSCRIPTION_ID);
- private static IntegerPropertyInvalidatedCache<Integer> sSlotIndexCache =
- new IntegerPropertyInvalidatedCache<>(ISub::getSlotIndex,
- CACHE_KEY_SLOT_INDEX_PROPERTY,
- INVALID_SIM_SLOT_INDEX);
-
private static IntegerPropertyInvalidatedCache<Integer> sGetSlotIndexCache =
new IntegerPropertyInvalidatedCache<>(ISub::getSlotIndex,
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_SIM_SLOT_INDEX);
- private static IntegerPropertyInvalidatedCache<Integer> sSubIdCache =
- new IntegerPropertyInvalidatedCache<>(ISub::getSubId,
- CACHE_KEY_SLOT_INDEX_PROPERTY,
- INVALID_SUBSCRIPTION_ID);
-
private static IntegerPropertyInvalidatedCache<Integer> sGetSubIdCache =
new IntegerPropertyInvalidatedCache<>(ISub::getSubId,
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_SUBSCRIPTION_ID);
- /** Cache depends on getDefaultSubId, so we use the defaultSubId cache key */
- private static IntegerPropertyInvalidatedCache<Integer> sPhoneIdCache =
- new IntegerPropertyInvalidatedCache<>(ISub::getPhoneId,
- CACHE_KEY_DEFAULT_SUB_ID_PROPERTY,
- INVALID_PHONE_INDEX);
-
private static IntegerPropertyInvalidatedCache<Integer> sGetPhoneIdCache =
new IntegerPropertyInvalidatedCache<>(ISub::getPhoneId,
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_PHONE_INDEX);
- //TODO: Removed before U AOSP public release.
- private static VoidPropertyInvalidatedCache<Boolean> sIsSubscriptionManagerServiceEnabled =
- new VoidPropertyInvalidatedCache<>(ISub::isSubscriptionManagerServiceEnabled,
- CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY,
- false);
-
/**
* Generates a content {@link Uri} used to receive updates on simInfo change
* on the given subscriptionId
@@ -1455,17 +1392,6 @@
mContext = context;
}
- /**
- * @return {@code true} if the new subscription manager service is used. This is temporary and
- * will be removed before Android 14 release.
- *
- * @hide
- */
- //TODO: Removed before U AOSP public release.
- public static boolean isSubscriptionManagerServiceEnabled() {
- return sIsSubscriptionManagerServiceEnabled.query(null);
- }
-
private NetworkPolicyManager getNetworkPolicyManager() {
return (NetworkPolicyManager) mContext
.getSystemService(Context.NETWORK_POLICY_SERVICE);
@@ -1520,7 +1446,7 @@
+ " listener=" + listener);
}
// We use the TelephonyRegistry as it runs in the system and thus is always
- // available. Where as SubscriptionController could crash and not be available
+ // available.
TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
if (telephonyRegistryManager != null) {
@@ -1550,7 +1476,7 @@
+ " listener=" + listener);
}
// We use the TelephonyRegistry as it runs in the system and thus is always
- // available where as SubscriptionController could crash and not be available
+ // available.
TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
if (telephonyRegistryManager != null) {
@@ -1608,7 +1534,7 @@
}
// We use the TelephonyRegistry as it runs in the system and thus is always
- // available where as SubscriptionController could crash and not be available
+ // available.
TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
if (telephonyRegistryManager != null) {
@@ -2149,9 +2075,9 @@
Log.e(LOG_TAG, "[removeSubscriptionInfoRecord]- ISub service is null");
return;
}
- int result = iSub.removeSubInfo(uniqueId, subscriptionType);
- if (result < 0) {
- Log.e(LOG_TAG, "Removal of subscription didn't succeed: error = " + result);
+ boolean result = iSub.removeSubInfo(uniqueId, subscriptionType);
+ if (!result) {
+ Log.e(LOG_TAG, "Removal of subscription didn't succeed");
} else {
logd("successfully removed subscription");
}
@@ -2236,8 +2162,7 @@
* subscriptionId doesn't have an associated slot index.
*/
public static int getSlotIndex(int subscriptionId) {
- if (isSubscriptionManagerServiceEnabled()) return sGetSlotIndexCache.query(subscriptionId);
- return sSlotIndexCache.query(subscriptionId);
+ return sGetSlotIndexCache.query(subscriptionId);
}
/**
@@ -2294,15 +2219,13 @@
return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
- if (isSubscriptionManagerServiceEnabled()) return sGetSubIdCache.query(slotIndex);
- return sSubIdCache.query(slotIndex);
+ return sGetSubIdCache.query(slotIndex);
}
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public static int getPhoneId(int subId) {
- if (isSubscriptionManagerServiceEnabled()) return sGetPhoneIdCache.query(subId);
- return sPhoneIdCache.query(subId);
+ return sGetPhoneIdCache.query(subId);
}
private static void logd(String msg) {
@@ -2323,8 +2246,7 @@
* @return the "system" default subscription id.
*/
public static int getDefaultSubscriptionId() {
- if (isSubscriptionManagerServiceEnabled()) return sGetDefaultSubIdCache.query(null);
- return sDefaultSubIdCache.query(null);
+ return sGetDefaultSubIdCache.query(null);
}
/**
@@ -2412,8 +2334,7 @@
* @return the default SMS subscription Id.
*/
public static int getDefaultSmsSubscriptionId() {
- if (isSubscriptionManagerServiceEnabled()) return sGetDefaultSmsSubIdCache.query(null);
- return sDefaultSmsSubIdCache.query(null);
+ return sGetDefaultSmsSubIdCache.query(null);
}
/**
@@ -2447,8 +2368,7 @@
* @return the default data subscription Id.
*/
public static int getDefaultDataSubscriptionId() {
- if (isSubscriptionManagerServiceEnabled()) return sGetDefaultDataSubIdCache.query(null);
- return sDefaultDataSubIdCache.query(null);
+ return sGetDefaultDataSubIdCache.query(null);
}
/**
@@ -3912,10 +3832,7 @@
* @see TelephonyCallback.ActiveDataSubscriptionIdListener
*/
public static int getActiveDataSubscriptionId() {
- if (isSubscriptionManagerServiceEnabled()) {
- return sGetActiveDataSubscriptionIdCache.query(null);
- }
- return sActiveDataSubIdCache.query(null);
+ return sGetActiveDataSubscriptionIdCache.query(null);
}
/**
@@ -3934,61 +3851,16 @@
}
/** @hide */
- public static void invalidateDefaultSubIdCaches() {
- PropertyInvalidatedCache.invalidateCache(CACHE_KEY_DEFAULT_SUB_ID_PROPERTY);
- }
-
- /** @hide */
- public static void invalidateDefaultDataSubIdCaches() {
- PropertyInvalidatedCache.invalidateCache(CACHE_KEY_DEFAULT_DATA_SUB_ID_PROPERTY);
- }
-
- /** @hide */
- public static void invalidateDefaultSmsSubIdCaches() {
- PropertyInvalidatedCache.invalidateCache(CACHE_KEY_DEFAULT_SMS_SUB_ID_PROPERTY);
- }
-
- /** @hide */
- public static void invalidateActiveDataSubIdCaches() {
- if (isSubscriptionManagerServiceEnabled()) {
- PropertyInvalidatedCache.invalidateCache(
- CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY);
- } else {
- PropertyInvalidatedCache.invalidateCache(CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY);
- }
- }
-
- /** @hide */
- public static void invalidateSlotIndexCaches() {
- PropertyInvalidatedCache.invalidateCache(CACHE_KEY_SLOT_INDEX_PROPERTY);
- }
-
- /** @hide */
public static void invalidateSubscriptionManagerServiceCaches() {
PropertyInvalidatedCache.invalidateCache(CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY);
}
- /** @hide */
- //TODO: Removed before U AOSP public release.
- public static void invalidateSubscriptionManagerServiceEnabledCaches() {
- PropertyInvalidatedCache.invalidateCache(
- CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY);
- }
-
/**
* Allows a test process to disable client-side caching operations.
*
* @hide
*/
public static void disableCaching() {
- sDefaultSubIdCache.disableLocal();
- sDefaultDataSubIdCache.disableLocal();
- sActiveDataSubIdCache.disableLocal();
- sDefaultSmsSubIdCache.disableLocal();
- sSlotIndexCache.disableLocal();
- sSubIdCache.disableLocal();
- sPhoneIdCache.disableLocal();
-
sGetDefaultSubIdCache.disableLocal();
sGetDefaultDataSubIdCache.disableLocal();
sGetActiveDataSubscriptionIdCache.disableLocal();
@@ -3996,8 +3868,6 @@
sGetSlotIndexCache.disableLocal();
sGetSubIdCache.disableLocal();
sGetPhoneIdCache.disableLocal();
-
- sIsSubscriptionManagerServiceEnabled.disableLocal();
}
/**
@@ -4005,14 +3875,6 @@
*
* @hide */
public static void clearCaches() {
- sDefaultSubIdCache.clear();
- sDefaultDataSubIdCache.clear();
- sActiveDataSubIdCache.clear();
- sDefaultSmsSubIdCache.clear();
- sSlotIndexCache.clear();
- sSubIdCache.clear();
- sPhoneIdCache.clear();
-
sGetDefaultSubIdCache.clear();
sGetDefaultDataSubIdCache.clear();
sGetActiveDataSubscriptionIdCache.clear();
@@ -4020,8 +3882,6 @@
sGetSlotIndexCache.clear();
sGetSubIdCache.clear();
sGetPhoneIdCache.clear();
-
- sIsSubscriptionManagerServiceEnabled.clear();
}
/**
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 6a5380d..21a6b44 100644
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -129,9 +129,9 @@
* @param uniqueId This is the unique identifier for the subscription within the specific
* subscription type.
* @param subscriptionType the type of subscription to be removed
- * @return 0 if success, < 0 on error.
+ * @return true if success, false on error.
*/
- int removeSubInfo(String uniqueId, int subscriptionType);
+ boolean removeSubInfo(String uniqueId, int subscriptionType);
/**
* Set SIM icon tint color by simInfo index
@@ -260,7 +260,7 @@
int[] getActiveSubIdList(boolean visibleOnly);
- int setSubscriptionProperty(int subId, String propKey, String propValue);
+ void setSubscriptionProperty(int subId, String propKey, String propValue);
String getSubscriptionProperty(int subId, String propKey, String callingPackage,
String callingFeatureId);
@@ -353,13 +353,6 @@
*/
List<SubscriptionInfo> getSubscriptionInfoListAssociatedWithUser(in UserHandle userHandle);
- /**
- * @return {@code true} if using SubscriptionManagerService instead of
- * SubscriptionController.
- */
- //TODO: Removed before U AOSP public release.
- boolean isSubscriptionManagerServiceEnabled();
-
/**
* Called during setup wizard restore flow to attempt to restore the backed up sim-specific
* configs to device for all existing SIMs in the subscription database
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
index 18e49fe..ae9ca80 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
@@ -102,7 +102,7 @@
@Postsubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
- @Postsubmit
+ @Ignore("Not applicable to this CUJ. App is full screen at the end")
@Test
override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
@@ -127,11 +127,11 @@
@Test
override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
- @Postsubmit
+ @Ignore("Not applicable to this CUJ. App is full screen at the end")
@Test
override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
- @Postsubmit
+ @Ignore("Not applicable to this CUJ. App is full screen at the end")
@Test
override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
@@ -145,7 +145,7 @@
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
- @Postsubmit
+ @Ignore("Not applicable to this CUJ. App is full screen at the end")
@Test
override fun navBarWindowIsVisibleAtStartAndEnd() {
super.navBarWindowIsVisibleAtStartAndEnd()
diff --git a/tools/validatekeymaps/Android.bp b/tools/validatekeymaps/Android.bp
index 25373f9..554f64e 100644
--- a/tools/validatekeymaps/Android.bp
+++ b/tools/validatekeymaps/Android.bp
@@ -15,7 +15,7 @@
cc_binary_host {
name: "validatekeymaps",
-
+ cpp_std: "c++20",
srcs: ["Main.cpp"],
cflags: [