Merge "Merge mContentCaptureSession and mCachedContentCaptureSession."
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000..b061ccf
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1 @@
+Ember Rose <emberr@google.com> <ashleyrose@google.com>
diff --git a/api/system-current.txt b/api/system-current.txt
index 4ed9633..1c5f772 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3029,6 +3029,26 @@
field public static final int STATUS_OK = 0; // 0x0
}
+ public static final class SoundTrigger.ModuleProperties implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.ModuleProperties> CREATOR;
+ field @NonNull public final String description;
+ field public final int id;
+ field @NonNull public final String implementor;
+ field public final int maxBufferMs;
+ field public final int maxKeyphrases;
+ field public final int maxSoundModels;
+ field public final int maxUsers;
+ field public final int powerConsumptionMw;
+ field public final int recognitionModes;
+ field public final boolean returnsTriggerInEvent;
+ field public final boolean supportsCaptureTransition;
+ field public final boolean supportsConcurrentCapture;
+ field @NonNull public final java.util.UUID uuid;
+ field public final int version;
+ }
+
public static class SoundTrigger.RecognitionEvent {
method @Nullable public android.media.AudioFormat getCaptureFormat();
method public int getCaptureSession();
@@ -3771,6 +3791,7 @@
method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void deleteModel(java.util.UUID);
method public int getDetectionServiceOperationsTimeout();
method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.media.soundtrigger.SoundTriggerManager.Model getModel(java.util.UUID);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) @Nullable public android.hardware.soundtrigger.SoundTrigger.ModuleProperties getModuleProperties();
method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void updateModel(android.media.soundtrigger.SoundTriggerManager.Model);
}
@@ -8187,7 +8208,9 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
method public int getSimApplicationState();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int);
method public int getSimCardState();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
diff --git a/api/test-current.txt b/api/test-current.txt
index 16bdefa..43b9086 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -620,7 +620,6 @@
method public int describeContents();
method public static android.content.AutofillOptions forWhitelistingItself();
method public boolean isAugmentedAutofillEnabled(@NonNull android.content.Context);
- method public boolean isAutofillDisabledLocked(@NonNull android.content.ComponentName);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.content.AutofillOptions> CREATOR;
field public long appDisabledExpiration;
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 917ee6d..b4913c8 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -1150,8 +1150,6 @@
Lcom/android/internal/statusbar/IStatusBarService$Stub;-><init>()V
Lcom/android/internal/statusbar/IStatusBarService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/statusbar/IStatusBarService;
Lcom/android/internal/telecom/ITelecomService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telecom/ITelecomService;
-Lcom/android/internal/telephony/IIccPhoneBook$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Lcom/android/internal/telephony/IIccPhoneBook$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IIccPhoneBook;
Lcom/android/internal/telephony/IMms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IMms;
Lcom/android/internal/telephony/IPhoneStateListener$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IPhoneStateListener;
Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -1159,7 +1157,6 @@
Lcom/android/internal/telephony/IPhoneSubInfo$Stub;->TRANSACTION_getDeviceId:I
Lcom/android/internal/telephony/ISms$Stub;-><init>()V
Lcom/android/internal/telephony/ISms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ISms;
-Lcom/android/internal/telephony/ISub$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/telephony/ISub$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ISub;
Lcom/android/internal/telephony/ITelephony$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->mRemote:Landroid/os/IBinder;
@@ -1183,5 +1180,4 @@
Lcom/android/server/ResettableTimeout$T;-><init>(Lcom/android/server/ResettableTimeout;)V
Lcom/google/android/gles_jni/EGLImpl;-><init>()V
Lcom/google/android/gles_jni/GLImpl;-><init>()V
-Lcom/google/android/mms/pdu/PduParser;->$assertionsDisabled:Z
Lcom/google/android/util/AbstractMessageParser$Token$Type;->values()[Lcom/google/android/util/AbstractMessageParser$Token$Type;
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 48ca716..dbe50c3 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -287,7 +287,8 @@
void handleApplicationStrictModeViolation(in IBinder app, int penaltyMask,
in StrictMode.ViolationInfo crashInfo);
boolean isTopActivityImmersive();
- void crashApplication(int uid, int initialPid, in String packageName, int userId, in String message);
+ void crashApplication(int uid, int initialPid, in String packageName, int userId,
+ in String message, boolean force);
@UnsupportedAppUsage
String getProviderMimeType(in Uri uri, int userId);
// Cause the specified process to dump the specified heap.
@@ -350,11 +351,13 @@
// Request a heap dump for the system server.
void requestSystemServerHeapDump();
- // Deprecated - This method is only used by a few internal components and it will soon be
- // replaced by a proper bug report API (which will be restricted to a few, pre-defined apps).
+ // Deprecated - This method is only used by a few internal components and it will soon start
+ // using bug report API (which will be restricted to a few, pre-defined apps).
// No new code should be calling it.
@UnsupportedAppUsage
void requestBugReport(int bugreportType);
+ void requestBugReportWithDescription(in @nullable String shareTitle,
+ in @nullable String shareDescription, int bugreportType);
/**
* Takes a telephony bug report and notifies the user with the title and description
@@ -369,7 +372,7 @@
void requestTelephonyBugReport(in String shareTitle, in String shareDescription);
/**
- * Deprecated - This method is only used by Wifi, and it will soon be replaced by a proper
+ * Deprecated - This method is only used by Wifi, and it will soon start using
* bug report API.
*
* Takes a minimal bugreport of Wifi-related state.
@@ -381,6 +384,12 @@
* parameters cannot be encoding to an UTF-8 charset.
*/
void requestWifiBugReport(in String shareTitle, in String shareDescription);
+ void requestInteractiveBugReportWithDescription(in String shareTitle,
+ in String shareDescription);
+
+ void requestInteractiveBugReport();
+ void requestFullBugReport();
+ void requestRemoteBugReport();
@UnsupportedAppUsage
Intent getIntentForIntentSender(in IIntentSender sender);
diff --git a/core/java/android/app/role/RoleControllerService.java b/core/java/android/app/role/RoleControllerService.java
index 85db6a4..06623f9 100644
--- a/core/java/android/app/role/RoleControllerService.java
+++ b/core/java/android/app/role/RoleControllerService.java
@@ -279,6 +279,10 @@
/**
* Check whether an application is visible for a role.
*
+ * While an application can be qualified for a role, it can still stay hidden from user (thus
+ * not visible). If an application is visible for a role, we may show things related to the role
+ * for it, e.g. showing an entry pointing to the role settings in its application info page.
+ *
* @param roleName name of the role to check for
* @param packageName package name of the application to check for
*
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 39d63de..e7ba85a 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -858,7 +858,10 @@
if (DBG) {
Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));
}
- return (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON);
+ return (state == BluetoothAdapter.STATE_ON
+ || state == BluetoothAdapter.STATE_BLE_ON
+ || state == BluetoothAdapter.STATE_TURNING_ON
+ || state == BluetoothAdapter.STATE_TURNING_OFF);
}
/**
diff --git a/core/java/android/bluetooth/BluetoothOutputStream.java b/core/java/android/bluetooth/BluetoothOutputStream.java
index a0aa2de..dfec4e1 100644
--- a/core/java/android/bluetooth/BluetoothOutputStream.java
+++ b/core/java/android/bluetooth/BluetoothOutputStream.java
@@ -75,4 +75,16 @@
}
mSocket.write(b, offset, count);
}
+
+ /**
+ * Wait until the data in sending queue is emptied. A polling version
+ * for flush implementation. Use it to ensure the writing data afterwards will
+ * be packed in the new RFCOMM frame.
+ *
+ * @throws IOException if an i/o error occurs.
+ * @since Android 4.2.3
+ */
+ public void flush() throws IOException {
+ mSocket.flush();
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 760166b..a6e3153 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -515,6 +515,20 @@
return mSocketIS.available();
}
+ /**
+ * Wait until the data in sending queue is emptied. A polling version
+ * for flush implementation. Used to ensure the writing data afterwards will
+ * be packed in new RFCOMM frame.
+ *
+ * @throws IOException if an i/o error occurs.
+ */
+ @UnsupportedAppUsage
+ /*package*/ void flush() throws IOException {
+ if (mSocketOS == null) throw new IOException("flush is called on null OutputStream");
+ if (VDBG) Log.d(TAG, "flush: " + mSocketOS);
+ mSocketOS.flush();
+ }
+
/*package*/ int read(byte[] b, int offset, int length) throws IOException {
int ret = 0;
if (VDBG) Log.d(TAG, "read in: " + mSocketIS + " len: " + length);
diff --git a/core/java/android/content/AutofillOptions.java b/core/java/android/content/AutofillOptions.java
index 082663e..97b33b7 100644
--- a/core/java/android/content/AutofillOptions.java
+++ b/core/java/android/content/AutofillOptions.java
@@ -97,6 +97,8 @@
/**
* Returns if autofill is disabled by service to the given activity.
+ *
+ * @hide
*/
public boolean isAutofillDisabledLocked(@NonNull ComponentName componentName) {
final long elapsedTime = SystemClock.elapsedRealtime();
diff --git a/core/java/android/content/pm/AndroidTelephonyCommonUpdater.java b/core/java/android/content/pm/AndroidTelephonyCommonUpdater.java
new file mode 100644
index 0000000..1a720d5
--- /dev/null
+++ b/core/java/android/content/pm/AndroidTelephonyCommonUpdater.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.pm;
+
+import static android.content.pm.SharedLibraryNames.ANDROID_TELEPHONY_COMMON;
+
+
+import com.android.internal.compat.IPlatformCompat;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
+import android.content.pm.PackageParser.Package;
+
+import android.os.Build.VERSION_CODES;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Updates a package to ensure that
+ * <ul>
+ * <li> if apps have target SDK < R, then telephony-common library is included by default to
+ * their class path. Even without <uses-library>.</li>
+ * <li> if apps with target SDK level >= R && have special permission (or Phone UID):
+ * apply <uses-library> on telephony-common should work.</li>
+ * <li> Otherwise not allow to use the lib.
+ * See {@link PackageSharedLibraryUpdater#removeLibrary(Package, String)}.</li>
+ * </ul>
+ *
+ * @hide
+ */
+@VisibleForTesting
+public class AndroidTelephonyCommonUpdater extends PackageSharedLibraryUpdater {
+
+ private static final String TAG = AndroidTelephonyCommonUpdater.class.getSimpleName();
+ /**
+ * Restrict telephony-common lib for apps having target SDK >= R
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = VERSION_CODES.Q)
+ static final long RESTRICT_TELEPHONY_COMMON_CHANGE_ID = 139318877L;
+
+ private static boolean apkTargetsApiLevelLessThanROrCurrent(Package pkg) {
+ boolean shouldRestrict = false;
+ try {
+ IBinder b = ServiceManager.getService("platform_compat");
+ IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(b);
+ shouldRestrict = platformCompat.isChangeEnabled(RESTRICT_TELEPHONY_COMMON_CHANGE_ID,
+ pkg.applicationInfo);
+ } catch (RemoteException ex) {
+ Log.e(TAG, ex.getMessage());
+ }
+ // TODO(b/139318877): remove version check for CUR_DEVELOPEMENT after clean up work.
+ return !shouldRestrict
+ || pkg.applicationInfo.targetSdkVersion == VERSION_CODES.CUR_DEVELOPMENT;
+ }
+
+ @Override
+ public void updatePackage(Package pkg) {
+ // for apps with targetSDKVersion < R include the library for backward compatibility.
+ if (apkTargetsApiLevelLessThanROrCurrent(pkg)) {
+ prefixRequiredLibrary(pkg, ANDROID_TELEPHONY_COMMON);
+ } else if (pkg.mSharedUserId == null || !pkg.mSharedUserId.equals("android.uid.phone")) {
+ // if apps target >= R
+ removeLibrary(pkg, ANDROID_TELEPHONY_COMMON);
+ }
+ }
+}
diff --git a/core/java/android/content/pm/PackageBackwardCompatibility.java b/core/java/android/content/pm/PackageBackwardCompatibility.java
index 4331bd4..797ba64b 100644
--- a/core/java/android/content/pm/PackageBackwardCompatibility.java
+++ b/core/java/android/content/pm/PackageBackwardCompatibility.java
@@ -51,6 +51,8 @@
packageUpdaters.add(new AndroidHidlUpdater());
+ packageUpdaters.add(new AndroidTelephonyCommonUpdater());
+
// Add this before adding AndroidTestBaseUpdater so that android.test.base comes before
// android.test.mock.
packageUpdaters.add(new AndroidTestRunnerSplitUpdater());
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ef08bf5..4c970da 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -57,6 +57,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageParserCacheHelper.ReadHelper;
import android.content.pm.PackageParserCacheHelper.WriteHelper;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.content.pm.split.DefaultSplitAssetLoader;
import android.content.pm.split.SplitAssetDependencyLoader;
import android.content.pm.split.SplitAssetLoader;
@@ -79,7 +80,6 @@
import android.os.Trace;
import android.os.UserHandle;
import android.os.storage.StorageManager;
-import android.permission.PermissionManager;
import android.system.ErrnoException;
import android.system.OsConstants;
import android.system.StructStat;
@@ -2528,11 +2528,17 @@
Slog.i(TAG, newPermsMsg.toString());
}
+ List<SplitPermissionInfoParcelable> splitPermissions;
- final int NS = PermissionManager.SPLIT_PERMISSIONS.size();
- for (int is=0; is<NS; is++) {
- final PermissionManager.SplitPermissionInfo spi =
- PermissionManager.SPLIT_PERMISSIONS.get(is);
+ try {
+ splitPermissions = ActivityThread.getPermissionManager().getSplitPermissions();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+
+ final int listSize = splitPermissions.size();
+ for (int is = 0; is < listSize; is++) {
+ final SplitPermissionInfoParcelable spi = splitPermissions.get(is);
if (pkg.applicationInfo.targetSdkVersion >= spi.getTargetSdk()
|| !pkg.requestedPermissions.contains(spi.getSplitPermission())) {
continue;
@@ -8501,5 +8507,4 @@
this.error = error;
}
}
-
}
diff --git a/core/java/android/content/pm/SharedLibraryNames.java b/core/java/android/content/pm/SharedLibraryNames.java
index a607a9f..4c66fc0 100644
--- a/core/java/android/content/pm/SharedLibraryNames.java
+++ b/core/java/android/content/pm/SharedLibraryNames.java
@@ -33,4 +33,6 @@
static final String ANDROID_TEST_RUNNER = "android.test.runner";
public static final String ORG_APACHE_HTTP_LEGACY = "org.apache.http.legacy";
+
+ public static final String ANDROID_TELEPHONY_COMMON = "telephony-common";
}
diff --git a/services/core/java/com/android/server/wm/SurfaceBuilderFactory.java b/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.aidl
similarity index 62%
rename from services/core/java/com/android/server/wm/SurfaceBuilderFactory.java
rename to core/java/android/content/pm/permission/SplitPermissionInfoParcelable.aidl
index 5390e5a..d84454c 100644
--- a/services/core/java/com/android/server/wm/SurfaceBuilderFactory.java
+++ b/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
+/**
+ * Copyright (c) 2019, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -14,12 +14,6 @@
* limitations under the License.
*/
-package com.android.server.wm;
+ package android.content.pm.permission;
-import android.view.SurfaceSession;
-import android.view.SurfaceControl;
-
-interface SurfaceBuilderFactory {
- SurfaceControl.Builder make(SurfaceSession s);
-};
-
+ parcelable SplitPermissionInfoParcelable;
\ No newline at end of file
diff --git a/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.java b/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.java
new file mode 100644
index 0000000..421ae49
--- /dev/null
+++ b/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.permission;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Preconditions;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Parcelable version of {@link android.permission.PermissionManager.SplitPermissionInfo}
+ * @hide
+ */
+@DataClass(genEqualsHashCode = true)
+public class SplitPermissionInfoParcelable implements Parcelable {
+
+ /**
+ * The permission that is split.
+ */
+ @NonNull
+ private final String mSplitPermission;
+
+ /**
+ * The permissions that are added.
+ */
+ @NonNull
+ private final List<String> mNewPermissions;
+
+ /**
+ * The target API level when the permission was split.
+ */
+ @IntRange(from = 0)
+ private final int mTargetSdk;
+
+ private void onConstructed() {
+ Preconditions.checkCollectionElementsNotNull(mNewPermissions, "newPermissions");
+ }
+
+
+
+ // Code below generated by codegen v1.0.0.
+ //
+ // DO NOT MODIFY!
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.java
+ //
+ // CHECKSTYLE:OFF Generated code
+
+ /**
+ * Creates a new SplitPermissionInfoParcelable.
+ *
+ * @param splitPermission
+ * The permission that is split.
+ * @param newPermissions
+ * The permissions that are added.
+ * @param targetSdk
+ * The target API level when the permission was split.
+ */
+ @DataClass.Generated.Member
+ public SplitPermissionInfoParcelable(
+ @NonNull String splitPermission,
+ @NonNull List<String> newPermissions,
+ @IntRange(from = 0) int targetSdk) {
+ this.mSplitPermission = splitPermission;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mSplitPermission);
+ this.mNewPermissions = newPermissions;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mNewPermissions);
+ this.mTargetSdk = targetSdk;
+ com.android.internal.util.AnnotationValidations.validate(
+ IntRange.class, null, mTargetSdk,
+ "from", 0);
+
+ onConstructed();
+ }
+
+ /**
+ * The permission that is split.
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getSplitPermission() {
+ return mSplitPermission;
+ }
+
+ /**
+ * The permissions that are added.
+ */
+ @DataClass.Generated.Member
+ public @NonNull List<String> getNewPermissions() {
+ return mNewPermissions;
+ }
+
+ /**
+ * The target API level when the permission was split.
+ */
+ @DataClass.Generated.Member
+ public @IntRange(from = 0) int getTargetSdk() {
+ return mTargetSdk;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(SplitPermissionInfoParcelable other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ SplitPermissionInfoParcelable that = (SplitPermissionInfoParcelable) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && Objects.equals(mSplitPermission, that.mSplitPermission)
+ && Objects.equals(mNewPermissions, that.mNewPermissions)
+ && mTargetSdk == that.mTargetSdk;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + Objects.hashCode(mSplitPermission);
+ _hash = 31 * _hash + Objects.hashCode(mNewPermissions);
+ _hash = 31 * _hash + mTargetSdk;
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeString(mSplitPermission);
+ dest.writeStringList(mNewPermissions);
+ dest.writeInt(mTargetSdk);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<SplitPermissionInfoParcelable> CREATOR
+ = new Parcelable.Creator<SplitPermissionInfoParcelable>() {
+ @Override
+ public SplitPermissionInfoParcelable[] newArray(int size) {
+ return new SplitPermissionInfoParcelable[size];
+ }
+
+ @Override
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ public SplitPermissionInfoParcelable createFromParcel(Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ String splitPermission = in.readString();
+ List<String> newPermissions = new java.util.ArrayList<>();
+ in.readStringList(newPermissions);
+ int targetSdk = in.readInt();
+ return new SplitPermissionInfoParcelable(
+ splitPermission,
+ newPermissions,
+ targetSdk);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1567634390477L,
+ codegenVersion = "1.0.0",
+ sourceFile = "frameworks/base/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.java",
+ inputSignatures = "private final @android.annotation.NonNull java.lang.String mSplitPermission\nprivate final @android.annotation.NonNull java.util.List<java.lang.String> mNewPermissions\nprivate final @android.annotation.IntRange(from=0L) int mTargetSdk\nprivate void onConstructed()\nclass SplitPermissionInfoParcelable extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 21c49ad..0b25dbd 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -829,23 +829,36 @@
public interface DeviceConfig {
/**
- * Key for accessing the 60 hz only regions.
+ * Key for refresh rate in the zone defined by thresholds.
+ *
+ * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
+ * @see android.R.integer#config_defaultZoneBehavior
+ */
+ String KEY_REFRESH_RATE_IN_ZONE = "refresh_rate_in_zone";
+
+ /**
+ * Key for accessing the display brightness thresholds for the configured refresh rate zone.
+ * The value will be a pair of comma separated integers representing the minimum and maximum
+ * thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]).
*
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
* @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
* @hide
*/
- String KEY_PEAK_REFRESH_RATE_BRIGHTNESS_THRESHOLDS =
+ String KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS =
"peak_refresh_rate_brightness_thresholds";
/**
- * Key for accessing the 60 hz only regions.
+ * Key for accessing the ambient brightness thresholds for the configured refresh rate zone.
+ * The value will be a pair of comma separated integers representing the minimum and maximum
+ * thresholds of the zone, respectively, in lux.
*
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
- * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
+ * @see android.R.array#config_ambientThresholdsOfPeakRefreshRate
* @hide
*/
- String KEY_PEAK_REFRESH_RATE_AMBIENT_THRESHOLDS = "peak_refresh_rate_ambient_thresholds";
+ String KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS =
+ "peak_refresh_rate_ambient_thresholds";
/**
* Key for default peak refresh rate
@@ -855,5 +868,16 @@
* @hide
*/
String KEY_PEAK_REFRESH_RATE_DEFAULT = "peak_refresh_rate_default";
+
+ /**
+ * Key for controlling which packages are explicitly blocked from running at refresh rates
+ * higher than 60hz. An app may be added to this list if they exhibit performance issues at
+ * higher refresh rates.
+ *
+ * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
+ * @see android.R.array#config_highRefreshRateBlacklist
+ * @hide
+ */
+ String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist";
}
}
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index f96f47d..b1134e1 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -71,28 +71,27 @@
* ID used to target any API call to this paricular module. Module
* properties are returned by listModules() method.
*
- * @hide
****************************************************************************/
- public static class ModuleProperties implements Parcelable {
+ public static final class ModuleProperties implements Parcelable {
/** Unique module ID provided by the native service */
- @UnsupportedAppUsage
public final int id;
/** human readable voice detection engine implementor */
+ @NonNull
public final String implementor;
/** human readable voice detection engine description */
+ @NonNull
public final String description;
/** Unique voice engine Id (changes with each version) */
- @UnsupportedAppUsage
+ @NonNull
public final UUID uuid;
/** Voice detection engine version */
public final int version;
/** Maximum number of active sound models */
- @UnsupportedAppUsage
public final int maxSoundModels;
/** Maximum number of key phrases */
@@ -120,7 +119,6 @@
* recognition callback event */
public final boolean returnsTriggerInEvent;
- @UnsupportedAppUsage
ModuleProperties(int id, String implementor, String description,
String uuid, int version, int maxSoundModels, int maxKeyphrases,
int maxUsers, int recognitionModes, boolean supportsCaptureTransition,
diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java
index b066a15..fe7632c 100644
--- a/core/java/android/net/LocalSocketImpl.java
+++ b/core/java/android/net/LocalSocketImpl.java
@@ -157,6 +157,40 @@
write_native(b, myFd);
}
}
+
+ /**
+ * Wait until the data in sending queue is emptied. A polling version
+ * for flush implementation.
+ * @throws IOException
+ * if an i/o error occurs.
+ */
+ @Override
+ public void flush() throws IOException {
+ FileDescriptor myFd = fd;
+ if (myFd == null) throw new IOException("socket closed");
+
+ // Loop until the output buffer is empty.
+ Int32Ref pending = new Int32Ref(0);
+ while (true) {
+ try {
+ // See linux/net/unix/af_unix.c
+ Os.ioctlInt(myFd, OsConstants.TIOCOUTQ, pending);
+ } catch (ErrnoException e) {
+ throw e.rethrowAsIOException();
+ }
+
+ if (pending.value <= 0) {
+ // The output buffer is empty.
+ break;
+ }
+
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException ie) {
+ break;
+ }
+ }
+ }
}
private native int read_native(FileDescriptor fd) throws IOException;
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 9fa5f16..60c8811 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -19,6 +19,7 @@
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.permission.IOnPermissionsChangeListener;
/**
@@ -97,4 +98,6 @@
String packageName, int userId);
boolean isPermissionRevokedByPolicy(String permName, String packageName, int userId);
+
+ List<SplitPermissionInfoParcelable> getSplitPermissions();
}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 5e35958..6c4ee01 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -24,16 +24,18 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.app.ActivityThread;
import android.content.Context;
import android.content.pm.IPackageManager;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.os.RemoteException;
+import android.util.Slog;
import com.android.internal.annotations.Immutable;
-import com.android.server.SystemConfig;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
-import java.util.Objects;
/**
* System level service for accessing the permission capabilities of the platform.
@@ -44,6 +46,8 @@
@SystemApi
@SystemService(Context.PERMISSION_SERVICE)
public final class PermissionManager {
+ private static final String TAG = PermissionManager.class.getName();
+
/** @hide */
public static final String KILL_APP_REASON_PERMISSIONS_REVOKED =
"permissions revoked";
@@ -51,19 +55,12 @@
public static final String KILL_APP_REASON_GIDS_CHANGED =
"permission grant or revoke changed gids";
-
- /**
- * {@link android.content.pm.PackageParser} needs access without having a {@link Context}.
- *
- * @hide
- */
- public static final ArrayList<SplitPermissionInfo> SPLIT_PERMISSIONS =
- SystemConfig.getInstance().getSplitPermissions();
-
private final @NonNull Context mContext;
private final IPackageManager mPackageManager;
+ private List<SplitPermissionInfo> mSplitPermissionInfos;
+
/**
* Creates a new instance.
*
@@ -131,7 +128,48 @@
* @return All permissions that are split.
*/
public @NonNull List<SplitPermissionInfo> getSplitPermissions() {
- return SPLIT_PERMISSIONS;
+ if (mSplitPermissionInfos != null) {
+ return mSplitPermissionInfos;
+ }
+
+ List<SplitPermissionInfoParcelable> parcelableList;
+ try {
+ parcelableList = ActivityThread.getPermissionManager().getSplitPermissions();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error getting split permissions", e);
+ return Collections.emptyList();
+ }
+
+ mSplitPermissionInfos = splitPermissionInfoListToNonParcelableList(parcelableList);
+
+ return mSplitPermissionInfos;
+ }
+
+ private List<SplitPermissionInfo> splitPermissionInfoListToNonParcelableList(
+ List<SplitPermissionInfoParcelable> parcelableList) {
+ final int size = parcelableList.size();
+ List<SplitPermissionInfo> list = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ list.add(new SplitPermissionInfo(parcelableList.get(i)));
+ }
+ return list;
+ }
+
+ /**
+ * Converts a {@link List} of {@link SplitPermissionInfo} into a List of
+ * {@link SplitPermissionInfoParcelable} and returns it.
+ * @hide
+ */
+ public static List<SplitPermissionInfoParcelable> splitPermissionInfoListToParcelableList(
+ List<SplitPermissionInfo> splitPermissionsList) {
+ final int size = splitPermissionsList.size();
+ List<SplitPermissionInfoParcelable> outList = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ SplitPermissionInfo info = splitPermissionsList.get(i);
+ outList.add(new SplitPermissionInfoParcelable(
+ info.getSplitPermission(), info.getNewPermissions(), info.getTargetSdk()));
+ }
+ return outList;
}
/**
@@ -140,44 +178,40 @@
*/
@Immutable
public static final class SplitPermissionInfo {
- private final @NonNull String mSplitPerm;
- private final @NonNull List<String> mNewPerms;
- private final int mTargetSdk;
+ private @NonNull final SplitPermissionInfoParcelable mSplitPermissionInfoParcelable;
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SplitPermissionInfo that = (SplitPermissionInfo) o;
- return mTargetSdk == that.mTargetSdk
- && mSplitPerm.equals(that.mSplitPerm)
- && mNewPerms.equals(that.mNewPerms);
+ return mSplitPermissionInfoParcelable.equals(that.mSplitPermissionInfoParcelable);
}
@Override
public int hashCode() {
- return Objects.hash(mSplitPerm, mNewPerms, mTargetSdk);
+ return mSplitPermissionInfoParcelable.hashCode();
}
/**
* Get the permission that is split.
*/
public @NonNull String getSplitPermission() {
- return mSplitPerm;
+ return mSplitPermissionInfoParcelable.getSplitPermission();
}
/**
* Get the permissions that are added.
*/
public @NonNull List<String> getNewPermissions() {
- return mNewPerms;
+ return mSplitPermissionInfoParcelable.getNewPermissions();
}
/**
* Get the target API level when the permission was split.
*/
public int getTargetSdk() {
- return mTargetSdk;
+ return mSplitPermissionInfoParcelable.getTargetSdk();
}
/**
@@ -191,9 +225,11 @@
*/
public SplitPermissionInfo(@NonNull String splitPerm, @NonNull List<String> newPerms,
int targetSdk) {
- mSplitPerm = splitPerm;
- mNewPerms = newPerms;
- mTargetSdk = targetSdk;
+ this(new SplitPermissionInfoParcelable(splitPerm, newPerms, targetSdk));
+ }
+
+ private SplitPermissionInfo(@NonNull SplitPermissionInfoParcelable parcelable) {
+ mSplitPermissionInfoParcelable = parcelable;
}
}
}
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 4b9daf1..5e201e4 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -367,15 +367,6 @@
*/
String KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS =
"system_gesture_exclusion_log_debounce_millis";
-
- /**
- * Key for controlling which packages are explicitly blocked from running at refresh rates
- * higher than 90hz.
- *
- * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
- * @hide
- */
- String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist";
}
private static final Object sLock = new Object();
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index d2f22bf..ff8b135 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -29,7 +29,6 @@
import android.telephony.euicc.DownloadableSubscription;
import android.telephony.euicc.EuiccInfo;
import android.telephony.euicc.EuiccManager.OtaStatus;
-import android.util.ArraySet;
import android.util.Log;
import java.lang.annotation.Retention;
@@ -252,18 +251,6 @@
public static final int RESULT_FIRST_USER = 1;
/**
- * List of all valid resolution actions for validation purposes.
- * @hide
- */
- public static final ArraySet<String> RESOLUTION_ACTIONS;
- static {
- RESOLUTION_ACTIONS = new ArraySet<>();
- RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM);
- RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_NO_PRIVILEGES);
- RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_RESOLVABLE_ERRORS);
- }
-
- /**
* Boolean extra for resolution actions indicating whether the user granted consent.
* This is used and set by the implementation and used in {@code EuiccOperation}.
*/
diff --git a/core/java/android/view/GestureExclusionTracker.java b/core/java/android/view/GestureExclusionTracker.java
index fcc14c1..fffb323e 100644
--- a/core/java/android/view/GestureExclusionTracker.java
+++ b/core/java/android/view/GestureExclusionTracker.java
@@ -44,7 +44,7 @@
while (i.hasNext()) {
final GestureExclusionViewInfo info = i.next();
final View v = info.getView();
- if (v == null || !v.isAttachedToWindow() || !v.isShown()) {
+ if (v == null || !v.isAttachedToWindow() || !v.isAggregatedVisible()) {
mGestureExclusionViewsChanged = true;
i.remove();
continue;
@@ -123,7 +123,7 @@
public int update() {
final View excludedView = getView();
if (excludedView == null || !excludedView.isAttachedToWindow()
- || !excludedView.isShown()) return GONE;
+ || !excludedView.isAggregatedVisible()) return GONE;
final List<Rect> localRects = excludedView.getSystemGestureExclusionRects();
final List<Rect> newRects = new ArrayList<>(localRects.size());
for (Rect src : localRects) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0a24940..7ee3973 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -14327,6 +14327,14 @@
}
/**
+ * @return true if this view and all ancestors are visible as of the last
+ * {@link #onVisibilityAggregated(boolean)} call.
+ */
+ boolean isAggregatedVisible() {
+ return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
+ }
+
+ /**
* Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
* ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
* {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
@@ -14354,7 +14362,7 @@
@CallSuper
public void onVisibilityAggregated(boolean isVisible) {
// Update our internal visibility tracking so we can detect changes
- boolean oldVisible = (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
+ boolean oldVisible = isAggregatedVisible();
mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
: (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
if (isVisible && mAttachInfo != null) {
@@ -14406,7 +14414,9 @@
}
notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
- updateSystemGestureExclusionRects();
+ if (isVisible != oldVisible) {
+ updateSystemGestureExclusionRects();
+ }
}
/**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index d302c2b..032af1c 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -707,9 +707,10 @@
if (mBindSequence != bindSequence) {
return;
}
- if (matrixValues == null) {
- // That this app is unbound from the parent ActivityView. In this case,
- // calling updateCursorAnchorInfo() isn't safe. Only clear the matrix.
+ if (matrixValues == null || mActivityViewToScreenMatrix == null) {
+ // Either InputBoundResult#mActivityViewToScreenMatrixValues is null
+ // OR this app is unbound from the parent ActivityView. In this case,
+ // calling updateCursorAnchorInfo() isn't safe. Only clear the matrix.
mActivityViewToScreenMatrix = null;
return;
}
diff --git a/core/java/android/view/inspector/OWNERS b/core/java/android/view/inspector/OWNERS
index 0473f54..4554fdc 100644
--- a/core/java/android/view/inspector/OWNERS
+++ b/core/java/android/view/inspector/OWNERS
@@ -1,3 +1,3 @@
alanv@google.com
-ashleyrose@google.com
-aurimas@google.com
\ No newline at end of file
+aurimas@google.com
+emberr@google.com
diff --git a/core/java/com/android/internal/app/ISoundTriggerService.aidl b/core/java/com/android/internal/app/ISoundTriggerService.aidl
index 764c0cf..ea24d5f 100644
--- a/core/java/com/android/internal/app/ISoundTriggerService.aidl
+++ b/core/java/com/android/internal/app/ISoundTriggerService.aidl
@@ -54,4 +54,6 @@
boolean isRecognitionActive(in ParcelUuid parcelUuid);
int getModelState(in ParcelUuid soundModelId);
+
+ @nullable SoundTrigger.ModuleProperties getModuleProperties();
}
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 364278d..7cd3e95 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -53,6 +53,8 @@
/**
* Loads global system configuration info.
+ * Note: Initializing this class hits the disk and is slow. This class should generally only be
+ * accessed by the system_server process.
*/
public class SystemConfig {
static final String TAG = "SystemConfig";
@@ -208,6 +210,11 @@
private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>();
public static SystemConfig getInstance() {
+ if (!isSystemProcess()) {
+ Slog.wtf(TAG, "SystemConfig is being accessed by a process other than "
+ + "system_server.");
+ }
+
synchronized (SystemConfig.class) {
if (sInstance == null) {
sInstance = new SystemConfig();
@@ -1161,4 +1168,8 @@
mSplitPermissions.add(new SplitPermissionInfo(splitPerm, newPermissions, targetSdk));
}
}
+
+ private static boolean isSystemProcess() {
+ return Process.myUid() == Process.SYSTEM_UID;
+ }
}
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 2d7069c..a52a7ed 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -28,7 +28,11 @@
#include <meminfo/sysmeminfo.h>
#include <processgroup/processgroup.h>
#include <processgroup/sched_policy.h>
+#include <android-base/unique_fd.h>
+#include <algorithm>
+#include <limits>
+#include <memory>
#include <string>
#include <vector>
@@ -58,8 +62,18 @@
static const bool kDebugPolicy = false;
static const bool kDebugProc = false;
-// When reading `proc` files, how many bytes to read at a time
-static const int kReadSize = 4096;
+
+// Stack reservation for reading small proc files. Most callers of
+// readProcFile() are reading files under this threshold, e.g.,
+// /proc/pid/stat. /proc/pid/time_in_state ends up being about 520
+// bytes, so use 1024 for the stack to provide a bit of slack.
+static const ssize_t kProcReadStackBufferSize = 1024;
+
+// The other files we read from proc tend to be a bit larger (e.g.,
+// /proc/stat is about 3kB), so once we exhaust the stack buffer,
+// retry with a relatively large heap-allocated buffer. We double
+// this size and retry until the whole file fits.
+static const ssize_t kProcReadMinHeapBufferSize = 4096;
#if GUARD_THREAD_PRIORITY
Mutex gKeyCreateMutex;
@@ -1004,9 +1018,9 @@
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
return JNI_FALSE;
}
- int fd = open(file8, O_RDONLY | O_CLOEXEC);
- if (fd < 0) {
+ ::android::base::unique_fd fd(open(file8, O_RDONLY | O_CLOEXEC));
+ if (!fd.ok()) {
if (kDebugProc) {
ALOGW("Unable to open process file: %s\n", file8);
}
@@ -1015,35 +1029,52 @@
}
env->ReleaseStringUTFChars(file, file8);
- std::vector<char> fileBuffer(kReadSize);
- int numBytesRead = 0;
- while (true) {
- // Resize buffer to make space for contents. This might be more than we need, but once we've
- // read we resize back down
- fileBuffer.resize(numBytesRead + kReadSize, 0);
- // Read in contents
- int len = TEMP_FAILURE_RETRY(read(fd, fileBuffer.data() + numBytesRead, kReadSize));
- numBytesRead += len;
- if (len < 0) {
- // If `len` is negative, an error occurred on read
+ // Most proc files we read are small, so we only go through the
+ // loop once and use the stack buffer. We allocate a buffer big
+ // enough for the whole file.
+
+ char readBufferStack[kProcReadStackBufferSize];
+ std::unique_ptr<char[]> readBufferHeap;
+ char* readBuffer = &readBufferStack[0];
+ ssize_t readBufferSize = kProcReadStackBufferSize;
+ ssize_t numberBytesRead;
+ for (;;) {
+ // By using pread, we can avoid an lseek to rewind the FD
+ // before retry, saving a system call.
+ numberBytesRead = pread(fd, readBuffer, readBufferSize, 0);
+ if (numberBytesRead < 0 && errno == EINTR) {
+ continue;
+ }
+ if (numberBytesRead < 0) {
if (kDebugProc) {
- ALOGW("Unable to open process file: %s fd=%d\n", file8, fd);
+ ALOGW("Unable to open process file: %s fd=%d\n", file8, fd.get());
}
- close(fd);
return JNI_FALSE;
- } else if (len == 0) {
- // If nothing read, we're done
+ }
+ if (numberBytesRead < readBufferSize) {
break;
}
+ if (readBufferSize > std::numeric_limits<ssize_t>::max() / 2) {
+ if (kDebugProc) {
+ ALOGW("Proc file too big: %s fd=%d\n", file8, fd.get());
+ }
+ return JNI_FALSE;
+ }
+ readBufferSize = std::max(readBufferSize * 2,
+ kProcReadMinHeapBufferSize);
+ readBufferHeap.reset(); // Free address space before getting more.
+ readBufferHeap = std::make_unique<char[]>(readBufferSize);
+ if (!readBufferHeap) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ return JNI_FALSE;
+ }
+ readBuffer = readBufferHeap.get();
}
- // Resize back down to the amount we read
- fileBuffer.resize(numBytesRead);
- // Terminate buffer with null byte
- fileBuffer.push_back('\0');
- close(fd);
- return android_os_Process_parseProcLineArray(env, clazz, fileBuffer.data(), 0, numBytesRead,
- format, outStrings, outLongs, outFloats);
+ // parseProcLineArray below modifies the buffer while parsing!
+ return android_os_Process_parseProcLineArray(
+ env, clazz, readBuffer, 0, numberBytesRead,
+ format, outStrings, outLongs, outFloats);
}
void android_os_Process_setApplicationObject(JNIEnv* env, jobject clazz,
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2cd39cb..5fd53de 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4202,6 +4202,10 @@
-->
</integer-array>
+ <!-- Default refresh rate in the zone defined by brightness and ambient thresholds.
+ If non-positive, then the refresh rate is unchanged even if thresholds are configured. -->
+ <integer name="config_defaultRefreshRateInZone">0</integer>
+
<!-- The type of the light sensor to be used by the display framework for things like
auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. -->
<string name="config_displayLightSensorType" translatable="false" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index eaebd91..8aa4a8c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3801,6 +3801,7 @@
<!-- For high refresh rate displays -->
<java-symbol type="integer" name="config_defaultPeakRefreshRate" />
+ <java-symbol type="integer" name="config_defaultRefreshRateInZone" />
<java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" />
<java-symbol type="array" name="config_ambientThresholdsOfPeakRefreshRate" />
diff --git a/core/tests/coretests/src/android/content/pm/AndroidTelephonyCommonUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidTelephonyCommonUpdaterTest.java
new file mode 100644
index 0000000..8ab9ddb
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/AndroidTelephonyCommonUpdaterTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import static android.content.pm.PackageBuilder.builder;
+import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_BASE;
+import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_MANAGER;
+import static android.content.pm.SharedLibraryNames.ANDROID_TELEPHONY_COMMON;
+
+import android.os.Build;
+import androidx.test.filters.SmallTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Test for {@link AndroidHidlUpdater}
+ */
+@SmallTest
+@RunWith(JUnit4.class)
+public class AndroidTelephonyCommonUpdaterTest extends PackageSharedLibraryUpdaterTest {
+
+ private static final String OTHER_LIBRARY = "other.library";
+ private static final String PHONE_UID = "android.uid.phone";
+
+ @Test
+ public void targeted_at_Q() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.Q);
+
+ PackageBuilder after = builder().targetSdkVersion(Build.VERSION_CODES.Q)
+ .requiredLibraries(ANDROID_TELEPHONY_COMMON);
+
+ // Should add telephony-common libraries
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void targeted_at_Q_phoneUID() {
+ PackageBuilder before = builder().setSharedUid(PHONE_UID)
+ .targetSdkVersion(Build.VERSION_CODES.Q);
+
+ // Should add telephony-common libraries
+ PackageBuilder after = builder().setSharedUid(PHONE_UID)
+ .targetSdkVersion(Build.VERSION_CODES.Q)
+ .requiredLibraries(ANDROID_TELEPHONY_COMMON);
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void targeted_at_Q_not_empty_usesLibraries() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.Q)
+ .requiredLibraries(OTHER_LIBRARY);
+
+ // no change
+ checkBackwardsCompatibility(before, before);
+ }
+
+ @Test
+ public void targeted_at_Q_not_empty_usesLibraries_phoneUID() {
+ PackageBuilder before = builder().setSharedUid(PHONE_UID)
+ .targetSdkVersion(Build.VERSION_CODES.Q)
+ .requiredLibraries(OTHER_LIBRARY);
+
+ // The telephony-common jars should be added at the start of the list because it
+ // is not on the bootclasspath and the package targets pre-R.
+ PackageBuilder after = builder().setSharedUid(PHONE_UID)
+ .targetSdkVersion(Build.VERSION_CODES.Q)
+ .requiredLibraries(ANDROID_TELEPHONY_COMMON, OTHER_LIBRARY);
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void targeted_at_R_in_usesLibraries() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.Q + 1)
+ .requiredLibraries(ANDROID_TELEPHONY_COMMON);
+
+ PackageBuilder after = builder()
+ .targetSdkVersion(Build.VERSION_CODES.Q + 1);
+
+ // Libraries are removed because they are not available for apps target >= R and not run
+ // on phone-uid
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void targeted_at_Q_in_usesLibraries() {
+ PackageBuilder before = builder().asSystemApp()
+ .targetSdkVersion(Build.VERSION_CODES.Q)
+ .requiredLibraries(ANDROID_TELEPHONY_COMMON);
+
+ // No change is required because the package explicitly requests the telephony libraries
+ // and is targeted at the current version so does not need backwards compatibility.
+ checkBackwardsCompatibility(before, before);
+ }
+
+
+ @Test
+ public void targeted_at_R_in_usesOptionalLibraries() {
+ PackageBuilder before = builder().targetSdkVersion(Build.VERSION_CODES.Q + 1)
+ .optionalLibraries(ANDROID_TELEPHONY_COMMON);
+
+ // Dependency is removed, it is not available.
+ PackageBuilder after = builder().targetSdkVersion(Build.VERSION_CODES.Q + 1);
+
+ // Libraries are removed because they are not available for apps targeting Q+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void targeted_at_R() {
+ PackageBuilder before = builder()
+ .targetSdkVersion(Build.VERSION_CODES.Q + 1);
+
+ // no change
+ checkBackwardsCompatibility(before, before);
+ }
+
+ private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) {
+ checkBackwardsCompatibility(before, after, AndroidTelephonyCommonUpdater::new);
+ }
+}
diff --git a/core/tests/coretests/src/android/content/pm/PackageBuilder.java b/core/tests/coretests/src/android/content/pm/PackageBuilder.java
index f7544af..f3a56e2 100644
--- a/core/tests/coretests/src/android/content/pm/PackageBuilder.java
+++ b/core/tests/coretests/src/android/content/pm/PackageBuilder.java
@@ -37,6 +37,8 @@
private ArrayList<String> mOptionalLibraries;
+ private String mSharedUid;
+
public static PackageBuilder builder() {
return new PackageBuilder();
}
@@ -47,6 +49,7 @@
pkg.applicationInfo.flags = mFlags;
pkg.usesLibraries = mRequiredLibraries;
pkg.usesOptionalLibraries = mOptionalLibraries;
+ pkg.mSharedUserId = mSharedUid;
return pkg;
}
@@ -55,6 +58,11 @@
return this;
}
+ PackageBuilder setSharedUid(String uid) {
+ this.mSharedUid = uid;
+ return this;
+ }
+
PackageBuilder asSystemApp() {
this.mFlags |= ApplicationInfo.FLAG_SYSTEM;
return this;
diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp
index 9272ea5..c445651 100644
--- a/data/etc/car/Android.bp
+++ b/data/etc/car/Android.bp
@@ -128,3 +128,10 @@
filename_from_src: true,
product_specific: true,
}
+
+prebuilt_etc {
+ name: "privapp_whitelist_com.android.car.floatingcardslauncher",
+ sub_dir: "permissions",
+ src: "com.android.car.floatingcardslauncher.xml",
+ filename_from_src: true,
+}
diff --git a/data/etc/car/com.android.car.floatingcardslauncher.xml b/data/etc/car/com.android.car.floatingcardslauncher.xml
new file mode 100644
index 0000000..2755fee
--- /dev/null
+++ b/data/etc/car/com.android.car.floatingcardslauncher.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<permissions>
+ <privapp-permissions package="com.android.car.floatingcardslauncher">
+ <permission name="android.permission.ACTIVITY_EMBEDDING"/>
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ <permission name="android.permission.MEDIA_CONTENT_CONTROL"/>
+ <permission name="android.permission.MODIFY_PHONE_STATE"/>
+ </privapp-permissions>
+</permissions>
diff --git a/data/etc/car/com.android.car.settings.xml b/data/etc/car/com.android.car.settings.xml
index 5f7e1c1..291ce80 100644
--- a/data/etc/car/com.android.car.settings.xml
+++ b/data/etc/car/com.android.car.settings.xml
@@ -50,7 +50,6 @@
<permission name="android.permission.USE_RESERVED_DISK"/>
<permission name="android.permission.USER_ACTIVITY"/>
<permission name="android.permission.WRITE_APN_SETTINGS"/>
- <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
<permission name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" />
</privapp-permissions>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 0960f78..d66930a 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -225,6 +225,8 @@
<library name="android.hidl.manager-V1.0-java"
file="/system/framework/android.hidl.manager-V1.0-java.jar"
dependency="android.hidl.base-V1.0-java" />
+ <library name="telephony-common"
+ file="/system/framework/telephony-common.jar" />
<!-- These are the standard packages that are white-listed to always have internet
access while in power save mode, even if they aren't in the foreground. -->
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 54ac0bd..2314072 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -163,7 +163,7 @@
SkCanvas::SaveLayerFlags layerFlags = 0;
if (!(flags & SaveFlags::ClipToLayer)) {
- layerFlags |= SkCanvas::kDontClipToLayer_Legacy_SaveLayerFlag;
+ layerFlags |= SkCanvasPriv::kDontClipToLayer_SaveLayerFlag;
}
return layerFlags;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index aad15ab..0ad050d 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -15,7 +15,17 @@
*/
#include "CanvasContext.h"
+
#include <GpuMemoryTracker.h>
+#include <apex/window.h>
+#include <fcntl.h>
+#include <strings.h>
+#include <sys/stat.h>
+
+#include <algorithm>
+#include <cstdint>
+#include <cstdlib>
+#include <functional>
#include "../Properties.h"
#include "AnimationContext.h"
@@ -32,16 +42,6 @@
#include "utils/TimeUtils.h"
#include "utils/TraceUtils.h"
-#include <strings.h>
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <algorithm>
-
-#include <cstdint>
-#include <cstdlib>
-#include <functional>
-
#define TRIM_MEMORY_COMPLETE 80
#define TRIM_MEMORY_UI_HIDDEN 20
@@ -484,16 +484,16 @@
swap.swapCompletedTime = systemTime(SYSTEM_TIME_MONOTONIC);
swap.vsyncTime = mRenderThread.timeLord().latestVsync();
if (didDraw) {
- int durationUs;
nsecs_t dequeueStart = mNativeSurface->getLastDequeueStartTime();
if (dequeueStart < mCurrentFrameInfo->get(FrameInfoIndex::SyncStart)) {
// Ignoring dequeue duration as it happened prior to frame render start
// and thus is not part of the frame.
swap.dequeueDuration = 0;
} else {
- mNativeSurface->query(NATIVE_WINDOW_LAST_DEQUEUE_DURATION, &durationUs);
- swap.dequeueDuration = us2ns(durationUs);
+ swap.dequeueDuration =
+ us2ns(ANativeWindow_getLastDequeueDuration(mNativeSurface.get()));
}
+ int durationUs;
mNativeSurface->query(NATIVE_WINDOW_LAST_QUEUE_DURATION, &durationUs);
swap.queueDuration = us2ns(durationUs);
} else {
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index ada77c5..dc400ad 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -383,4 +383,20 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Get the hardware sound trigger module properties currently loaded.
+ *
+ * @return The properties currently loaded. Returns null if no supported hardware loaded.
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
+ @Nullable
+ public SoundTrigger.ModuleProperties getModuleProperties() {
+
+ try {
+ return mSoundTriggerService.getModuleProperties();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/packages/CarSystemUI/res/layout/super_status_bar.xml b/packages/CarSystemUI/res/layout/super_status_bar.xml
index 728a239..e1bcc2e 100644
--- a/packages/CarSystemUI/res/layout/super_status_bar.xml
+++ b/packages/CarSystemUI/res/layout/super_status_bar.xml
@@ -42,6 +42,14 @@
</com.android.systemui.statusbar.BackDropView>
<com.android.systemui.statusbar.ScrimView
+ android:id="@+id/scrim_for_bubble"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:importantForAccessibility="no"
+ sysui:ignoreRightInset="true"
+ />
+
+ <com.android.systemui.statusbar.ScrimView
android:id="@+id/scrim_behind"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/packages/CarSystemUI/res/layout/trust_agent_unlock_dialog.xml b/packages/CarSystemUI/res/layout/trust_agent_unlock_dialog.xml
index 2d9901c..9df78f1 100644
--- a/packages/CarSystemUI/res/layout/trust_agent_unlock_dialog.xml
+++ b/packages/CarSystemUI/res/layout/trust_agent_unlock_dialog.xml
@@ -16,12 +16,13 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/layout"
+ android:id="@+id/unlock_dialog_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<LinearLayout
+ android:id="@+id/unlock_dialog"
android:layout_width="@dimen/unlock_dialog_width"
android:layout_height="wrap_content"
android:gravity="center"
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
index 013c63b..ec72ee7 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
@@ -52,7 +52,7 @@
* Not using Dialog because context passed from {@link FullscreenUserSwitcher} is not an
* activity.
*/
- private final View mUnlockDialog;
+ private final View mUnlockDialogLayout;
private final TextView mUnlockingText;
private final Button mButton;
private final IntentFilter mFilter;
@@ -70,14 +70,25 @@
mParams.packageName = mContext.getPackageName();
mParams.setTitle(mContext.getString(R.string.unlock_dialog_title));
- mUnlockDialog = LayoutInflater.from(mContext).inflate(
+ mUnlockDialogLayout = LayoutInflater.from(mContext).inflate(
R.layout.trust_agent_unlock_dialog, null);
- mUnlockDialog.setLayoutParams(mParams);
+ mUnlockDialogLayout.setLayoutParams(mParams);
- mUnlockingText = mUnlockDialog.findViewById(R.id.unlocking_text);
- mButton = mUnlockDialog.findViewById(R.id.enter_pin_button);
+ View dialogParent = mUnlockDialogLayout.findViewById(R.id.unlock_dialog_parent);
+ dialogParent.setOnTouchListener((v, event)-> {
+ hideUnlockDialog(/* dismissUserSwitcher= */ false);
+ return true;
+ });
+ View unlockDialog = mUnlockDialogLayout.findViewById(R.id.unlock_dialog);
+ unlockDialog.setOnTouchListener((v, event) -> {
+ // If the person taps inside the unlock dialog, the touch event will be intercepted here
+ // and the dialog will not exit
+ return true;
+ });
+ mUnlockingText = mUnlockDialogLayout.findViewById(R.id.unlocking_text);
+ mButton = mUnlockDialogLayout.findViewById(R.id.enter_pin_button);
mButton.setOnClickListener(v -> {
- hideUnlockDialog(/* notifyOnHideListener= */true);
+ hideUnlockDialog(/* dismissUserSwitcher= */true);
// TODO(b/138250105) Stop unlock advertising
});
@@ -133,7 +144,7 @@
if (!mUserManager.isUserUnlocked(uid)) {
logd("Showed unlock dialog for user: " + uid + " after " + delayMillis
+ " delay.");
- mWindowManager.addView(mUnlockDialog, mParams);
+ mWindowManager.addView(mUnlockDialogLayout, mParams);
}
}, delayMillis);
}
@@ -142,22 +153,22 @@
private void setUid(int uid) {
mUid = uid;
- TextView userName = mUnlockDialog.findViewById(R.id.user_name);
+ TextView userName = mUnlockDialogLayout.findViewById(R.id.user_name);
userName.setText(mUserManager.getUserInfo(mUid).name);
- ImageView avatar = mUnlockDialog.findViewById(R.id.avatar);
+ ImageView avatar = mUnlockDialogLayout.findViewById(R.id.avatar);
avatar.setImageBitmap(mUserManager.getUserIcon(mUid));
setButtonText();
}
- private void hideUnlockDialog(boolean notifyOnHideListener) {
+ private void hideUnlockDialog(boolean dismissUserSwitcher) {
if (!mIsDialogShowing) {
return;
}
- mWindowManager.removeView(mUnlockDialog);
+ mWindowManager.removeView(mUnlockDialogLayout);
logd("Receiver unregistered");
mContext.unregisterReceiver(this);
- if (notifyOnHideListener && mOnHideListener != null) {
- mOnHideListener.onHide();
+ if (mOnHideListener != null) {
+ mOnHideListener.onHide(dismissUserSwitcher);
}
mIsDialogShowing = false;
}
@@ -240,6 +251,6 @@
* Listener used to notify when the dialog is hidden
*/
interface OnHideListener {
- void onHide();
+ void onHide(boolean dismissUserSwitcher);
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 7cd6adb..0f7c1ee 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -34,6 +34,7 @@
import androidx.recyclerview.widget.GridLayoutManager;
import com.android.systemui.R;
+import com.android.systemui.statusbar.car.CarTrustAgentUnlockDialogHelper.OnHideListener;
import com.android.systemui.statusbar.car.UserGridRecyclerView.UserRecord;
/**
@@ -116,7 +117,7 @@
// Show unlock dialog for initial user
if (hasTrustedDevice(initialUser)) {
mUnlockDialogHelper.showUnlockDialogAfterDelay(initialUser,
- () -> dismissUserSwitcher());
+ mOnHideListener);
}
}
@@ -162,7 +163,7 @@
private void onUserSelected(UserGridRecyclerView.UserRecord record) {
mSelectedUser = record;
if (hasTrustedDevice(record.mInfo.id)) {
- mUnlockDialogHelper.showUnlockDialog(record.mInfo.id, () -> dismissUserSwitcher());
+ mUnlockDialogHelper.showUnlockDialog(record.mInfo.id, mOnHideListener);
return;
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
@@ -202,4 +203,18 @@
private boolean hasTrustedDevice(int uid) {
return !mEnrollmentManager.getEnrolledDeviceInfoForUser(uid).isEmpty();
}
+
+ private OnHideListener mOnHideListener = new OnHideListener() {
+ @Override
+ public void onHide(boolean dismissUserSwitcher) {
+ if (dismissUserSwitcher) {
+ dismissUserSwitcher();
+ } else {
+ // Re-draw the parent view, otherwise the unlock dialog will not be removed from
+ // the screen immediately.
+ mParent.invalidate();
+ }
+
+ }
+ };
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
index eeb6cb0..ea8a62f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
@@ -49,6 +49,7 @@
private final ArraySet<String> mWhitelistedApps = new ArraySet<>();
private final ArraySet<String> mSysWhitelistedApps = new ArraySet<>();
private final ArraySet<String> mSysWhitelistedAppsExceptIdle = new ArraySet<>();
+ private final ArraySet<String> mDefaultActiveApps = new ArraySet<>();
public PowerWhitelistBackend(Context context) {
this(context, IDeviceIdleController.Stub.asInterface(
@@ -90,17 +91,7 @@
// should be automatically whitelisted (otherwise user may be able to set restriction on
// them, leading to bad device behavior.)
- final boolean hasTelephony = mAppContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_TELEPHONY);
- final ComponentName defaultSms = SmsApplication.getDefaultSmsApplication(mAppContext,
- true /* updateIfNeeded */);
- if (hasTelephony && defaultSms != null && TextUtils.equals(pkg,
- defaultSms.getPackageName())) {
- return true;
- }
-
- final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mAppContext);
- if (hasTelephony && TextUtils.equals(pkg, defaultDialer)) {
+ if (mDefaultActiveApps.contains(pkg)) {
return true;
}
@@ -166,6 +157,7 @@
mSysWhitelistedApps.clear();
mSysWhitelistedAppsExceptIdle.clear();
mWhitelistedApps.clear();
+ mDefaultActiveApps.clear();
if (mDeviceIdleService == null) {
return;
}
@@ -183,6 +175,21 @@
for (String app : sysWhitelistedAppsExceptIdle) {
mSysWhitelistedAppsExceptIdle.add(app);
}
+ final boolean hasTelephony = mAppContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY);
+ final ComponentName defaultSms = SmsApplication.getDefaultSmsApplication(mAppContext,
+ true /* updateIfNeeded */);
+ final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(
+ mAppContext);
+
+ if (hasTelephony) {
+ if (defaultSms != null) {
+ mDefaultActiveApps.add(defaultSms.getPackageName());
+ }
+ if (!TextUtils.isEmpty(defaultDialer)) {
+ mDefaultActiveApps.add(defaultDialer);
+ }
+ }
} catch (RemoteException e) {
Log.w(TAG, "Unable to reach IDeviceIdleController", e);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixin.java b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixin.java
deleted file mode 100644
index fcf2363..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixin.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2016 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.settingslib.widget;
-
-import android.content.Context;
-
-import androidx.preference.PreferenceFragment;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.SetPreferenceScreen;
-
-/**
- * Framework mixin is deprecated, use the compat version instead.
- *
- * @deprecated
- */
-@Deprecated
-public class FooterPreferenceMixin implements LifecycleObserver, SetPreferenceScreen {
-
- private final PreferenceFragment mFragment;
- private FooterPreference mFooterPreference;
-
- public FooterPreferenceMixin(PreferenceFragment fragment, Lifecycle lifecycle) {
- mFragment = fragment;
- lifecycle.addObserver(this);
- }
-
- @Override
- public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
- if (mFooterPreference != null) {
- preferenceScreen.addPreference(mFooterPreference);
- }
- }
-
- /**
- * Creates a new {@link FooterPreference}.
- */
- public FooterPreference createFooterPreference() {
- final PreferenceScreen screen = mFragment.getPreferenceScreen();
- if (mFooterPreference != null && screen != null) {
- screen.removePreference(mFooterPreference);
- }
- mFooterPreference = new FooterPreference(getPrefContext());
-
- if (screen != null) {
- screen.addPreference(mFooterPreference);
- }
- return mFooterPreference;
- }
-
- /**
- * Returns an UI context with theme properly set for new Preference objects.
- */
- private Context getPrefContext() {
- return mFragment.getPreferenceManager().getContext();
- }
-
- public boolean hasFooter() {
- return mFooterPreference != null;
- }
-}
-
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java
deleted file mode 100644
index d45e56d..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2018 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.settingslib.widget;
-
-import android.content.Context;
-
-import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.SetPreferenceScreen;
-
-public class FooterPreferenceMixinCompat implements LifecycleObserver, SetPreferenceScreen {
-
- private final PreferenceFragmentCompat mFragment;
- private FooterPreference mFooterPreference;
-
- public FooterPreferenceMixinCompat(PreferenceFragmentCompat fragment, Lifecycle lifecycle) {
- mFragment = fragment;
- lifecycle.addObserver(this);
- }
-
- @Override
- public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
- if (mFooterPreference != null) {
- preferenceScreen.addPreference(mFooterPreference);
- }
- }
-
- /**
- * Creates a new {@link FooterPreference}.
- */
- public FooterPreference createFooterPreference() {
- final PreferenceScreen screen = mFragment.getPreferenceScreen();
- if (mFooterPreference != null && screen != null) {
- screen.removePreference(mFooterPreference);
- }
- mFooterPreference = new FooterPreference(getPrefContext());
-
- if (screen != null) {
- screen.addPreference(mFooterPreference);
- }
- return mFooterPreference;
- }
-
- /**
- * Returns an UI context with theme properly set for new Preference objects.
- */
- private Context getPrefContext() {
- return mFragment.getPreferenceManager().getContext();
- }
-
- public boolean hasFooter() {
- return mFooterPreference != null;
- }
-}
-
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
index 44ee423..3a571f9 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
@@ -117,6 +117,8 @@
final String testSms = "com.android.test.defaultsms";
ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver"));
+ mPowerWhitelistBackend.refreshList();
+
assertThat(mPowerWhitelistBackend.isWhitelisted(testSms)).isTrue();
assertThat(mPowerWhitelistBackend.isDefaultActiveApp(testSms)).isTrue();
}
@@ -126,6 +128,8 @@
final String testDialer = "com.android.test.defaultdialer";
ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer);
+ mPowerWhitelistBackend.refreshList();
+
assertThat(mPowerWhitelistBackend.isWhitelisted(testDialer)).isTrue();
assertThat(mPowerWhitelistBackend.isDefaultActiveApp(testDialer)).isTrue();
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java
deleted file mode 100644
index 601da051..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2016 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.settingslib.widget;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class FooterPreferenceMixinCompatTest {
-
- @Mock
- private PreferenceFragmentCompat mFragment;
- @Mock
- private PreferenceScreen mScreen;
-
- private LifecycleOwner mLifecycleOwner;
- private Lifecycle mLifecycle;
- private FooterPreferenceMixinCompat mMixin;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mLifecycleOwner = () -> mLifecycle;
- mLifecycle = new Lifecycle(mLifecycleOwner);
- when(mFragment.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
- when(mFragment.getPreferenceManager().getContext())
- .thenReturn(RuntimeEnvironment.application);
- mMixin = new FooterPreferenceMixinCompat(mFragment, mLifecycle);
- }
-
- @Test
- public void createFooter_screenNotAvailable_noCrash() {
- assertThat(mMixin.createFooterPreference()).isNotNull();
- }
-
- @Test
- public void createFooter_screenAvailable_canAttachToScreen() {
- when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
-
- final FooterPreference preference = mMixin.createFooterPreference();
-
- assertThat(preference).isNotNull();
- verify(mScreen).addPreference(preference);
- }
-
- @Test
- public void createFooter_screenAvailableDelayed_canAttachToScreen() {
- final FooterPreference preference = mMixin.createFooterPreference();
-
- mLifecycle.setPreferenceScreen(mScreen);
-
- assertThat(preference).isNotNull();
- verify(mScreen).addPreference(preference);
- }
-
- @Test
- public void createFooterTwice_screenAvailable_replaceOldFooter() {
- when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
-
- mMixin.createFooterPreference();
- mMixin.createFooterPreference();
-
- verify(mScreen).removePreference(any(FooterPreference.class));
- verify(mScreen, times(2)).addPreference(any(FooterPreference.class));
- }
-}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
deleted file mode 100644
index 7ae5d2d..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2016 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.settingslib.widget;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class FooterPreferenceMixinTest {
-
- @Mock
- private PreferenceFragment mFragment;
- @Mock
- private PreferenceScreen mScreen;
-
- private LifecycleOwner mLifecycleOwner;
- private Lifecycle mLifecycle;
- private FooterPreferenceMixin mMixin;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mLifecycleOwner = () -> mLifecycle;
- mLifecycle = new Lifecycle(mLifecycleOwner);
- when(mFragment.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
- when(mFragment.getPreferenceManager().getContext())
- .thenReturn(RuntimeEnvironment.application);
- mMixin = new FooterPreferenceMixin(mFragment, mLifecycle);
- }
-
- @Test
- public void createFooter_screenNotAvailable_noCrash() {
- assertThat(mMixin.createFooterPreference()).isNotNull();
- }
-
- @Test
- public void createFooter_screenAvailable_canAttachToScreen() {
- when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
-
- final FooterPreference preference = mMixin.createFooterPreference();
-
- assertThat(preference).isNotNull();
- verify(mScreen).addPreference(preference);
- }
-
- @Test
- public void createFooter_screenAvailableDelayed_canAttachToScreen() {
- final FooterPreference preference = mMixin.createFooterPreference();
-
- mLifecycle.setPreferenceScreen(mScreen);
-
- assertThat(preference).isNotNull();
- verify(mScreen).addPreference(preference);
- }
-
- @Test
- public void createFooterTwice_screenAvailable_replaceOldFooter() {
- when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
-
- mMixin.createFooterPreference();
- mMixin.createFooterPreference();
-
- verify(mScreen).removePreference(any(FooterPreference.class));
- verify(mScreen, times(2)).addPreference(any(FooterPreference.class));
- }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
new file mode 100644
index 0000000..30be775
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.pip;
+
+import static android.util.TypedValue.COMPLEX_UNIT_DIP;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.Size;
+import android.util.TypedValue;
+import android.view.DisplayInfo;
+import android.view.Gravity;
+import android.view.IPinnedStackController;
+import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
+
+import com.android.internal.policy.PipSnapAlgorithm;
+
+import java.io.PrintWriter;
+
+/**
+ * Handles bounds calculation for PIP on Phone and other form factors, it keeps tracking variant
+ * state changes originated from Window Manager and is the source of truth for PiP window bounds.
+ */
+public class PipBoundsHandler {
+
+ private static final String TAG = PipBoundsHandler.class.getSimpleName();
+ private static final float INVALID_SNAP_FRACTION = -1f;
+
+ // System.identityHashCode guarantees zero for null object.
+ private static final int INVALID_SYSTEM_IDENTITY_TOKEN = 0;
+
+ private final Context mContext;
+ private final IWindowManager mWindowManager;
+ private final PipSnapAlgorithm mSnapAlgorithm;
+ private final DisplayInfo mDisplayInfo = new DisplayInfo();
+ private final Rect mStableInsets = new Rect();
+ private final Rect mTmpInsets = new Rect();
+ private final Point mTmpDisplaySize = new Point();
+
+ private IPinnedStackController mPinnedStackController;
+ private int mLastPipToken;
+ private float mReentrySnapFraction = INVALID_SNAP_FRACTION;
+
+ private float mDefaultAspectRatio;
+ private float mMinAspectRatio;
+ private float mMaxAspectRatio;
+ private float mAspectRatio;
+ private int mDefaultStackGravity;
+ private int mDefaultMinSize;
+ private Point mScreenEdgeInsets;
+ private int mCurrentMinSize;
+
+ private boolean mIsMinimized;
+ private boolean mIsImeShowing;
+ private int mImeHeight;
+ private boolean mIsShelfShowing;
+ private int mShelfHeight;
+
+ public PipBoundsHandler(Context context) {
+ mContext = context;
+ mSnapAlgorithm = new PipSnapAlgorithm(context);
+ mWindowManager = WindowManagerGlobal.getWindowManagerService();
+ mAspectRatio = mDefaultAspectRatio;
+ reloadResources();
+ }
+
+ /**
+ * TODO: move the resources to SysUI package.
+ */
+ private void reloadResources() {
+ final Resources res = mContext.getResources();
+ mDefaultAspectRatio = res.getFloat(
+ com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio);
+ mDefaultStackGravity = res.getInteger(
+ com.android.internal.R.integer.config_defaultPictureInPictureGravity);
+ mDefaultMinSize = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.default_minimal_size_pip_resizable_task);
+ mCurrentMinSize = mDefaultMinSize;
+ final String screenEdgeInsetsDpString = res.getString(
+ com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets);
+ final Size screenEdgeInsetsDp = !screenEdgeInsetsDpString.isEmpty()
+ ? Size.parseSize(screenEdgeInsetsDpString)
+ : null;
+ mScreenEdgeInsets = screenEdgeInsetsDp == null ? new Point()
+ : new Point(dpToPx(screenEdgeInsetsDp.getWidth(), res.getDisplayMetrics()),
+ dpToPx(screenEdgeInsetsDp.getHeight(), res.getDisplayMetrics()));
+ mMinAspectRatio = res.getFloat(
+ com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
+ mMaxAspectRatio = res.getFloat(
+ com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio);
+ }
+
+ public void setPinnedStackController(IPinnedStackController controller) {
+ mPinnedStackController = controller;
+ }
+
+ public void setMinEdgeSize(int minEdgeSize) {
+ mCurrentMinSize = minEdgeSize;
+ }
+
+ /**
+ * Responds to IPinnedStackListener on IME visibility change.
+ */
+ public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
+ mIsImeShowing = imeVisible;
+ mImeHeight = imeHeight;
+ }
+
+ /**
+ * Responds to IPinnedStackListener on shelf visibility change.
+ */
+ public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {
+ mIsShelfShowing = shelfVisible;
+ mShelfHeight = shelfHeight;
+ }
+
+ /**
+ * Responds to IPinnedStackListener on minimized state change.
+ */
+ public void onMinimizedStateChanged(boolean minimized) {
+ mIsMinimized = minimized;
+ }
+
+ /**
+ * Responds to IPinnedStackListener on movement bounds change.
+ * Note that both inset and normal bounds will be calculated here rather than in the caller.
+ */
+ public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
+ Rect animatingBounds, DisplayInfo displayInfo) {
+ getInsetBounds(insetBounds);
+ final Rect defaultBounds = getDefaultBounds(INVALID_SNAP_FRACTION);
+ normalBounds.set(defaultBounds);
+ if (animatingBounds.isEmpty()) {
+ animatingBounds.set(defaultBounds);
+ }
+ if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
+ transformBoundsToAspectRatio(normalBounds, mAspectRatio,
+ false /* useCurrentMinEdgeSize */);
+ }
+ displayInfo.copyFrom(mDisplayInfo);
+ }
+
+ /**
+ * Responds to IPinnedStackListener on saving reentry snap fraction for a given token.
+ * Token should be generated via {@link System#identityHashCode(Object)}
+ */
+ public void onSaveReentrySnapFraction(int token, Rect stackBounds) {
+ mReentrySnapFraction = getSnapFraction(stackBounds);
+ mLastPipToken = token;
+ }
+
+ /**
+ * Responds to IPinnedStackListener on resetting reentry snap fraction for a given token.
+ * Token should be generated via {@link System#identityHashCode(Object)}
+ */
+ public void onResetReentrySnapFraction(int token) {
+ if (mLastPipToken == token) {
+ onResetReentrySnapFractionUnchecked();
+ }
+ }
+
+ private void onResetReentrySnapFractionUnchecked() {
+ mReentrySnapFraction = INVALID_SNAP_FRACTION;
+ mLastPipToken = INVALID_SYSTEM_IDENTITY_TOKEN;
+ }
+
+ /**
+ * Responds to IPinnedStackListener on {@link DisplayInfo} change.
+ * It will normally follow up with a
+ * {@link #onMovementBoundsChanged(Rect, Rect, Rect, DisplayInfo)} callback.
+ */
+ public void onDisplayInfoChanged(DisplayInfo displayInfo) {
+ mDisplayInfo.copyFrom(displayInfo);
+ }
+
+ /**
+ * Responds to IPinnedStackListener on configuration change.
+ */
+ public void onConfigurationChanged() {
+ reloadResources();
+ }
+
+ /**
+ * Responds to IPinnedStackListener on resetting aspect ratio for the pinned window.
+ * It will normally follow up with a
+ * {@link #onMovementBoundsChanged(Rect, Rect, Rect, DisplayInfo)} callback.
+ */
+ public void onAspectRatioChanged(float aspectRatio) {
+ mAspectRatio = aspectRatio;
+ }
+
+ /**
+ * Responds to IPinnedStackListener on preparing the pinned stack animation.
+ */
+ public void onPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect stackBounds) {
+ final Rect targetStackBounds;
+ if (stackBounds == null) {
+ targetStackBounds = getDefaultBounds(mReentrySnapFraction);
+ } else {
+ targetStackBounds = new Rect();
+ targetStackBounds.set(stackBounds);
+ }
+ if (isValidPictureInPictureAspectRatio(aspectRatio)) {
+ transformBoundsToAspectRatio(targetStackBounds, aspectRatio,
+ true /* useCurrentMinEdgeSize */);
+ }
+ if (targetStackBounds.equals(stackBounds)) {
+ return;
+ }
+ mAspectRatio = aspectRatio;
+ onResetReentrySnapFractionUnchecked();
+ // TODO: callback Window Manager on starting animation with calculated bounds
+ }
+
+ /**
+ * @return whether the given {@param aspectRatio} is valid.
+ */
+ private boolean isValidPictureInPictureAspectRatio(float aspectRatio) {
+ return Float.compare(mMinAspectRatio, aspectRatio) <= 0
+ && Float.compare(aspectRatio, mMaxAspectRatio) <= 0;
+ }
+
+ /**
+ * Set the current bounds (or the default bounds if there are no current bounds) with the
+ * specified aspect ratio.
+ */
+ private void transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio,
+ boolean useCurrentMinEdgeSize) {
+ // Save the snap fraction, calculate the aspect ratio based on screen size
+ final float snapFraction = mSnapAlgorithm.getSnapFraction(stackBounds,
+ getMovementBounds(stackBounds));
+
+ final int minEdgeSize = useCurrentMinEdgeSize ? mCurrentMinSize : mDefaultMinSize;
+ final Size size = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, minEdgeSize,
+ mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+ final int left = (int) (stackBounds.centerX() - size.getWidth() / 2f);
+ final int top = (int) (stackBounds.centerY() - size.getHeight() / 2f);
+ stackBounds.set(left, top, left + size.getWidth(), top + size.getHeight());
+ mSnapAlgorithm.applySnapFraction(stackBounds, getMovementBounds(stackBounds), snapFraction);
+ if (mIsMinimized) {
+ applyMinimizedOffset(stackBounds, getMovementBounds(stackBounds));
+ }
+ }
+
+ /**
+ * @return the default bounds to show the PIP, if a {@param snapFraction} is provided, then it
+ * will apply the default bounds to the provided snap fraction.
+ */
+ private Rect getDefaultBounds(float snapFraction) {
+ final Rect insetBounds = new Rect();
+ getInsetBounds(insetBounds);
+
+ final Rect defaultBounds = new Rect();
+ final Size size = mSnapAlgorithm.getSizeForAspectRatio(mDefaultAspectRatio,
+ mDefaultMinSize, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+ if (snapFraction != INVALID_SNAP_FRACTION) {
+ defaultBounds.set(0, 0, size.getWidth(), size.getHeight());
+ final Rect movementBounds = getMovementBounds(defaultBounds);
+ mSnapAlgorithm.applySnapFraction(defaultBounds, movementBounds, snapFraction);
+ } else {
+ Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds,
+ 0, Math.max(mIsImeShowing ? mImeHeight : 0,
+ mIsShelfShowing ? mShelfHeight : 0),
+ defaultBounds);
+ }
+ return defaultBounds;
+ }
+
+ /**
+ * Populates the bounds on the screen that the PIP can be visible in.
+ */
+ private void getInsetBounds(Rect outRect) {
+ try {
+ mWindowManager.getStableInsets(mContext.getDisplayId(), mTmpInsets);
+ outRect.set(mTmpInsets.left + mScreenEdgeInsets.x,
+ mTmpInsets.top + mScreenEdgeInsets.y,
+ mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x,
+ mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to get stable insets from WM", e);
+ }
+ }
+
+ /**
+ * @return the movement bounds for the given {@param stackBounds} and the current state of the
+ * controller.
+ */
+ private Rect getMovementBounds(Rect stackBounds) {
+ return getMovementBounds(stackBounds, true /* adjustForIme */);
+ }
+
+ /**
+ * @return the movement bounds for the given {@param stackBounds} and the current state of the
+ * controller.
+ */
+ private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) {
+ final Rect movementBounds = new Rect();
+ getInsetBounds(movementBounds);
+
+ // Apply the movement bounds adjustments based on the current state.
+ mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
+ (adjustForIme && mIsImeShowing) ? mImeHeight : 0);
+ return movementBounds;
+ }
+
+ /**
+ * Applies the minimized offsets to the given stack bounds.
+ */
+ private void applyMinimizedOffset(Rect stackBounds, Rect movementBounds) {
+ mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+ try {
+ mWindowManager.getStableInsets(mContext.getDisplayId(), mStableInsets);
+ mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize,
+ mStableInsets);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to get stable insets from WM", e);
+ }
+ }
+
+ /**
+ * @return the default snap fraction to apply instead of the default gravity when calculating
+ * the default stack bounds when first entering PiP.
+ */
+ private float getSnapFraction(Rect stackBounds) {
+ return mSnapAlgorithm.getSnapFraction(stackBounds, getMovementBounds(stackBounds));
+ }
+
+ /**
+ * @return the pixels for a given dp value.
+ */
+ private int dpToPx(float dpValue, DisplayMetrics dm) {
+ return (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, dpValue, dm);
+ }
+
+ /**
+ * Dumps internal states.
+ */
+ public void dump(PrintWriter pw, String prefix) {
+ final String innerPrefix = prefix + " ";
+ pw.println(prefix + TAG);
+ pw.println(innerPrefix + "mReentrySnapFraction=" + mReentrySnapFraction);
+ pw.println(innerPrefix + "mDisplayInfo=" + mDisplayInfo);
+ pw.println(innerPrefix + "mDefaultAspectRatio=" + mDefaultAspectRatio);
+ pw.println(innerPrefix + "mMinAspectRatio=" + mMinAspectRatio);
+ pw.println(innerPrefix + "mMaxAspectRatio=" + mMaxAspectRatio);
+ pw.println(innerPrefix + "mAspectRatio=" + mAspectRatio);
+ pw.println(innerPrefix + "mDefaultStackGravity=" + mDefaultStackGravity);
+ pw.println(innerPrefix + "mIsMinimized=" + mIsMinimized);
+ pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing);
+ pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
+ pw.println(innerPrefix + "mIsShelfShowing=" + mIsShelfShowing);
+ pw.println(innerPrefix + "mShelfHeight=" + mShelfHeight);
+ mSnapAlgorithm.dump(pw, innerPrefix);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 83b000d..38153ec 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -38,8 +38,8 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSDetailClipper;
@@ -52,6 +52,8 @@
import java.util.ArrayList;
import java.util.List;
+import javax.inject.Inject;
+
/**
* Allows full-screen customization of QS, through show() and hide().
*
@@ -66,6 +68,8 @@
private final QSDetailClipper mClipper;
private final LightBarController mLightBarController;
+ private KeyguardMonitor mKeyguardMonitor;
+ private final ScreenLifecycle mScreenLifecycle;
private final TileQueryHelper mTileQueryHelper;
private final View mTransparentView;
@@ -82,7 +86,11 @@
private boolean mOpening;
private boolean mIsShowingNavBackdrop;
- public QSCustomizer(Context context, AttributeSet attrs) {
+ @Inject
+ public QSCustomizer(Context context, AttributeSet attrs,
+ LightBarController lightBarController,
+ KeyguardMonitor keyguardMonitor,
+ ScreenLifecycle screenLifecycle) {
super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
LayoutInflater.from(getContext()).inflate(R.layout.qs_customize_panel_content, this);
@@ -115,7 +123,9 @@
DefaultItemAnimator animator = new DefaultItemAnimator();
animator.setMoveDuration(TileAdapter.MOVE_DURATION);
mRecyclerView.setItemAnimator(animator);
- mLightBarController = Dependency.get(LightBarController.class);
+ mLightBarController = lightBarController;
+ mKeyguardMonitor = keyguardMonitor;
+ mScreenLifecycle = screenLifecycle;
updateNavBackDrop(getResources().getConfiguration());
}
@@ -177,7 +187,7 @@
queryTiles();
mNotifQsContainer.setCustomizerAnimating(true);
mNotifQsContainer.setCustomizerShowing(true);
- Dependency.get(KeyguardMonitor.class).addCallback(mKeyguardCallback);
+ mKeyguardMonitor.addCallback(mKeyguardCallback);
updateNavColors();
}
}
@@ -193,7 +203,7 @@
queryTiles();
mNotifQsContainer.setCustomizerAnimating(false);
mNotifQsContainer.setCustomizerShowing(true);
- Dependency.get(KeyguardMonitor.class).addCallback(mKeyguardCallback);
+ mKeyguardMonitor.addCallback(mKeyguardCallback);
updateNavColors();
}
}
@@ -203,16 +213,21 @@
}
public void hide() {
+ final boolean animate = mScreenLifecycle.getScreenState() != ScreenLifecycle.SCREEN_OFF;
if (isShown) {
MetricsLogger.hidden(getContext(), MetricsProto.MetricsEvent.QS_EDIT);
isShown = false;
mToolbar.dismissPopupMenus();
setCustomizing(false);
save();
- mClipper.animateCircularClip(mX, mY, false, mCollapseAnimationListener);
- mNotifQsContainer.setCustomizerAnimating(true);
+ if (animate) {
+ mClipper.animateCircularClip(mX, mY, false, mCollapseAnimationListener);
+ } else {
+ setVisibility(View.GONE);
+ }
+ mNotifQsContainer.setCustomizerAnimating(animate);
mNotifQsContainer.setCustomizerShowing(false);
- Dependency.get(KeyguardMonitor.class).removeCallback(mKeyguardCallback);
+ mKeyguardMonitor.removeCallback(mKeyguardCallback);
updateNavColors();
}
}
@@ -268,7 +283,7 @@
public void saveInstanceState(Bundle outState) {
if (isShown) {
- Dependency.get(KeyguardMonitor.class).removeCallback(mKeyguardCallback);
+ mKeyguardMonitor.removeCallback(mKeyguardCallback);
}
outState.putBoolean(EXTRA_QS_CUSTOMIZING, mCustomizing);
}
@@ -300,7 +315,7 @@
@Override
public void onKeyguardShowingChanged() {
if (!isAttachedToWindow()) return;
- if (Dependency.get(KeyguardMonitor.class).isShowing() && !mOpening) {
+ if (mKeyguardMonitor.isShowing() && !mOpening) {
hide();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index d6dad68..187a3bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -76,7 +76,7 @@
UserSwitcherController.UserRecord item) {
UserDetailItemView v = UserDetailItemView.convertOrInflate(
mContext, convertView, parent);
- if ((v != convertView && !item.isCurrent) || item.isGuest) {
+ if (!item.isCurrent || item.isGuest) {
v.setOnClickListener(this);
} else {
v.setOnClickListener(null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 6556ed0..2ae2ac5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -653,7 +653,6 @@
if (!updateMonitor.isUnlockingWithBiometricAllowed()) {
return;
}
- animatePadlockError();
boolean showSwipeToUnlock =
msgId == KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index a58ba85..256c8e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1798,7 +1798,8 @@
private void setQsExpansion(float height) {
height = Math.min(Math.max(height, mQsMinExpansionHeight), mQsMaxExpansionHeight);
mQsFullyExpanded = height == mQsMaxExpansionHeight && mQsMaxExpansionHeight != 0;
- if (height > mQsMinExpansionHeight && !mQsExpanded && !mStackScrollerOverscrolling) {
+ if (height > mQsMinExpansionHeight && !mQsExpanded && !mStackScrollerOverscrolling
+ && !mDozing) {
setQsExpanded(true);
} else if (height <= mQsMinExpansionHeight && mQsExpanded) {
setQsExpanded(false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index e1ef809..6dc90b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -19,7 +19,6 @@
public interface KeyguardMonitor extends CallbackController<Callback> {
boolean isSecure();
- boolean canSkipBouncer();
boolean isShowing();
boolean isOccluded();
boolean isKeyguardFadingAway();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index a950626..e8b0f9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -17,14 +17,12 @@
package com.android.systemui.statusbar.policy;
import android.annotation.NonNull;
-import android.app.ActivityManager;
import android.content.Context;
import com.android.internal.util.Preconditions;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dependency;
-import com.android.systemui.settings.CurrentUserTracker;
import java.util.ArrayList;
@@ -40,14 +38,11 @@
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
private final Context mContext;
- private final CurrentUserTracker mUserTracker;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- private int mCurrentUser;
private boolean mShowing;
private boolean mSecure;
private boolean mOccluded;
- private boolean mCanSkipBouncer;
private boolean mListening;
private boolean mKeyguardFadingAway;
@@ -63,13 +58,6 @@
public KeyguardMonitorImpl(Context context) {
mContext = context;
mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
- mUserTracker = new CurrentUserTracker(mContext) {
- @Override
- public void onUserSwitched(int newUserId) {
- mCurrentUser = newUserId;
- updateCanSkipBouncerState();
- }
- };
}
@Override
@@ -78,10 +66,7 @@
mCallbacks.add(callback);
if (mCallbacks.size() != 0 && !mListening) {
mListening = true;
- mCurrentUser = ActivityManager.getCurrentUser();
- updateCanSkipBouncerState();
mKeyguardUpdateMonitor.registerCallback(this);
- mUserTracker.startTracking();
}
}
@@ -91,7 +76,6 @@
if (mCallbacks.remove(callback) && mCallbacks.size() == 0 && mListening) {
mListening = false;
mKeyguardUpdateMonitor.removeCallback(this);
- mUserTracker.stopTracking();
}
}
@@ -110,11 +94,6 @@
return mOccluded;
}
- @Override
- public boolean canSkipBouncer() {
- return mCanSkipBouncer;
- }
-
public void notifyKeyguardState(boolean showing, boolean secure, boolean occluded) {
if (mShowing == showing && mSecure == secure && mOccluded == occluded) return;
mShowing = showing;
@@ -125,7 +104,6 @@
@Override
public void onTrustChanged(int userId) {
- updateCanSkipBouncerState();
notifyKeyguardChanged();
}
@@ -133,10 +111,6 @@
return mKeyguardUpdateMonitor.isDeviceInteractive();
}
- private void updateCanSkipBouncerState() {
- mCanSkipBouncer = mKeyguardUpdateMonitor.getUserCanSkipBouncer(mCurrentUser);
- }
-
private void notifyKeyguardChanged() {
// Copy the list to allow removal during callback.
new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardShowingChanged);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 2e1e520..4fa4b6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -62,6 +62,7 @@
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.tiles.UserDetailView;
import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.phone.UnlockMethodCache;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -597,17 +598,19 @@
final UserSwitcherController mController;
private final KeyguardMonitor mKeyguardMonitor;
+ private final UnlockMethodCache mUnlockMethodCache;
protected BaseUserAdapter(UserSwitcherController controller) {
mController = controller;
mKeyguardMonitor = controller.mKeyguardMonitor;
+ mUnlockMethodCache = UnlockMethodCache.getInstance(controller.mContext);
controller.addAdapter(new WeakReference<>(this));
}
public int getUserCount() {
boolean secureKeyguardShowing = mKeyguardMonitor.isShowing()
&& mKeyguardMonitor.isSecure()
- && !mKeyguardMonitor.canSkipBouncer();
+ && !mUnlockMethodCache.canSkipBouncer();
if (!secureKeyguardShowing) {
return mController.getUsers().size();
}
@@ -629,7 +632,7 @@
public int getCount() {
boolean secureKeyguardShowing = mKeyguardMonitor.isShowing()
&& mKeyguardMonitor.isSecure()
- && !mKeyguardMonitor.canSkipBouncer();
+ && !mUnlockMethodCache.canSkipBouncer();
if (!secureKeyguardShowing) {
return mController.getUsers().size();
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index 9b264c4..e44e58a 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -32,6 +32,7 @@
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.QuickStatusBarHeader;
+import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.phone.LockIcon;
@@ -172,6 +173,11 @@
* Creates the QuickQSPanel.
*/
QuickQSPanel createQuickQSPanel();
+
+ /**
+ * Creates the QSCustomizer.
+ */
+ QSCustomizer createQSCustomizer();
}
/**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index f2292fd..07fbbcf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -97,6 +97,8 @@
mLooper.getLooper(),
mPluginManager, mTunerService, mAutoTiles, mDumpController);
setUpTileFactory();
+ Settings.Secure.putStringForUser(mContext.getContentResolver(), QSTileHost.TILES_SETTING,
+ "", ActivityManager.getCurrentUser());
}
private void setUpTileFactory() {
@@ -188,7 +190,8 @@
// changed
String newSetting = Settings.Secure.getStringForUser(getContext().getContentResolver(),
TILES_SETTING, ActivityManager.getCurrentUser());
- if (!previousSetting.equals(newSetting)) {
+ // newSetting is not null, as it has just been set.
+ if (!newSetting.equals(previousSetting)) {
onTuningChanged(TILES_SETTING, newSetting);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
new file mode 100644
index 0000000..b51e716
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.qs.tiles
+
+import android.content.Context
+import android.content.pm.UserInfo
+import android.graphics.Bitmap
+import android.testing.AndroidTestingRunner
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.policy.UserSwitcherController
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class UserDetailViewAdapterTest : SysuiTestCase() {
+
+ @Mock private lateinit var mUserSwitcherController: UserSwitcherController
+ @Mock private lateinit var mParent: ViewGroup
+ @Mock private lateinit var mUserDetailItemView: UserDetailItemView
+ @Mock private lateinit var mOtherView: View
+ @Mock private lateinit var mInflatedUserDetailItemView: UserDetailItemView
+ @Mock private lateinit var mUserInfo: UserInfo
+ @Mock private lateinit var mPicture: Bitmap
+ @Mock private lateinit var mLayoutInflater: LayoutInflater
+ private lateinit var adapter: UserDetailView.Adapter
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, mLayoutInflater)
+ `when`(mLayoutInflater.inflate(anyInt(), any(ViewGroup::class.java), anyBoolean()))
+ .thenReturn(mInflatedUserDetailItemView)
+ adapter = UserDetailView.Adapter(mContext, mUserSwitcherController)
+ }
+
+ private fun clickableTest(
+ current: Boolean,
+ guest: Boolean,
+ convertView: View,
+ shouldBeClickable: Boolean
+ ) {
+ val user = createUserRecord(current, guest)
+ val v = adapter.createUserDetailItemView(convertView, mParent, user)
+ if (shouldBeClickable) {
+ verify(v).setOnClickListener(adapter)
+ } else {
+ verify(v).setOnClickListener(null)
+ }
+ }
+
+ @Test
+ fun testGuestIsClickable_differentViews_notCurrent() {
+ clickableTest(false, true, mOtherView, true)
+ }
+
+ @Test
+ fun testGuestIsClickable_differentViews_Current() {
+ clickableTest(true, true, mOtherView, true)
+ }
+
+ @Test
+ fun testGuestIsClickable_sameView_notCurrent() {
+ clickableTest(false, true, mUserDetailItemView, true)
+ }
+
+ @Test
+ fun testGuestIsClickable_sameView_Current() {
+ clickableTest(true, true, mUserDetailItemView, true)
+ }
+
+ @Test
+ fun testNotGuestCurrentUserIsNotClickable_otherView() {
+ clickableTest(true, false, mOtherView, false)
+ }
+
+ @Test
+ fun testNotGuestCurrentUserIsNotClickable_sameView() {
+ clickableTest(true, false, mUserDetailItemView, false)
+ }
+
+ @Test
+ fun testNotGuestNotCurrentUserIsClickable_otherView() {
+ clickableTest(false, false, mOtherView, true)
+ }
+
+ @Test
+ fun testNotGuestNotCurrentUserIsClickable_sameView() {
+ clickableTest(false, false, mUserDetailItemView, true)
+ }
+
+ private fun createUserRecord(current: Boolean, guest: Boolean) =
+ UserSwitcherController.UserRecord(
+ mUserInfo,
+ mPicture,
+ guest,
+ current,
+ false /* isAddUser */,
+ false /* isRestricted */,
+ true /* isSwitchToEnabled */)
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
index 95c7a4d..2fb0e0e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
@@ -80,9 +80,4 @@
public long calculateGoingToFullShadeDelay() {
return 0;
}
-
- @Override
- public boolean canSkipBouncer() {
- return false;
- }
}
diff --git a/packages/WAPPushManager/Android.bp b/packages/WAPPushManager/Android.bp
index 1bec492..c391369 100644
--- a/packages/WAPPushManager/Android.bp
+++ b/packages/WAPPushManager/Android.bp
@@ -9,4 +9,6 @@
optimize: {
proguard_flags_files: ["proguard.flags"],
},
+
+ product_specific: true,
}
diff --git a/packages/WAPPushManager/CleanSpec.mk b/packages/WAPPushManager/CleanSpec.mk
index b84e1b6..2dcbb10 100644
--- a/packages/WAPPushManager/CleanSpec.mk
+++ b/packages/WAPPushManager/CleanSpec.mk
@@ -47,3 +47,5 @@
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/WAPPushManager)
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 73ec561..e194f72 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -29,7 +29,6 @@
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
-import android.os.SystemClock;
import android.provider.DeviceConfig;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -117,6 +116,10 @@
private final AtomicFile mPolicyFile;
private final ExplicitHealthCheckController mHealthCheckController;
private final ConnectivityModuleConnector mConnectivityModuleConnector;
+ private final Runnable mSyncRequests = this::syncRequests;
+ private final Runnable mSyncStateWithScheduledReason = this::syncStateWithScheduledReason;
+ private final Runnable mSaveToFile = this::saveToFile;
+ private final SystemClock mSystemClock;
@GuardedBy("mLock")
private boolean mIsPackagesReady;
// Flag to control whether explicit health checks are supported or not
@@ -131,9 +134,11 @@
@GuardedBy("mLock")
private long mUptimeAtLastStateSync;
- private final Runnable mSyncRequests = this::syncRequests;
- private final Runnable mSyncStateWithScheduledReason = this::syncStateWithScheduledReason;
- private final Runnable mSaveToFile = this::saveToFile;
+ @FunctionalInterface
+ @VisibleForTesting
+ interface SystemClock {
+ long uptimeMillis();
+ }
private PackageWatchdog(Context context) {
// Needs to be constructed inline
@@ -142,7 +147,8 @@
"package-watchdog.xml")),
new Handler(Looper.myLooper()), BackgroundThread.getHandler(),
new ExplicitHealthCheckController(context),
- ConnectivityModuleConnector.getInstance());
+ ConnectivityModuleConnector.getInstance(),
+ android.os.SystemClock::uptimeMillis);
}
/**
@@ -151,13 +157,14 @@
@VisibleForTesting
PackageWatchdog(Context context, AtomicFile policyFile, Handler shortTaskHandler,
Handler longTaskHandler, ExplicitHealthCheckController controller,
- ConnectivityModuleConnector connectivityModuleConnector) {
+ ConnectivityModuleConnector connectivityModuleConnector, SystemClock clock) {
mContext = context;
mPolicyFile = policyFile;
mShortTaskHandler = shortTaskHandler;
mLongTaskHandler = longTaskHandler;
mHealthCheckController = controller;
mConnectivityModuleConnector = connectivityModuleConnector;
+ mSystemClock = clock;
loadFromFile();
}
@@ -579,7 +586,7 @@
mUptimeAtLastStateSync = 0;
} else {
Slog.i(TAG, "Scheduling next state sync in " + durationMs + "ms");
- mUptimeAtLastStateSync = SystemClock.uptimeMillis();
+ mUptimeAtLastStateSync = mSystemClock.uptimeMillis();
mShortTaskHandler.postDelayed(mSyncStateWithScheduledReason, durationMs);
}
}
@@ -612,7 +619,7 @@
@GuardedBy("mLock")
private void pruneObserversLocked() {
long elapsedMs = mUptimeAtLastStateSync == 0
- ? 0 : SystemClock.uptimeMillis() - mUptimeAtLastStateSync;
+ ? 0 : mSystemClock.uptimeMillis() - mUptimeAtLastStateSync;
if (elapsedMs <= 0) {
Slog.i(TAG, "Not pruning observers, elapsed time: " + elapsedMs + "ms");
return;
@@ -1036,7 +1043,7 @@
*/
@GuardedBy("mLock")
public boolean onFailureLocked() {
- final long now = SystemClock.uptimeMillis();
+ final long now = mSystemClock.uptimeMillis();
final long duration = now - mUptimeStartMs;
if (duration > mTriggerFailureDurationMs) {
// TODO(b/120598832): Reseting to 1 is not correct
diff --git a/services/core/java/com/android/server/RecoverySystemService.java b/services/core/java/com/android/server/RecoverySystemService.java
index 997178e..1517887 100644
--- a/services/core/java/com/android/server/RecoverySystemService.java
+++ b/services/core/java/com/android/server/RecoverySystemService.java
@@ -25,12 +25,15 @@
import android.os.RecoverySystem;
import android.os.RemoteException;
import android.os.SystemProperties;
+import android.system.ErrnoException;
+import android.system.Os;
import android.util.Slog;
import libcore.io.IoUtils;
import java.io.DataInputStream;
import java.io.DataOutputStream;
+import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
@@ -285,6 +288,7 @@
byte[] cmdUtf8 = command.getBytes("UTF-8");
dos.writeInt(cmdUtf8.length);
dos.write(cmdUtf8, 0, cmdUtf8.length);
+ dos.flush();
}
// Read the status from the socket.
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 8eb5d9b..1675b94 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -829,6 +829,15 @@
}
}
+ void killMisbehavingService(ServiceRecord r,
+ int appUid, int appPid, String localPackageName) {
+ synchronized (mAm) {
+ stopServiceLocked(r);
+ mAm.crashApplication(appUid, appPid, localPackageName, -1,
+ "Bad notification for startForeground", true /*force*/);
+ }
+ }
+
IBinder peekServiceLocked(Intent service, String resolvedType, String callingPackage) {
ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, callingPackage,
Binder.getCallingPid(), Binder.getCallingUid(),
@@ -3930,7 +3939,7 @@
void serviceForegroundCrash(ProcessRecord app, CharSequence serviceRecord) {
mAm.crashApplication(app.uid, app.pid, app.info.packageName, app.userId,
"Context.startForegroundService() did not then call Service.startForeground(): "
- + serviceRecord);
+ + serviceRecord, false /*force*/);
}
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3dc33f8..9b1eb3a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3568,7 +3568,7 @@
@Override
public void crashApplication(int uid, int initialPid, String packageName, int userId,
- String message) {
+ String message, boolean force) {
if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: crashApplication() from pid="
@@ -3580,7 +3580,8 @@
}
synchronized(this) {
- mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId, message);
+ mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId,
+ message, force);
}
}
@@ -8203,10 +8204,12 @@
}
/**
- * @deprecated This method is only used by a few internal components and it will soon be
- * replaced by a proper bug report API (which will be restricted to a few, pre-defined apps).
+ * @deprecated This method is only used by a few internal components and it will soon start
+ * using bug report API (which will be restricted to a few, pre-defined apps).
* No new code should be calling it.
*/
+ // TODO(b/137825297): Remove deprecated annotation and rephrase comments for all
+ // requestBugreport functions below.
@Deprecated
@Override
public void requestBugReport(int bugreportType) {
@@ -8214,11 +8217,12 @@
}
/**
- * @deprecated This method is only used by a few internal components and it will soon be
- * replaced by a proper bug report API (which will be restricted to a few, pre-defined apps).
+ * @deprecated This method is only used by a few internal components and it will soon start
+ * using bug report API (which will be restricted to a few, pre-defined apps).
* No new code should be calling it.
*/
@Deprecated
+ @Override
public void requestBugReportWithDescription(@Nullable String shareTitle,
@Nullable String shareDescription, int bugreportType) {
String type = null;
@@ -8299,8 +8303,8 @@
}
/**
- * @deprecated This method is only used by a few internal components and it will soon be
- * replaced by a proper bug report API (which will be restricted to a few, pre-defined apps).
+ * @deprecated This method is only used by a few internal components and it will soon start
+ * using bug report API (which will be restricted to a few, pre-defined apps).
* No new code should be calling it.
*/
@Deprecated
@@ -8311,8 +8315,8 @@
}
/**
- * @deprecated This method is only used by a few internal components and it will soon be
- * replaced by a proper bug report API (which will be restricted to a few, pre-defined apps).
+ * @deprecated This method is only used by a few internal components and it will soon start
+ * using bug report API (which will be restricted to a few, pre-defined apps).
* No new code should be calling it.
*/
@Deprecated
@@ -8322,6 +8326,41 @@
ActivityManager.BUGREPORT_OPTION_WIFI);
}
+ /**
+ * Takes an interactive bugreport with a progress notification
+ */
+ @Override
+ public void requestInteractiveBugReport() {
+ requestBugReportWithDescription(null, null, ActivityManager.BUGREPORT_OPTION_INTERACTIVE);
+ }
+
+ /**
+ * Takes an interactive bugreport with a progress notification. Also, shows the given title and
+ * description on the final share notification
+ */
+ @Override
+ public void requestInteractiveBugReportWithDescription(String shareTitle,
+ String shareDescription) {
+ requestBugReportWithDescription(shareTitle, shareDescription,
+ ActivityManager.BUGREPORT_OPTION_INTERACTIVE);
+ }
+
+ /**
+ * Takes a bugreport with minimal user interference
+ */
+ @Override
+ public void requestFullBugReport() {
+ requestBugReportWithDescription(null, null, ActivityManager.BUGREPORT_OPTION_FULL);
+ }
+
+ /**
+ * Takes a bugreport remotely
+ */
+ @Override
+ public void requestRemoteBugReport() {
+ requestBugReportWithDescription(null, null, ActivityManager.BUGREPORT_OPTION_REMOTE);
+ }
+
public void registerProcessObserver(IProcessObserver observer) {
enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
"registerProcessObserver()");
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index a0900b6..8b8c40e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -1070,7 +1070,7 @@
} catch (NumberFormatException e) {
packageName = arg;
}
- mInterface.crashApplication(-1, pid, packageName, userId, "shell-induced crash");
+ mInterface.crashApplication(-1, pid, packageName, userId, "shell-induced crash", false);
return 0;
}
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 1ff6f4d..6a29c75 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -314,20 +314,24 @@
}
void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) {
- app.setCrashing(false);
- app.crashingReport = null;
- app.setNotResponding(false);
- app.notRespondingReport = null;
if (app.anrDialog == fromDialog) {
app.anrDialog = null;
}
if (app.waitDialog == fromDialog) {
app.waitDialog = null;
}
+ killAppImmediateLocked(app, "user-terminated", "user request after error");
+ }
+
+ private void killAppImmediateLocked(ProcessRecord app, String reason, String killReason) {
+ app.setCrashing(false);
+ app.crashingReport = null;
+ app.setNotResponding(false);
+ app.notRespondingReport = null;
if (app.pid > 0 && app.pid != MY_PID) {
- handleAppCrashLocked(app, "user-terminated" /*reason*/,
+ handleAppCrashLocked(app, reason,
null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/);
- app.kill("user request after error", true);
+ app.kill(killReason, true);
}
}
@@ -341,7 +345,7 @@
* @param message
*/
void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId,
- String message) {
+ String message, boolean force) {
ProcessRecord proc = null;
// Figure out which process to kill. We don't trust that initialPid
@@ -374,6 +378,14 @@
}
proc.scheduleCrash(message);
+ if (force) {
+ // If the app is responsive, the scheduled crash will happen as expected
+ // and then the delayed summary kill will be a no-op.
+ final ProcessRecord p = proc;
+ mService.mHandler.postDelayed(
+ () -> killAppImmediateLocked(p, "forced", "killed for invalid state"),
+ 5000L);
+ }
}
/**
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 7a3d3c2..3c2aee4 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1576,7 +1576,7 @@
}
if (adj == ProcessList.SERVICE_ADJ) {
- if (doingAll) {
+ if (doingAll && !cycleReEval) {
app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3);
mNewNumServiceProcs++;
//Slog.i(TAG, "ADJ " + app + " serviceb=" + app.serviceb);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 8c038aa..cc4b160 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -803,6 +803,7 @@
final String localPackageName = packageName;
final int localForegroundId = foregroundId;
final Notification _foregroundNoti = foregroundNoti;
+ final ServiceRecord record = this;
ams.mHandler.post(new Runnable() {
public void run() {
NotificationManagerInternal nm = LocalServices.getService(
@@ -901,10 +902,8 @@
Slog.w(TAG, "Error showing notification for service", e);
// If it gave us a garbage notification, it doesn't
// get to be foreground.
- ams.setServiceForeground(instanceName, ServiceRecord.this,
- 0, null, 0, 0);
- ams.crashApplication(appUid, appPid, localPackageName, -1,
- "Bad notification for startForeground: " + e);
+ ams.mServices.killMisbehavingService(record,
+ appUid, appPid, localPackageName);
}
}
});
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 7b3eae1..faf01f9 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -2082,6 +2082,7 @@
}
out.write(0xFF);
out.write(0xFF);
+ out.flush();
// Wait for End-of-File.
InputStream in = mSockets[i].getInputStream();
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 58aadd1..1fc0db3 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -69,6 +69,7 @@
private static final int MSG_ALLOWED_MODES_CHANGED = 1;
private static final int MSG_BRIGHTNESS_THRESHOLDS_CHANGED = 2;
private static final int MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED = 3;
+ private static final int MSG_REFRESH_RATE_IN_ZONE_CHANGED = 4;
// Special ID used to indicate that given vote is to be applied globally, rather than to a
// specific display.
@@ -440,23 +441,48 @@
mSettingsObserver.onDeviceConfigDefaultPeakRefreshRateChanged(
defaultPeakRefreshRate);
break;
+
+ case MSG_REFRESH_RATE_IN_ZONE_CHANGED:
+ int refreshRateInZone = msg.arg1;
+ mBrightnessObserver.onDeviceConfigRefreshRateInZoneChanged(
+ refreshRateInZone);
+ break;
}
}
}
private static final class Vote {
- // We split the app request into two priorities in case we can satisfy one desire without
- // the other.
- public static final int PRIORITY_APP_REQUEST_REFRESH_RATE = 0;
- public static final int PRIORITY_APP_REQUEST_SIZE = 1;
- public static final int PRIORITY_USER_SETTING_REFRESH_RATE = 2;
- public static final int PRIORITY_LOW_BRIGHTNESS = 3;
- public static final int PRIORITY_LOW_POWER_MODE = 4;
+ // LOW_BRIGHTNESS votes for a single refresh rate like [60,60], [90,90] or null.
+ // If the higher voters result is a range, it will fix the rate to a single choice.
+ // It's used to avoid rate switch in certain conditions.
+ public static final int PRIORITY_LOW_BRIGHTNESS = 0;
+
+ // SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate.
+ // It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
+ public static final int PRIORITY_USER_SETTING_MIN_REFRESH_RATE = 1;
+
+ // We split the app request into different priorities in case we can satisfy one desire
+ // without the other.
+
+ // Application can specify preferred refresh rate with below attrs.
+ // @see android.view.WindowManager.LayoutParams#preferredRefreshRate
+ // @see android.view.WindowManager.LayoutParams#preferredDisplayModeId
+ // System also forces some apps like blacklisted app to run at a lower refresh rate.
+ // @see android.R.array#config_highRefreshRateBlacklist
+ public static final int PRIORITY_APP_REQUEST_REFRESH_RATE = 2;
+ public static final int PRIORITY_APP_REQUEST_SIZE = 3;
+
+ // SETTING_PEAK_REFRESH_RATE has a high priority and will restrict the bounds of the rest
+ // of low priority voters. It votes [0, max(PEAK, MIN)]
+ public static final int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 4;
+
+ // LOW_POWER_MODE force display to [0, 60HZ] if Settings.Global.LOW_POWER_MODE is on.
+ public static final int PRIORITY_LOW_POWER_MODE = 5;
// Whenever a new priority is added, remember to update MIN_PRIORITY and/or MAX_PRIORITY as
// appropriate, as well as priorityToString.
- public static final int MIN_PRIORITY = PRIORITY_APP_REQUEST_REFRESH_RATE;
+ public static final int MIN_PRIORITY = PRIORITY_LOW_BRIGHTNESS;
public static final int MAX_PRIORITY = PRIORITY_LOW_POWER_MODE;
/**
@@ -500,12 +526,16 @@
public static String priorityToString(int priority) {
switch (priority) {
+ case PRIORITY_LOW_BRIGHTNESS:
+ return "PRIORITY_LOW_BRIGHTNESS";
+ case PRIORITY_USER_SETTING_MIN_REFRESH_RATE:
+ return "PRIORITY_USER_SETTING_MIN_REFRESH_RATE";
case PRIORITY_APP_REQUEST_REFRESH_RATE:
return "PRIORITY_APP_REQUEST_REFRESH_RATE";
case PRIORITY_APP_REQUEST_SIZE:
return "PRIORITY_APP_REQUEST_SIZE";
- case PRIORITY_USER_SETTING_REFRESH_RATE:
- return "PRIORITY_USER_SETTING_REFRESH_RATE";
+ case PRIORITY_USER_SETTING_PEAK_REFRESH_RATE:
+ return "PRIORITY_USER_SETTING_PEAK_REFRESH_RATE";
case PRIORITY_LOW_POWER_MODE:
return "PRIORITY_LOW_POWER_MODE";
default:
@@ -608,12 +638,11 @@
float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate);
- if (peakRefreshRate < minRefreshRate) {
- peakRefreshRate = minRefreshRate;
- }
+ updateVoteLocked(Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE,
+ Vote.forRefreshRates(0f, Math.max(minRefreshRate, peakRefreshRate)));
+ updateVoteLocked(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE,
+ Vote.forRefreshRates(minRefreshRate, Float.POSITIVE_INFINITY));
- Vote vote = Vote.forRefreshRates(minRefreshRate, peakRefreshRate);
- updateVoteLocked(Vote.PRIORITY_USER_SETTING_REFRESH_RATE, vote);
mBrightnessObserver.onRefreshRateSettingChangedLocked(minRefreshRate, peakRefreshRate);
}
@@ -655,6 +684,7 @@
refreshRateVote = null;
sizeVote = null;
}
+
updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, refreshRateVote);
updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_SIZE, sizeVote);
return;
@@ -799,6 +829,8 @@
private boolean mRefreshRateChangeable = false;
private boolean mLowPowerModeEnabled = false;
+ private int mRefreshRateInZone;
+
BrightnessObserver(Context context, Handler handler) {
super(handler);
mContext = context;
@@ -815,6 +847,7 @@
public void observe(SensorManager sensorManager) {
mSensorManager = sensorManager;
+
// DeviceConfig is accessible after system ready.
int[] brightnessThresholds = mDeviceConfigDisplaySettings.getBrightnessThresholds();
int[] ambientThresholds = mDeviceConfigDisplaySettings.getAmbientThresholds();
@@ -824,6 +857,8 @@
mDisplayBrightnessThresholds = brightnessThresholds;
mAmbientBrightnessThresholds = ambientThresholds;
}
+
+ mRefreshRateInZone = mDeviceConfigDisplaySettings.getRefreshRateInZone();
restartObserver();
mDeviceConfigDisplaySettings.startListening();
}
@@ -863,8 +898,16 @@
restartObserver();
}
+ public void onDeviceConfigRefreshRateInZoneChanged(int refreshRate) {
+ if (refreshRate != mRefreshRateInZone) {
+ mRefreshRateInZone = refreshRate;
+ restartObserver();
+ }
+ }
+
public void dumpLocked(PrintWriter pw) {
pw.println(" BrightnessObserver");
+ pw.println(" mRefreshRateInZone: " + mRefreshRateInZone);
for (int d: mDisplayBrightnessThresholds) {
pw.println(" mDisplayBrightnessThreshold: " + d);
@@ -950,6 +993,10 @@
* to value changes.
*/
private boolean checkShouldObserve(int[] a) {
+ if (mRefreshRateInZone <= 0) {
+ return false;
+ }
+
for (int d: a) {
if (d >= 0) {
return true;
@@ -959,37 +1006,42 @@
return false;
}
+ private boolean isInsideZone(int brightness, float lux) {
+ for (int i = 0; i < mDisplayBrightnessThresholds.length; i++) {
+ int disp = mDisplayBrightnessThresholds[i];
+ int ambi = mAmbientBrightnessThresholds[i];
+
+ if (disp >= 0 && ambi >= 0) {
+ if (brightness <= disp && mAmbientLux <= ambi) {
+ return true;
+ }
+ } else if (disp >= 0) {
+ if (brightness <= disp) {
+ return true;
+ }
+ } else if (ambi >= 0) {
+ if (mAmbientLux <= ambi) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
private void onBrightnessChangedLocked() {
int brightness = Settings.System.getInt(mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS, -1);
Vote vote = null;
- for (int i = 0; i < mDisplayBrightnessThresholds.length; i++) {
- int disp = mDisplayBrightnessThresholds[i];
- int ambi = mAmbientBrightnessThresholds[i];
-
- if (disp >= 0 && ambi >= 0) {
- if (brightness <= disp && mAmbientLux <= ambi) {
- vote = Vote.forRefreshRates(0f, 60f);
- }
- } else if (disp >= 0) {
- if (brightness <= disp) {
- vote = Vote.forRefreshRates(0f, 60f);
- }
- } else if (ambi >= 0) {
- if (mAmbientLux <= ambi) {
- vote = Vote.forRefreshRates(0f, 60f);
- }
- }
-
- if (vote != null) {
- break;
- }
+ boolean insideZone = isInsideZone(brightness, mAmbientLux);
+ if (insideZone) {
+ vote = Vote.forRefreshRates(mRefreshRateInZone, mRefreshRateInZone);
}
if (DEBUG) {
Slog.d(TAG, "Display brightness " + brightness + ", ambient lux " + mAmbientLux +
- (vote != null ? " 60hz only" : " no refresh rate limit"));
+ ", Vote " + vote);
}
updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, vote);
}
@@ -1104,7 +1156,6 @@
}
private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener {
-
public DeviceConfigDisplaySettings() {
}
@@ -1118,7 +1169,8 @@
*/
public int[] getBrightnessThresholds() {
return getIntArrayProperty(
- DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_BRIGHTNESS_THRESHOLDS);
+ DisplayManager.DeviceConfig.
+ KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS);
}
/*
@@ -1126,7 +1178,8 @@
*/
public int[] getAmbientThresholds() {
return getIntArrayProperty(
- DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_AMBIENT_THRESHOLDS);
+ DisplayManager.DeviceConfig.
+ KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS);
}
/*
@@ -1143,17 +1196,32 @@
return defaultPeakRefreshRate;
}
+ public int getRefreshRateInZone() {
+ int defaultRefreshRateInZone = mContext.getResources().getInteger(
+ R.integer.config_defaultRefreshRateInZone);
+
+ int refreshRate = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_ZONE,
+ defaultRefreshRateInZone);
+
+ return refreshRate;
+ }
+
@Override
public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
int[] brightnessThresholds = getBrightnessThresholds();
int[] ambientThresholds = getAmbientThresholds();
Float defaultPeakRefreshRate = getDefaultPeakRefreshRate();
+ int refreshRateInZone = getRefreshRateInZone();
mHandler.obtainMessage(MSG_BRIGHTNESS_THRESHOLDS_CHANGED,
new Pair<int[], int[]>(brightnessThresholds, ambientThresholds))
.sendToTarget();
mHandler.obtainMessage(MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED,
defaultPeakRefreshRate).sendToTarget();
+ mHandler.obtainMessage(MSG_REFRESH_RATE_IN_ZONE_CHANGED, refreshRateInZone,
+ 0).sendToTarget();
}
private int[] getIntArrayProperty(String prop) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index dacf372..9a85f952 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1635,6 +1635,10 @@
removeAction(SystemAudioAutoInitiationAction.class);
removeAction(SystemAudioStatusAction.class);
removeAction(VolumeControlAction.class);
+
+ if (!mService.isControlEnabled()) {
+ setSystemAudioMode(false);
+ }
}
@ServiceThreadOnly
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f04d459..db8d098 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -926,7 +926,7 @@
() -> mAm.crashApplication(uid, initialPid, pkg, -1,
"Bad notification(tag=" + tag + ", id=" + id + ") posted from package "
+ pkg + ", crashing app(uid=" + uid + ", pid=" + initialPid + "): "
- + message));
+ + message, true /* force */));
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6e2fd38..ab77cc6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13852,7 +13852,7 @@
// If this is an update to a package that might be potentially downgraded, then we
// need to check with the rollback manager whether there's any userdata that might
- // need to be restored for the package.
+ // need to be snapshotted or restored for the package.
//
// TODO(narayan): Get this working for cases where userId == UserHandle.USER_ALL.
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && !doRestore && update) {
@@ -13879,12 +13879,16 @@
installedUsers = ps.queryInstalledUsers(allUsers, true);
}
- if (ps != null) {
+ boolean doSnapshotOrRestore = data != null && data.args != null
+ && ((data.args.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0
+ || (data.args.installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0);
+
+ if (ps != null && doSnapshotOrRestore) {
try {
rm.snapshotAndRestoreUserData(packageName, installedUsers, appId, ceDataInode,
seInfo, token);
} catch (RemoteException re) {
- // Cannot happen, the RollbackManager is hosted in the same process.
+ Log.e(TAG, "Error snapshotting/restoring user data: " + re);
}
doRestore = true;
}
@@ -18013,19 +18017,20 @@
// or packages running under the shared user of the removed
// package if revoking the permissions requested only by the removed
// package is successful and this causes a change in gids.
+ boolean shouldKill = false;
for (int userId : UserManagerService.getInstance().getUserIds()) {
final int userIdToKill = mSettings.updateSharedUserPermsLPw(deletedPs,
userId);
- if (userIdToKill == UserHandle.USER_ALL
- || userIdToKill >= UserHandle.USER_SYSTEM) {
- // If gids changed for this user, kill all affected packages.
- mHandler.post(() -> {
- // This has to happen with no lock held.
- killApplication(deletedPs.name, deletedPs.appId,
- KILL_APP_REASON_GIDS_CHANGED);
- });
- break;
- }
+ shouldKill |= userIdToKill == UserHandle.USER_ALL
+ || userIdToKill >= UserHandle.USER_SYSTEM;
+ }
+ // If gids changed, kill all affected packages.
+ if (shouldKill) {
+ mHandler.post(() -> {
+ // This has to happen with no lock held.
+ killApplication(deletedPs.name, deletedPs.appId,
+ KILL_APP_REASON_GIDS_CHANGED);
+ });
}
}
clearPackagePreferredActivitiesLPw(
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index dd1eb83..8d1ed43 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -150,6 +150,14 @@
return;
}
+ // Verify signing details for downgrade
+ // Allow downgrading from B to A iff it is possible to upgrade from A to B
+ if (existingApexPkg.getLongVersionCode() > newApexPkg.getLongVersionCode()
+ && existingSigningDetails.checkCapability(signingDetails,
+ PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)) {
+ return;
+ }
+
throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"APK-container signature of APEX package " + packageName + " with version "
+ newApexPkg.versionCodeMajor + " and path " + apexPath + " is not"
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 72c8b22..83aa07d 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -67,6 +67,7 @@
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.metrics.LogMaker;
import android.os.Binder;
import android.os.Build;
@@ -2348,10 +2349,11 @@
// or has updated its target SDK and AR is no longer implicit to it.
// This is a compatibility workaround for apps when AR permission was
// split in Q.
- int numSplitPerms = PermissionManager.SPLIT_PERMISSIONS.size();
+ final List<SplitPermissionInfoParcelable> permissionList =
+ getSplitPermissions();
+ int numSplitPerms = permissionList.size();
for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
- PermissionManager.SplitPermissionInfo sp =
- PermissionManager.SPLIT_PERMISSIONS.get(splitPermNum);
+ SplitPermissionInfoParcelable sp = permissionList.get(splitPermNum);
String splitPermName = sp.getSplitPermission();
if (sp.getNewPermissions().contains(permName)
&& origPermissions.hasInstallPermission(splitPermName)) {
@@ -2920,10 +2922,10 @@
String pkgName = pkg.packageName;
ArrayMap<String, ArraySet<String>> newToSplitPerms = new ArrayMap<>();
- int numSplitPerms = PermissionManager.SPLIT_PERMISSIONS.size();
+ final List<SplitPermissionInfoParcelable> permissionList = getSplitPermissions();
+ int numSplitPerms = permissionList.size();
for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
- PermissionManager.SplitPermissionInfo spi =
- PermissionManager.SPLIT_PERMISSIONS.get(splitPermNum);
+ SplitPermissionInfoParcelable spi = permissionList.get(splitPermNum);
List<String> newPerms = spi.getNewPermissions();
int numNewPerms = newPerms.size();
@@ -2991,6 +2993,12 @@
return updatedUserIds;
}
+ @Override
+ public List<SplitPermissionInfoParcelable> getSplitPermissions() {
+ return PermissionManager.splitPermissionInfoListToParcelableList(
+ SystemConfig.getInstance().getSplitPermissions());
+ }
+
private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) {
boolean allowed = false;
final int NP = PackageParser.NEW_PERMISSIONS.length;
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index ddbd9c9..a671e5f 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -118,6 +118,10 @@
@GuardedBy("mLock")
private final List<Rollback> mRollbacks;
+ // Apk sessions from a staged session with no matching rollback.
+ @GuardedBy("mLock")
+ private final IntArray mOrphanedApkSessionIds = new IntArray();
+
private final RollbackStore mRollbackStore;
private final Context mContext;
@@ -655,6 +659,11 @@
// hasn't actually been updated.
onPackageReplaced(apexPackageName);
}
+
+ synchronized (mLock) {
+ mOrphanedApkSessionIds.clear();
+ }
+
mPackageHealthObserver.onBootCompletedAsync();
});
}
@@ -865,6 +874,16 @@
}
}
+ // Check to see if this is the apk session for a staged session for which rollback was
+ // cancelled.
+ synchronized (mLock) {
+ if (mOrphanedApkSessionIds.indexOf(parentSession.getSessionId()) != -1) {
+ Slog.w(TAG, "Not enabling rollback for apk as no matching staged session "
+ + "rollback exists");
+ return false;
+ }
+ }
+
NewRollback newRollback;
synchronized (mLock) {
// See if we already have a NewRollback that contains this package
@@ -1122,6 +1141,13 @@
break;
}
}
+ if (rollback == null) {
+ // Did not find rollback matching originalSessionId.
+ Slog.e(TAG, "notifyStagedApkSession did not find rollback for session "
+ + originalSessionId
+ + ". Adding orphaned apk session " + apkSessionId);
+ mOrphanedApkSessionIds.add(apkSessionId);
+ }
}
if (rollback != null) {
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 30a3aef..ad340fe 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -255,13 +255,19 @@
}
}
- public void onSomeWindowResizedOrMovedLocked(int displayId) {
+ /**
+ * Called when the location or the size of the window is changed. Moving the window to
+ * another display is also taken into consideration.
+ * @param displayIds the display ids of displays when the situation happens.
+ */
+ public void onSomeWindowResizedOrMovedLocked(int... displayIds) {
// Not relevant for the display magnifier.
-
- final WindowsForAccessibilityObserver windowsForA11yObserver =
- mWindowsForAccessibilityObserver.get(displayId);
- if (windowsForA11yObserver != null) {
- windowsForA11yObserver.scheduleComputeChangedWindowsLocked();
+ for (int i = 0; i < displayIds.length; i++) {
+ final WindowsForAccessibilityObserver windowsForA11yObserver =
+ mWindowsForAccessibilityObserver.get(displayIds[i]);
+ if (windowsForA11yObserver != null) {
+ windowsForA11yObserver.scheduleComputeChangedWindowsLocked();
+ }
}
}
@@ -808,7 +814,7 @@
private final Paint mPaint = new Paint();
private final SurfaceControl mSurfaceControl;
- private final Surface mSurface = new Surface();
+ private final Surface mSurface = mService.mSurfaceFactory.get();
private final AnimationController mAnimationController;
@@ -961,7 +967,7 @@
}
public void releaseSurface() {
- mService.mTransactionFactory.make().remove(mSurfaceControl).apply();
+ mService.mTransactionFactory.get().remove(mSurfaceControl).apply();
mSurface.release();
}
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index e76078f..f3e7384 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -574,11 +574,9 @@
* then we should explicitly pause that stack's top activity.
* @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
* @param resuming The resuming activity.
- * @param dontWait The resuming activity isn't going to wait for all activities to be paused
- * before resuming.
* @return {@code true} if any activity was paused as a result of this call.
*/
- boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
+ boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming) {
boolean someActivityPaused = false;
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
@@ -588,8 +586,8 @@
|| !stack.isFocusable())) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
" mResumedActivity=" + resumedActivity);
- someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
- dontWait);
+ someActivityPaused |= stack.startPausingLocked(userLeaving, false /* uiSleeping*/,
+ resuming);
}
}
return someActivityPaused;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 8e42943..12cb94d 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -118,7 +118,6 @@
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
-import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_APP;
@@ -1664,11 +1663,10 @@
@interface FinishRequest {}
/**
- * See {@link #finishIfPossible(int, Intent, String, boolean, boolean)}
+ * See {@link #finishIfPossible(int, Intent, String, boolean)}
*/
@FinishRequest int finishIfPossible(String reason, boolean oomAdj) {
- return finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
- oomAdj, !PAUSE_IMMEDIATELY);
+ return finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason, oomAdj);
}
/**
@@ -1683,7 +1681,7 @@
* request to finish it was not ignored.
*/
@FinishRequest int finishIfPossible(int resultCode, Intent resultData, String reason,
- boolean oomAdj, boolean pauseImmediately) {
+ boolean oomAdj) {
if (DEBUG_RESULTS || DEBUG_STATES) {
Slog.v(TAG_STATES, "Finishing activity r=" + this + ", result=" + resultCode
+ ", data=" + resultData + ", reason=" + reason);
@@ -1768,7 +1766,8 @@
if (DEBUG_USER_LEAVING) {
Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");
}
- stack.startPausingLocked(false, false, null, pauseImmediately);
+ stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
+ null /* resuming */);
}
if (endTask) {
@@ -2104,7 +2103,7 @@
// TODO: If the callers to removeTask() changes such that we have multiple places
// where we are destroying the task, move this back into removeTask()
mStackSupervisor.removeTaskByIdLocked(task.taskId, false /* killProcess */,
- !REMOVE_FROM_RECENTS, PAUSE_IMMEDIATELY, reason);
+ !REMOVE_FROM_RECENTS, reason);
}
// We must keep the task around until all activities are destroyed. The following
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index a8eaaa4c..f5f6625 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -63,7 +63,6 @@
import static com.android.server.wm.ActivityStack.ActivityState.STARTED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList;
import static com.android.server.wm.ActivityStackSupervisor.printThisActivity;
@@ -1547,7 +1546,7 @@
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"Sleep => pause with userLeaving=false");
- startPausingLocked(false, true, null, false);
+ startPausingLocked(false /* userLeaving */, true /* uiSleeping */, null /* resuming */);
shouldSleep = false ;
} else if (mPausingActivity != null) {
// Still waiting for something to pause; can't sleep yet.
@@ -1617,13 +1616,11 @@
* @param resuming The activity we are currently trying to resume or null if this is not being
* called as part of resuming the top activity, so we shouldn't try to instigate
* a resume here if not null.
- * @param pauseImmediately True if the caller does not want to wait for the activity callback to
- * complete pausing.
* @return Returns true if an activity now is in the PAUSING state, and we are waiting for
* it to tell us when it is done.
*/
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
- ActivityRecord resuming, boolean pauseImmediately) {
+ ActivityRecord resuming) {
if (mPausingActivity != null) {
Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
+ " state=" + mPausingActivity.getState());
@@ -1661,6 +1658,19 @@
mService.updateCpuStats();
+ boolean pauseImmediately = false;
+ if (resuming != null && (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0) {
+ // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous
+ // activity to be paused, while at the same time resuming the new resume activity
+ // only if the previous activity can't go into Pip since we want to give Pip
+ // activities a chance to enter Pip before resuming the next activity.
+ final boolean lastResumedCanPip = prev != null && prev.checkEnterPictureInPictureState(
+ "shouldResumeWhilePausing", userLeaving);
+ if (!lastResumedCanPip) {
+ pauseImmediately = true;
+ }
+ }
+
if (prev.attachedToProcess()) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
try {
@@ -1758,7 +1768,8 @@
mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
- private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
+ @VisibleForTesting
+ void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
ActivityRecord prev = mPausingActivity;
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
@@ -2594,7 +2605,6 @@
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
- boolean lastResumedCanPip = false;
ActivityRecord lastResumed = null;
final ActivityStack lastFocusedStack = display.getLastFocusedStack();
if (lastFocusedStack != null && lastFocusedStack != this) {
@@ -2608,23 +2618,15 @@
+ " next=" + next + " lastResumed=" + lastResumed);
userLeaving = false;
}
- lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
- "resumeTopActivity", userLeaving /* beforeStopping */);
}
- // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
- // to be paused, while at the same time resuming the new resume activity only if the
- // previous activity can't go into Pip since we want to give Pip activities a chance to
- // enter Pip before resuming the next activity.
- final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
- && !lastResumedCanPip;
- boolean pausing = display.pauseBackStacks(userLeaving, next, false);
+ boolean pausing = display.pauseBackStacks(userLeaving, next);
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
- pausing |= startPausingLocked(userLeaving, false, next, false);
+ pausing |= startPausingLocked(userLeaving, false /* uiSleeping */, next);
}
- if (pausing && !resumeWhilePausing) {
+ if (pausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
"resumeTopActivityLocked: Skip resume: need to start pausing");
// At this point we want to put the upcoming activity's process
@@ -3802,8 +3804,7 @@
final long origId = Binder.clearCallingIdentity();
for (int i = start; i > finishTo; i--) {
final ActivityRecord r = activities.get(i);
- r.finishIfPossible(resultCode, resultData, "navigate-up", true /* oomAdj */,
- !PAUSE_IMMEDIATELY);
+ r.finishIfPossible(resultCode, resultData, "navigate-up", true /* oomAdj */);
// Only return the supplied result for the first activity finished
resultCode = Activity.RESULT_CANCELED;
resultData = null;
@@ -3840,8 +3841,7 @@
} catch (RemoteException e) {
foundParentInTask = false;
}
- parent.finishIfPossible(resultCode, resultData, "navigate-top",
- true /* oomAdj */, !PAUSE_IMMEDIATELY);
+ parent.finishIfPossible(resultCode, resultData, "navigate-top", true /* oomAdj */);
}
}
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index a06b9ce..a480fb8 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -200,10 +200,6 @@
// Used to indicate that a task is removed it should also be removed from recents.
static final boolean REMOVE_FROM_RECENTS = true;
- // Used to indicate that pausing an activity should occur immediately without waiting for
- // the activity callback indicating that it has completed pausing
- static final boolean PAUSE_IMMEDIATELY = true;
-
/** True if the docked stack is currently being resized. */
private boolean mDockedStackResizing;
@@ -1778,30 +1774,19 @@
}
/**
- * See {@link #removeTaskByIdLocked(int, boolean, boolean, boolean)}
- */
- boolean removeTaskByIdLocked(int taskId, boolean killProcess, boolean removeFromRecents,
- String reason) {
- return removeTaskByIdLocked(taskId, killProcess, removeFromRecents, !PAUSE_IMMEDIATELY,
- reason);
- }
-
- /**
* Removes the task with the specified task id.
*
* @param taskId Identifier of the task to be removed.
* @param killProcess Kill any process associated with the task if possible.
* @param removeFromRecents Whether to also remove the task from recents.
- * @param pauseImmediately Pauses all task activities immediately without waiting for the
- * pause-complete callback from the activity.
* @return Returns true if the given task was found and removed.
*/
boolean removeTaskByIdLocked(int taskId, boolean killProcess, boolean removeFromRecents,
- boolean pauseImmediately, String reason) {
+ String reason) {
final TaskRecord tr =
mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr != null) {
- tr.removeTaskActivitiesLocked(pauseImmediately, reason);
+ tr.removeTaskActivitiesLocked(reason);
cleanUpRemovedTaskLocked(tr, killProcess, removeFromRecents);
mService.getLockTaskController().clearLockedTask(tr);
if (tr.isPersistable) {
@@ -1925,7 +1910,7 @@
// Task was trimmed from the recent tasks list -- remove the active task record as well
// since the user won't really be able to go back to it
removeTaskByIdLocked(task.taskId, killProcess, false /* removeFromRecents */,
- !PAUSE_IMMEDIATELY, "recent-task-trimmed");
+ "recent-task-trimmed");
}
task.removedFromRecents();
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 8d40f87..ee56c09 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -87,7 +87,6 @@
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
-import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
@@ -1616,8 +1615,7 @@
// Explicitly dismissing the activity so reset its relaunch flag.
r.mRelaunchReason = RELAUNCH_REASON_NONE;
} else {
- r.finishIfPossible(resultCode, resultData, "app-request",
- true /* oomAdj */, !PAUSE_IMMEDIATELY);
+ r.finishIfPossible(resultCode, resultData, "app-request", true /* oomAdj */);
res = r.finishing;
if (!res) {
Slog.i(TAG, "Failed to finish by app-request");
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index 4ceae72..b52ade4 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -41,6 +41,8 @@
import com.android.server.wm.SurfaceAnimator.Animatable;
+import java.util.function.Supplier;
+
/**
* Represents a surface that is displayed over an {@link AppWindowToken}
*/
@@ -55,8 +57,9 @@
private final int mHeight;
private final boolean mRelative;
- AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader) {
- this(t, appToken, thumbnailHeader, false /* relative */);
+ AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, AppWindowToken appToken,
+ GraphicBuffer thumbnailHeader) {
+ this(surfaceFactory, t, appToken, thumbnailHeader, false /* relative */);
}
/**
@@ -66,9 +69,9 @@
* @param relative Whether this thumbnail will be a child of appToken (and thus positioned
* relative to it) or not.
*/
- AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader,
- boolean relative) {
- this(t, appToken, thumbnailHeader, relative, new Surface(), null);
+ AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, AppWindowToken appToken,
+ GraphicBuffer thumbnailHeader, boolean relative) {
+ this(t, appToken, thumbnailHeader, relative, surfaceFactory.get(), null);
}
AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader,
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 7e0d9a0..ffd9021 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1793,8 +1793,8 @@
mWmService.mTaskSnapshotController.createTaskSnapshot(
task, 1 /* scaleFraction */);
if (snapshot != null) {
- mThumbnail = new AppWindowThumbnail(t, this, snapshot.getGraphicBuffer(),
- true /* relative */);
+ mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, t, this,
+ snapshot.getGraphicBuffer(), true /* relative */);
}
}
}
@@ -2033,7 +2033,8 @@
final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
if (needsLetterbox) {
if (mLetterbox == null) {
- mLetterbox = new Letterbox(() -> makeChildSurface(null));
+ mLetterbox = new Letterbox(() -> makeChildSurface(null),
+ mWmService.mTransactionFactory);
mLetterbox.attachInput(w);
}
getPosition(mTmpPoint);
@@ -2981,7 +2982,8 @@
return;
}
clearThumbnail();
- mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
+ mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, getPendingTransaction(),
+ this, thumbnailHeader);
mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
}
@@ -3009,7 +3011,8 @@
if (thumbnail == null) {
return;
}
- mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
+ mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory,
+ getPendingTransaction(), this, thumbnail);
final Animation animation =
getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
win.getFrameLw());
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index 7fc17e1..7557271a 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -27,6 +27,7 @@
import android.view.SurfaceControl;
import java.io.PrintWriter;
+import java.util.function.Supplier;
/**
* Four black surfaces put together to make a black frame.
@@ -97,7 +98,7 @@
final BlackSurface[] mBlackSurfaces = new BlackSurface[4];
final boolean mForceDefaultOrientation;
- private final TransactionFactory mTransactionFactory;
+ private final Supplier<SurfaceControl.Transaction> mTransactionFactory;
public void printTo(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("Outer: "); mOuterRect.printShortString(pw);
@@ -112,8 +113,8 @@
}
}
- public BlackFrame(TransactionFactory factory, SurfaceControl.Transaction t, Rect outer,
- Rect inner, int layer, DisplayContent dc, boolean forceDefaultOrientation)
+ public BlackFrame(Supplier<SurfaceControl.Transaction> factory, SurfaceControl.Transaction t,
+ Rect outer, Rect inner, int layer, DisplayContent dc, boolean forceDefaultOrientation)
throws OutOfResourcesException {
boolean success = false;
@@ -151,7 +152,7 @@
public void kill() {
if (mBlackSurfaces != null) {
- SurfaceControl.Transaction t = mTransactionFactory.make();
+ SurfaceControl.Transaction t = mTransactionFactory.get();
for (int i=0; i<mBlackSurfaces.length; i++) {
if (mBlackSurfaces[i] != null) {
if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM,
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
index c3d6211..c1ca816 100644
--- a/services/core/java/com/android/server/wm/CircularDisplayMask.java
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -34,6 +34,8 @@
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
+import java.util.function.Supplier;
+
class CircularDisplayMask {
private static final String TAG = TAG_WITH_CLASS_NAME ? "CircularDisplayMask" : TAG_WM;
@@ -43,7 +45,7 @@
private Point mScreenSize;
private final SurfaceControl mSurfaceControl;
- private final Surface mSurface = new Surface();
+ private final Surface mSurface;
private int mLastDW;
private int mLastDH;
private boolean mDrawNeeded;
@@ -53,10 +55,10 @@
private boolean mDimensionsUnequal = false;
private int mMaskThickness;
- public CircularDisplayMask(DisplayContent dc, int zOrder,
+ CircularDisplayMask(Supplier<Surface> surfaceFactory, DisplayContent dc, int zOrder,
int screenOffset, int maskThickness) {
final Display display = dc.getDisplay();
-
+ mSurface = surfaceFactory.get();
mScreenSize = new Point();
display.getSize(mScreenSize);
if (mScreenSize.x != mScreenSize.y + screenOffset) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 71a0126..1267652 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1062,6 +1062,12 @@
}
addWindowToken(token.token, token);
+
+ if (mWmService.mAccessibilityController != null) {
+ final int prevDisplayId = prevDc != null ? prevDc.getDisplayId() : INVALID_DISPLAY;
+ mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(prevDisplayId,
+ getDisplayId());
+ }
}
void removeAppToken(IBinder binder) {
@@ -4388,7 +4394,7 @@
.show(mSplitScreenDividerAnchor);
scheduleAnimation();
} else {
- mWmService.mTransactionFactory.make()
+ mWmService.mTransactionFactory.get()
.remove(mAppAnimationLayer)
.remove(mBoostedAppAnimationLayer)
.remove(mHomeAppAnimationLayer)
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index c48f07c..17daabf 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -140,7 +140,7 @@
mFlags = flags;
mLocalWin = localWin;
mNotifiedWindows = new ArrayList<WindowState>();
- mTransaction = service.mTransactionFactory.make();
+ mTransaction = service.mTransactionFactory.get();
}
boolean isClosing() {
@@ -695,7 +695,8 @@
implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
- try (final SurfaceControl.Transaction transaction = new SurfaceControl.Transaction()) {
+ try (SurfaceControl.Transaction transaction =
+ mService.mTransactionFactory.get()) {
transaction.setPosition(
mSurfaceControl,
(float) animation.getAnimatedValue(ANIMATED_PROPERTY_X),
diff --git a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
index 7cb4a43..f64592f 100644
--- a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
+++ b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
@@ -32,6 +32,8 @@
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
+import java.util.function.Supplier;
+
class EmulatorDisplayOverlay {
private static final String TAG = TAG_WITH_CLASS_NAME ? "EmulatorDisplayOverlay" : TAG_WM;
@@ -39,7 +41,7 @@
private Point mScreenSize;
private final SurfaceControl mSurfaceControl;
- private final Surface mSurface = new Surface();
+ private final Surface mSurface;
private int mLastDW;
private int mLastDH;
private boolean mDrawNeeded;
@@ -47,8 +49,9 @@
private int mRotation;
private boolean mVisible;
- public EmulatorDisplayOverlay(Context context, DisplayContent dc,
+ EmulatorDisplayOverlay(Supplier<Surface> surfaceFactory, Context context, DisplayContent dc,
int zOrder) {
+ mSurface = surfaceFactory.get();
final Display display = dc.getDisplay();
mScreenSize = new Point();
display.getSize(mScreenSize);
diff --git a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
index 315de91..8ae740d 100644
--- a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
+++ b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
@@ -16,7 +16,7 @@
package com.android.server.wm;
-import static android.provider.DeviceConfig.WindowManager.KEY_HIGH_REFRESH_RATE_BLACKLIST;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_HIGH_REFRESH_RATE_BLACKLIST;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -58,9 +58,9 @@
@VisibleForTesting
HighRefreshRateBlacklist(Resources r, DeviceConfigInterface deviceConfig) {
mDefaultBlacklist = r.getStringArray(R.array.config_highRefreshRateBlacklist);
- deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
BackgroundThread.getExecutor(), new OnPropertiesChangedListener());
- final String property = deviceConfig.getProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ final String property = deviceConfig.getProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
KEY_HIGH_REFRESH_RATE_BLACKLIST);
updateBlacklist(property);
}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 2eec926..dd9000e 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -153,7 +153,7 @@
mService = service;
mDisplayContent = mService.mRoot.getDisplayContent(displayId);
mDisplayId = displayId;
- mInputTransaction = mService.mTransactionFactory.make();
+ mInputTransaction = mService.mTransactionFactory.get();
mHandler = AnimationThread.getHandler();
mUpdateInputForAllWindowsConsumer = new UpdateInputForAllWindowsConsumer();
}
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index bb035d5..1bd2493 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -41,7 +41,8 @@
private static final Rect EMPTY_RECT = new Rect();
private static final Point ZERO_POINT = new Point(0, 0);
- private final Supplier<SurfaceControl.Builder> mFactory;
+ private final Supplier<SurfaceControl.Builder> mSurfaceControlFactory;
+ private final Supplier<SurfaceControl.Transaction> mTransactionFactory;
private final Rect mOuter = new Rect();
private final Rect mInner = new Rect();
private final LetterboxSurface mTop = new LetterboxSurface("top");
@@ -55,8 +56,10 @@
*
* @param surfaceControlFactory a factory for creating the managed {@link SurfaceControl}s
*/
- public Letterbox(Supplier<SurfaceControl.Builder> surfaceControlFactory) {
- mFactory = surfaceControlFactory;
+ public Letterbox(Supplier<SurfaceControl.Builder> surfaceControlFactory,
+ Supplier<SurfaceControl.Transaction> transactionFactory) {
+ mSurfaceControlFactory = surfaceControlFactory;
+ mTransactionFactory = transactionFactory;
}
/**
@@ -245,7 +248,7 @@
}
private void createSurface() {
- mSurface = mFactory.get().setName("Letterbox - " + mType)
+ mSurface = mSurfaceControlFactory.get().setName("Letterbox - " + mType)
.setFlags(HIDDEN).setColorLayer().build();
mSurface.setLayer(-1);
mSurface.setColor(new float[]{0, 0, 0});
@@ -261,7 +264,7 @@
public void remove() {
if (mSurface != null) {
- new SurfaceControl.Transaction().remove(mSurface).apply();
+ mTransactionFactory.get().remove(mSurface).apply();
mSurface = null;
}
if (mInputInterceptor != null) {
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 8752f37..f4280a2 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -592,7 +592,7 @@
return null;
}
- final TaskScreenshotAnimatable animatable = new TaskScreenshotAnimatable(task,
+ final TaskScreenshotAnimatable animatable = new TaskScreenshotAnimatable(mService.mSurfaceControlFactory, task,
new SurfaceControl.ScreenshotGraphicBuffer(taskSnapshot.getSnapshot(),
taskSnapshot.getColorSpace(), false /* containsSecureLayers */));
mRecentScreenshotAnimator = new SurfaceAnimator(
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 968d02b..d0b6fc8 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -134,7 +134,7 @@
// Only a separate transaction until we separate the apply surface changes
// transaction from the global transaction.
- private final SurfaceControl.Transaction mDisplayTransaction = new SurfaceControl.Transaction();
+ private final SurfaceControl.Transaction mDisplayTransaction;
private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
if (w.mHasSurface) {
@@ -154,6 +154,7 @@
RootWindowContainer(WindowManagerService service) {
super(service);
+ mDisplayTransaction = service.mTransactionFactory.get();
mHandler = new MyHandler(service.mH.getLooper());
}
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 82dde0d..cbaf098 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -127,7 +127,7 @@
mOriginalWidth = originalWidth;
mOriginalHeight = originalHeight;
- final SurfaceControl.Transaction t = mService.mTransactionFactory.make();
+ final SurfaceControl.Transaction t = mService.mTransactionFactory.get();
try {
mSurfaceControl = displayContent.makeOverlay()
.setName("ScreenshotSurface")
@@ -137,13 +137,13 @@
// In case display bounds change, screenshot buffer and surface may mismatch so set a
// scaling mode.
- SurfaceControl.Transaction t2 = mService.mTransactionFactory.make();
+ SurfaceControl.Transaction t2 = mService.mTransactionFactory.get();
t2.setOverrideScalingMode(mSurfaceControl, Surface.SCALING_MODE_SCALE_TO_WINDOW);
t2.apply(true /* sync */);
// Capture a screenshot into the surface we just created.
final int displayId = display.getDisplayId();
- final Surface surface = mService.mSurfaceFactory.make();
+ final Surface surface = mService.mSurfaceFactory.get();
surface.copyFrom(mSurfaceControl);
SurfaceControl.ScreenshotGraphicBuffer gb =
mService.mDisplayManagerInternal.screenshot(displayId);
@@ -427,7 +427,7 @@
Slog.i(TAG_WM,
" FREEZE " + mSurfaceControl + ": DESTROY");
}
- mService.mTransactionFactory.make().remove(mSurfaceControl).apply();
+ mService.mTransactionFactory.get().remove(mSurfaceControl).apply();
mSurfaceControl = null;
}
if (mExitingBlackFrame != null) {
diff --git a/services/core/java/com/android/server/wm/StrictModeFlash.java b/services/core/java/com/android/server/wm/StrictModeFlash.java
index 82f2ad8..9e5d9ca 100644
--- a/services/core/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/core/java/com/android/server/wm/StrictModeFlash.java
@@ -27,17 +27,20 @@
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
+import java.util.function.Supplier;
+
class StrictModeFlash {
private static final String TAG = TAG_WITH_CLASS_NAME ? "StrictModeFlash" : TAG_WM;
private final SurfaceControl mSurfaceControl;
- private final Surface mSurface = new Surface();
+ private final Surface mSurface;
private int mLastDW;
private int mLastDH;
private boolean mDrawNeeded;
private final int mThickness = 20;
- public StrictModeFlash(DisplayContent dc) {
+ StrictModeFlash(Supplier<Surface> surfaceFactory, DisplayContent dc) {
+ mSurface = surfaceFactory.get();
SurfaceControl ctrl = null;
try {
ctrl = dc.makeOverlay()
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index 85176be..bbd986f 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -39,6 +39,8 @@
import com.android.server.AnimationThread;
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
+import java.util.function.Supplier;
+
/**
* Class to run animations without holding the window manager lock.
*/
@@ -73,9 +75,10 @@
@GuardedBy("mLock")
private boolean mAnimationStartDeferred;
- SurfaceAnimationRunner(PowerManagerInternal powerManagerInternal) {
- this(null /* callbackProvider */, null /* animatorFactory */, new Transaction(),
- powerManagerInternal);
+ SurfaceAnimationRunner(Supplier<Transaction> transactionFactory,
+ PowerManagerInternal powerManagerInternal) {
+ this(null /* callbackProvider */, null /* animatorFactory */,
+ transactionFactory.get(), powerManagerInternal);
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/wm/SurfaceFactory.java b/services/core/java/com/android/server/wm/SurfaceFactory.java
deleted file mode 100644
index 076b7df..0000000
--- a/services/core/java/com/android/server/wm/SurfaceFactory.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import android.view.Surface;
-
-/**
- * Helper class to inject custom {@link Surface} objects into window manager.
- */
-interface SurfaceFactory {
- Surface make();
-};
-
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index ede2f56..e25ca73 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -71,7 +71,6 @@
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
-import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
@@ -702,7 +701,7 @@
&& toStack.topRunningActivityLocked() != null) {
// Pause the resumed activity on the target stack while re-parenting task on top of it.
toStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
- null /* resuming */, false /* pauseImmediately */);
+ null /* resuming */);
}
final int toStackWindowingMode = toStack.getWindowingMode();
@@ -1405,8 +1404,7 @@
* Completely remove all activities associated with an existing
* task starting at a specified index.
*/
- final void performClearTaskAtIndexLocked(int activityNdx, boolean pauseImmediately,
- String reason) {
+ final void performClearTaskAtIndexLocked(int activityNdx, String reason) {
int numActivities = mActivities.size();
for ( ; activityNdx < numActivities; ++activityNdx) {
final ActivityRecord r = mActivities.get(activityNdx);
@@ -1419,8 +1417,8 @@
mActivities.remove(activityNdx);
--activityNdx;
--numActivities;
- } else if (r.finishIfPossible(Activity.RESULT_CANCELED,
- null /* resultData */, reason, false /* oomAdj */, pauseImmediately)
+ } else if (r.finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
+ false /* oomAdj */)
== FINISH_RESULT_REMOVED) {
--activityNdx;
--numActivities;
@@ -1433,7 +1431,7 @@
*/
void performClearTaskLocked() {
mReuseTask = true;
- performClearTaskAtIndexLocked(0, !PAUSE_IMMEDIATELY, "clear-task-all");
+ performClearTaskAtIndexLocked(0, "clear-task-all");
mReuseTask = false;
}
@@ -1501,9 +1499,9 @@
return null;
}
- void removeTaskActivitiesLocked(boolean pauseImmediately, String reason) {
+ void removeTaskActivitiesLocked(String reason) {
// Just remove the entire task.
- performClearTaskAtIndexLocked(0, pauseImmediately, reason);
+ performClearTaskAtIndexLocked(0, reason);
}
String lockTaskAuthToString() {
diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
index d6c2f66..d36ebf0 100644
--- a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
+++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
@@ -23,6 +23,8 @@
import android.view.SurfaceControl;
import android.view.SurfaceSession;
+import java.util.function.Function;
+
/**
* Class used by {@link RecentsAnimationController} to create a surface control with taking
* screenshot of task when canceling recents animation.
@@ -36,7 +38,7 @@
private int mWidth;
private int mHeight;
- TaskScreenshotAnimatable(Task task,
+ TaskScreenshotAnimatable(Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory, Task task,
SurfaceControl.ScreenshotGraphicBuffer screenshotBuffer) {
GraphicBuffer buffer = screenshotBuffer == null
? null : screenshotBuffer.getGraphicBuffer();
@@ -47,7 +49,7 @@
Slog.d(TAG, "Creating TaskScreenshotAnimatable: task: " + task
+ "width: " + mWidth + "height: " + mHeight);
}
- mSurfaceControl = new SurfaceControl.Builder(new SurfaceSession())
+ mSurfaceControl = surfaceControlFactory.apply(new SurfaceSession())
.setName("RecentTaskScreenshotSurface")
.setBufferSize(mWidth, mHeight)
.build();
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 1b3e4c1..7456f0d 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -237,7 +237,7 @@
int sysUiVis, int windowFlags, int windowPrivateFlags, Rect taskBounds,
int currentOrientation) {
mService = service;
- mSurface = new Surface();
+ mSurface = service.mSurfaceFactory.get();
mHandler = new Handler(mService.mH.getLooper());
mSession = WindowManagerGlobal.getWindowSession();
mWindow = window;
@@ -325,13 +325,13 @@
- ((float) mFrame.width() / mFrame.height())) > 0.01f;
// Keep a reference to it such that it doesn't get destroyed when finalized.
- mChildSurfaceControl = new SurfaceControl.Builder(session)
+ mChildSurfaceControl = mService.mSurfaceControlFactory.apply(session)
.setName(mTitle + " - task-snapshot-surface")
.setBufferSize(buffer.getWidth(), buffer.getHeight())
.setFormat(buffer.getFormat())
.setParent(mSurfaceControl)
.build();
- Surface surface = new Surface();
+ Surface surface = mService.mSurfaceFactory.get();
surface.copyFrom(mChildSurfaceControl);
final Rect frame;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index cc2112e..814bec6 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1009,7 +1009,7 @@
EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
if (mAnimationBackgroundSurface != null) {
- mWmService.mTransactionFactory.make().remove(mAnimationBackgroundSurface).apply();
+ mWmService.mTransactionFactory.get().remove(mAnimationBackgroundSurface).apply();
mAnimationBackgroundSurface = null;
}
diff --git a/services/core/java/com/android/server/wm/TransactionFactory.java b/services/core/java/com/android/server/wm/TransactionFactory.java
deleted file mode 100644
index 067f083..0000000
--- a/services/core/java/com/android/server/wm/TransactionFactory.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2017 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.view.SurfaceControl.Transaction;
-
-/**
- * Helper class to inject custom transaction objects into window manager.
- */
-interface TransactionFactory {
- Transaction make();
-};
-
diff --git a/services/core/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java
index e6ac059..729cfc0 100644
--- a/services/core/java/com/android/server/wm/Watermark.java
+++ b/services/core/java/com/android/server/wm/Watermark.java
@@ -33,6 +33,8 @@
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
+import java.util.function.Supplier;
+
/**
* Displays a watermark on top of the window manager's windows.
*/
@@ -47,19 +49,20 @@
private final int mDeltaY;
private final SurfaceControl mSurfaceControl;
- private final Surface mSurface = new Surface();
+ private final Surface mSurface;
private int mLastDW;
private int mLastDH;
private boolean mDrawNeeded;
- Watermark(DisplayContent dc, DisplayMetrics dm, String[] tokens) {
+ Watermark(Supplier<Surface> surfaceFactory, DisplayContent dc, DisplayMetrics dm,
+ String[] tokens) {
if (false) {
Log.i(TAG_WM, "*********************** WATERMARK");
for (int i=0; i<tokens.length; i++) {
Log.i(TAG_WM, " TOKEN #" + i + ": " + tokens[i]);
}
}
-
+ mSurface = surfaceFactory.get();
mDisplay = dc.getDisplay();
mTokens = tokens;
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index b8db98b..4fce46b 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -83,12 +83,13 @@
private final ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>();
private boolean mInExecuteAfterPrepareSurfacesRunnables;
- private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
+ private final SurfaceControl.Transaction mTransaction;
WindowAnimator(final WindowManagerService service) {
mService = service;
mContext = service.mContext;
mPolicy = service.mPolicy;
+ mTransaction = service.mTransactionFactory.get();
AnimationThread.getHandler().runWithScissors(
() -> mChoreographer = Choreographer.getSfInstance(), 0 /* timeout */);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 29d232f..e280a663 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -139,7 +139,7 @@
WindowContainer(WindowManagerService wms) {
mWmService = wms;
- mPendingTransaction = wms.mTransactionFactory.make();
+ mPendingTransaction = wms.mTransactionFactory.get();
mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index fa1ace6..8d3a107 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -286,6 +286,8 @@
import java.util.Arrays;
import java.util.Date;
import java.util.List;
+import java.util.function.Function;
+import java.util.function.Supplier;
/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
@@ -911,9 +913,9 @@
static WindowManagerThreadPriorityBooster sThreadPriorityBooster =
new WindowManagerThreadPriorityBooster();
- SurfaceBuilderFactory mSurfaceBuilderFactory = SurfaceControl.Builder::new;
- TransactionFactory mTransactionFactory = SurfaceControl.Transaction::new;
- SurfaceFactory mSurfaceFactory = Surface::new;
+ Function<SurfaceSession, SurfaceControl.Builder> mSurfaceControlFactory;
+ Supplier<SurfaceControl.Transaction> mTransactionFactory;
+ final Supplier<Surface> mSurfaceFactory;
private final SurfaceControl.Transaction mTransaction;
@@ -1013,20 +1015,22 @@
final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
ActivityTaskManagerService atm) {
return main(context, im, showBootMsgs, onlyCore, policy, atm,
- SurfaceControl.Transaction::new);
+ SurfaceControl.Transaction::new, Surface::new, SurfaceControl.Builder::new);
}
/**
* Creates and returns an instance of the WindowManagerService. This call allows the caller
- * to override the {@link TransactionFactory} to stub functionality under test.
+ * to override factories that can be used to stub native calls during test.
*/
@VisibleForTesting
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
- ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
+ ActivityTaskManagerService atm, Supplier<SurfaceControl.Transaction> transactionFactory,
+ Supplier<Surface> surfaceFactory,
+ Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
DisplayThread.getHandler().runWithScissors(() ->
sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
- atm, transactionFactory), 0);
+ atm, transactionFactory, surfaceFactory, surfaceControlFactory), 0);
return sInstance;
}
@@ -1048,7 +1052,9 @@
private WindowManagerService(Context context, InputManagerService inputManager,
boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
- ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
+ ActivityTaskManagerService atm, Supplier<SurfaceControl.Transaction> transactionFactory,
+ Supplier<Surface> surfaceFactory,
+ Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
installLock(this, INDEX_WINDOW);
mGlobalLock = atm.getGlobalLock();
mAtmService = atm;
@@ -1076,10 +1082,13 @@
com.android.internal.R.bool.config_lowRamTaskSnapshotsAndRecents);
mInputManager = inputManager; // Must be before createDisplayContentLocked.
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
- mDisplayWindowSettings = new DisplayWindowSettings(this);
+ mSurfaceControlFactory = surfaceControlFactory;
mTransactionFactory = transactionFactory;
- mTransaction = mTransactionFactory.make();
+ mSurfaceFactory = surfaceFactory;
+ mTransaction = mTransactionFactory.get();
+
+ mDisplayWindowSettings = new DisplayWindowSettings(this);
mPolicy = policy;
mAnimator = new WindowAnimator(this);
mRoot = new RootWindowContainer(this);
@@ -1183,7 +1192,8 @@
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
mHoldingScreenWakeLock.setReferenceCounted(false);
- mSurfaceAnimationRunner = new SurfaceAnimationRunner(mPowerManagerInternal);
+ mSurfaceAnimationRunner = new SurfaceAnimationRunner(mTransactionFactory,
+ mPowerManagerInternal);
mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
@@ -3460,7 +3470,7 @@
int maskThickness = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.circular_display_mask_thickness);
- mCircularDisplayMask = new CircularDisplayMask(
+ mCircularDisplayMask = new CircularDisplayMask(mSurfaceFactory,
getDefaultDisplayContentLocked(),
mPolicy.getWindowLayerFromTypeLw(
WindowManager.LayoutParams.TYPE_POINTER)
@@ -3488,6 +3498,7 @@
try {
if (mEmulatorDisplayOverlay == null) {
mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
+ mSurfaceFactory,
mContext,
getDefaultDisplayContentLocked(),
mPolicy.getWindowLayerFromTypeLw(
@@ -3536,7 +3547,7 @@
try {
// TODO(multi-display): support multiple displays
if (mStrictModeFlash == null) {
- mStrictModeFlash = new StrictModeFlash(
+ mStrictModeFlash = new StrictModeFlash(mSurfaceFactory,
getDefaultDisplayContentLocked());
}
mStrictModeFlash.setVisibility(on);
@@ -5553,7 +5564,8 @@
if (toks != null && toks.length > 0) {
// TODO(multi-display): Show watermarks on secondary displays.
final DisplayContent displayContent = getDefaultDisplayContentLocked();
- mWatermark = new Watermark(displayContent, displayContent.mRealDisplayMetrics,
+ mWatermark = new Watermark(mSurfaceFactory, displayContent,
+ displayContent.mRealDisplayMetrics,
toks);
}
}
@@ -7544,7 +7556,7 @@
}
SurfaceControl.Builder makeSurfaceBuilder(SurfaceSession s) {
- return mSurfaceBuilderFactory.make(s);
+ return mSurfaceControlFactory.apply(s);
}
/**
@@ -7616,7 +7628,8 @@
mRoot.forAllDisplays(displayContent ->
displayContent.getInputMonitor().updateInputWindowsImmediately());
}
- new SurfaceControl.Transaction().syncInputWindows().apply(true);
+
+ mTransactionFactory.get().syncInputWindows().apply(true);
}
private void waitForAnimationsToComplete() {
@@ -7738,7 +7751,7 @@
h.replaceTouchableRegionWithCrop(null);
SurfaceSession s = new SurfaceSession();
- SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ SurfaceControl.Transaction t = mTransactionFactory.get();
t.setInputWindowInfo(surface, h);
t.apply();
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 242b116..8c51452 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -620,7 +620,7 @@
final ActivityStack stack = mPreQTopResumedActivity.getActivityStack();
if (stack != null) {
stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
- null /* resuming */, false /* pauseImmediately */);
+ activity);
}
}
mPreQTopResumedActivity = activity;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index ae3a10a..8e679d4 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -159,7 +159,7 @@
* window is first added or shown, cleared when the callback has been made. */
boolean mEnteringAnimation;
- private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
+ private final SurfaceControl.Transaction mTmpTransaction;
/** The pixel format of the underlying SurfaceControl */
int mSurfaceFormat;
@@ -246,6 +246,7 @@
final WindowManagerService service = win.mWmService;
mService = service;
+ mTmpTransaction = service.mTransactionFactory.get();
mAnimator = service.mAnimator;
mPolicy = service.mPolicy;
mContext = service.mContext;
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index bcefa8f..8cede6c 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -81,7 +81,7 @@
private final int mWindowType;
private final Session mWindowSession;
- private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
+ private final SurfaceControl.Transaction mTmpTransaction;
public WindowSurfaceController(SurfaceSession s, String name, int w, int h, int format,
int flags, WindowStateAnimator animator, int windowType, int ownerUid) {
@@ -96,6 +96,7 @@
final WindowState win = animator.mWin;
mWindowType = windowType;
mWindowSession = win.mSession;
+ mTmpTransaction = mService.mTransactionFactory.get();
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
final SurfaceControl.Builder b = win.makeSurface()
diff --git a/services/net/java/android/net/ConnectivityModuleConnector.java b/services/net/java/android/net/ConnectivityModuleConnector.java
index 7333f58..62f2c35 100644
--- a/services/net/java/android/net/ConnectivityModuleConnector.java
+++ b/services/net/java/android/net/ConnectivityModuleConnector.java
@@ -38,6 +38,7 @@
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import java.io.File;
import java.io.PrintWriter;
@@ -76,8 +77,17 @@
private final SharedLog mLog = new SharedLog(TAG);
@GuardedBy("mHealthListeners")
private final ArraySet<ConnectivityModuleHealthListener> mHealthListeners = new ArraySet<>();
+ @NonNull
+ private final Dependencies mDeps;
- private ConnectivityModuleConnector() { }
+ private ConnectivityModuleConnector() {
+ this(new DependenciesImpl());
+ }
+
+ @VisibleForTesting
+ ConnectivityModuleConnector(@NonNull Dependencies deps) {
+ mDeps = deps;
+ }
/**
* Get the {@link ConnectivityModuleConnector} singleton instance.
@@ -124,6 +134,59 @@
void onModuleServiceConnected(@NonNull IBinder iBinder);
}
+ /**
+ * Interface used to determine the intent to use to bind to the module. Useful for testing.
+ */
+ @VisibleForTesting
+ protected interface Dependencies {
+ /**
+ * Determine the intent to use to bind to the module.
+ * @return null if the intent could not be resolved, the intent otherwise.
+ */
+ @Nullable
+ Intent getModuleServiceIntent(
+ @NonNull PackageManager pm, @NonNull String serviceIntentBaseAction,
+ @NonNull String servicePermissionName, boolean inSystemProcess);
+ }
+
+ private static class DependenciesImpl implements Dependencies {
+ @Nullable
+ @Override
+ public Intent getModuleServiceIntent(
+ @NonNull PackageManager pm, @NonNull String serviceIntentBaseAction,
+ @NonNull String servicePermissionName, boolean inSystemProcess) {
+ final Intent intent =
+ new Intent(inSystemProcess
+ ? serviceIntentBaseAction + IN_PROCESS_SUFFIX
+ : serviceIntentBaseAction);
+ final ComponentName comp = intent.resolveSystemService(pm, 0);
+ if (comp == null) {
+ return null;
+ }
+ intent.setComponent(comp);
+
+ final int uid;
+ try {
+ uid = pm.getPackageUidAsUser(comp.getPackageName(), UserHandle.USER_SYSTEM);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new SecurityException(
+ "Could not check network stack UID; package not found.", e);
+ }
+
+ final int expectedUid =
+ inSystemProcess ? Process.SYSTEM_UID : Process.NETWORK_STACK_UID;
+ if (uid != expectedUid) {
+ throw new SecurityException("Invalid network stack UID: " + uid);
+ }
+
+ if (!inSystemProcess) {
+ checkModuleServicePermission(pm, comp, servicePermissionName);
+ }
+
+ return intent;
+ }
+ }
+
/**
* Add a {@link ConnectivityModuleHealthListener} to listen to network stack health events.
@@ -156,13 +219,13 @@
final PackageManager pm = mContext.getPackageManager();
// Try to bind in-process if the device was shipped with an in-process version
- Intent intent = getModuleServiceIntent(pm, serviceIntentBaseAction, servicePermissionName,
- true /* inSystemProcess */);
+ Intent intent = mDeps.getModuleServiceIntent(pm, serviceIntentBaseAction,
+ servicePermissionName, true /* inSystemProcess */);
// Otherwise use the updatable module version
if (intent == null) {
- intent = getModuleServiceIntent(pm, serviceIntentBaseAction, servicePermissionName,
- false /* inSystemProcess */);
+ intent = mDeps.getModuleServiceIntent(pm, serviceIntentBaseAction,
+ servicePermissionName, false /* inSystemProcess */);
log("Starting networking module in network_stack process");
} else {
log("Starting networking module in system_server process");
@@ -219,41 +282,7 @@
}
}
- @Nullable
- private Intent getModuleServiceIntent(
- @NonNull PackageManager pm, @NonNull String serviceIntentBaseAction,
- @NonNull String servicePermissionName, boolean inSystemProcess) {
- final Intent intent =
- new Intent(inSystemProcess
- ? serviceIntentBaseAction + IN_PROCESS_SUFFIX
- : serviceIntentBaseAction);
- final ComponentName comp = intent.resolveSystemService(pm, 0);
- if (comp == null) {
- return null;
- }
- intent.setComponent(comp);
-
- int uid = -1;
- try {
- uid = pm.getPackageUidAsUser(comp.getPackageName(), UserHandle.USER_SYSTEM);
- } catch (PackageManager.NameNotFoundException e) {
- logWtf("Networking module package not found", e);
- // Fall through
- }
-
- final int expectedUid = inSystemProcess ? Process.SYSTEM_UID : Process.NETWORK_STACK_UID;
- if (uid != expectedUid) {
- throw new SecurityException("Invalid network stack UID: " + uid);
- }
-
- if (!inSystemProcess) {
- checkModuleServicePermission(pm, comp, servicePermissionName);
- }
-
- return intent;
- }
-
- private void checkModuleServicePermission(
+ private static void checkModuleServicePermission(
@NonNull PackageManager pm, @NonNull ComponentName comp,
@NonNull String servicePermissionName) {
final int hasPermission =
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index abb4666..69e2406 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -35,6 +35,7 @@
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -51,6 +52,9 @@
private static NetworkStackClient sInstance;
@NonNull
+ private final Dependencies mDependencies;
+
+ @NonNull
@GuardedBy("mPendingNetStackRequests")
private final ArrayList<NetworkStackCallback> mPendingNetStackRequests = new ArrayList<>();
@Nullable
@@ -66,7 +70,50 @@
void onNetworkStackConnected(INetworkStackConnector connector);
}
- private NetworkStackClient() { }
+ @VisibleForTesting
+ protected NetworkStackClient(@NonNull Dependencies dependencies) {
+ mDependencies = dependencies;
+ }
+
+ private NetworkStackClient() {
+ this(new DependenciesImpl());
+ }
+
+ @VisibleForTesting
+ protected interface Dependencies {
+ void addToServiceManager(@NonNull IBinder service);
+ void checkCallerUid();
+ ConnectivityModuleConnector getConnectivityModuleConnector();
+ }
+
+ private static class DependenciesImpl implements Dependencies {
+ @Override
+ public void addToServiceManager(@NonNull IBinder service) {
+ ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service,
+ false /* allowIsolated */, DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
+ }
+
+ @Override
+ public void checkCallerUid() {
+ final int caller = Binder.getCallingUid();
+ // This is a client lib so "caller" is the current UID in most cases. The check is done
+ // here in the caller's process just to provide a nicer error message to clients; more
+ // generic checks are also done in NetworkStackService.
+ // See PermissionUtil in NetworkStack for the actual check on the service side - the
+ // checks here should be kept in sync with PermissionUtil.
+ if (caller != Process.SYSTEM_UID
+ && caller != Process.NETWORK_STACK_UID
+ && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) {
+ throw new SecurityException(
+ "Only the system server should try to bind to the network stack.");
+ }
+ }
+
+ @Override
+ public ConnectivityModuleConnector getConnectivityModuleConnector() {
+ return ConnectivityModuleConnector.getInstance();
+ }
+ }
/**
* Get the NetworkStackClient singleton instance.
@@ -150,9 +197,7 @@
private void registerNetworkStackService(@NonNull IBinder service) {
final INetworkStackConnector connector = INetworkStackConnector.Stub.asInterface(service);
-
- ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service, false /* allowIsolated */,
- DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
+ mDependencies.addToServiceManager(service);
log("Network stack service registered");
final ArrayList<NetworkStackCallback> requests;
@@ -185,7 +230,7 @@
* started.
*/
public void start() {
- ConnectivityModuleConnector.getInstance().startModuleService(
+ mDependencies.getConnectivityModuleConnector().startModuleService(
INetworkStackConnector.class.getName(), PERMISSION_MAINLINE_NETWORK_STACK,
new NetworkStackConnection());
log("Network stack service start requested");
@@ -251,16 +296,7 @@
}
private void requestConnector(@NonNull NetworkStackCallback request) {
- // TODO: PID check.
- final int caller = Binder.getCallingUid();
- if (caller != Process.SYSTEM_UID
- && caller != Process.NETWORK_STACK_UID
- && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)
- && !UserHandle.isSameApp(caller, Process.PHONE_UID)) {
- // Don't even attempt to obtain the connector and give a nice error message
- throw new SecurityException(
- "Only the system server should try to bind to the network stack.");
- }
+ mDependencies.checkCallerUid();
if (!mWasSystemServerInitialized) {
// The network stack is not being started in this process, e.g. this process is not
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 9670899..1685b04 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -1486,6 +1486,45 @@
SCHED_GROUP_DEFAULT);
}
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoAll_ServiceB() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ long now = SystemClock.uptimeMillis();
+ ServiceRecord s = bindService(app, app2, null, 0, mock(IBinder.class));
+ s.startRequested = true;
+ s.lastActivity = now;
+ s = bindService(app2, app, null, 0, mock(IBinder.class));
+ s.startRequested = true;
+ s.lastActivity = now;
+ ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ s = mock(ServiceRecord.class);
+ s.app = app3;
+ setFieldValue(ServiceRecord.class, s, "connections",
+ new ArrayMap<IBinder, ArrayList<ConnectionRecord>>());
+ app3.services.add(s);
+ doCallRealMethod().when(s).getConnections();
+ s.startRequested = true;
+ s.lastActivity = now;
+ ArrayList<ProcessRecord> lru = sService.mProcessList.mLruProcesses;
+ lru.clear();
+ lru.add(app3);
+ lru.add(app2);
+ lru.add(app);
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.mNumServiceProcs = 3;
+ sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+ lru.clear();
+
+ assertEquals(SERVICE_B_ADJ, app3.setAdj);
+ assertEquals(SERVICE_ADJ, app2.setAdj);
+ assertEquals(SERVICE_ADJ, app.setAdj);
+ }
+
private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,
String packageName, boolean hasShownUi) {
long now = SystemClock.uptimeMillis();
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 977dd8e..aaaa7a5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -47,6 +47,7 @@
import org.mockito.ArgumentMatcher;
import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
/**
* Tests for the {@link ActivityMetricsLaunchObserver} class.
@@ -118,7 +119,7 @@
static <T> T verifyAsync(T mock) {
// AMLO callbacks happen on a separate thread than AML calls, so we need to use a timeout.
- return verify(mock, timeout(100));
+ return verify(mock, timeout(TimeUnit.SECONDS.toMillis(5)));
}
@Test
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 f548225..7b06490 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -820,7 +820,7 @@
mActivity.setState(RESUMED, "test");
mActivity.finishIfPossible(0 /* resultCode */, null /* resultData */, "test",
- false /* oomAdj */, false /* pauseImmediately */);
+ false /* oomAdj */);
assertTrue(stack1.isTopStackOnDisplay());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index c83e5cb..2a8b4c8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -25,6 +25,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -980,6 +981,19 @@
}
@Test
+ public void testCompletePauseOnResumeWhilePausingActivity() {
+ final ActivityRecord bottomActivity = new ActivityBuilder(mService).setTask(mTask).build();
+ doReturn(true).when(bottomActivity).attachedToProcess();
+ mStack.mPausingActivity = null;
+ mStack.mResumedActivity = bottomActivity;
+ final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
+ topActivity.info.flags |= FLAG_RESUME_WHILE_PAUSING;
+
+ mStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */, topActivity);
+ verify(mStack).completePauseLocked(anyBoolean(), eq(topActivity));
+ }
+
+ @Test
public void testAdjustFocusedStackToHomeWhenNoActivity() {
final ActivityStack homeStask = mDefaultDisplay.getHomeStack();
TaskRecord homeTask = homeStask.topTask();
diff --git a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
index daee911..fa83f85 100644
--- a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
@@ -16,7 +16,7 @@
package com.android.server.wm;
-import static android.provider.DeviceConfig.WindowManager.KEY_HIGH_REFRESH_RATE_BLACKLIST;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_HIGH_REFRESH_RATE_BLACKLIST;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -128,9 +128,9 @@
@Override
public String getProperty(String namespace, String name) {
- if (!DeviceConfig.NAMESPACE_WINDOW_MANAGER.equals(namespace)
+ if (!DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace)
|| !KEY_HIGH_REFRESH_RATE_BLACKLIST.equals(name)) {
- throw new IllegalArgumentException("Only things in NAMESPACE_WINDOW_MANAGER "
+ throw new IllegalArgumentException("Only things in NAMESPACE_DISPLAY_MANAGER "
+ "supported.");
}
return mBlacklist;
@@ -140,8 +140,8 @@
public void addOnPropertiesChangedListener(String namespace, Executor executor,
DeviceConfig.OnPropertiesChangedListener listener) {
- if (!DeviceConfig.NAMESPACE_WINDOW_MANAGER.equals(namespace)) {
- throw new IllegalArgumentException("Only things in NAMESPACE_WINDOW_MANAGER "
+ if (!DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace)) {
+ throw new IllegalArgumentException("Only things in NAMESPACE_DISPLAY_MANAGER "
+ "supported.");
}
mListeners.add(new Pair<>(listener, executor));
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
index c52c8d7..2d0416d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
@@ -48,7 +48,7 @@
@Before
public void setUp() throws Exception {
mSurfaces = new SurfaceControlMocker();
- mLetterbox = new Letterbox(mSurfaces);
+ mLetterbox = new Letterbox(mSurfaces, () -> mock(SurfaceControl.Transaction.class));
mTransaction = mock(SurfaceControl.Transaction.class);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 21ed285..43c6b35 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -257,17 +257,14 @@
// Suppress StrictMode violation (DisplayWindowSettings) to avoid log flood.
DisplayThread.getHandler().post(StrictMode::allowThreadDiskWritesMask);
mWmService = WindowManagerService.main(
- mContext, mImService, false, false, mWMPolicy, mAtmService, StubTransaction::new);
+ mContext, mImService, false, false, mWMPolicy, mAtmService, StubTransaction::new,
+ () -> mock(Surface.class), (unused) -> new MockSurfaceControlBuilder());
spyOn(mWmService);
// Setup factory classes to prevent calls to native code.
mTransaction = spy(StubTransaction.class);
// Return a spied Transaction class than can be used to verify calls.
mWmService.mTransactionFactory = () -> mTransaction;
- // Return a SurfaceControl.Builder class that creates mocked SurfaceControl instances.
- mWmService.mSurfaceBuilderFactory = (unused) -> new MockSurfaceControlBuilder();
- // Return mocked Surface instances.
- mWmService.mSurfaceFactory = () -> mock(Surface.class);
mWmService.mSurfaceAnimationRunner = new SurfaceAnimationRunner(
null, null, mTransaction, mWmService.mPowerManagerInternal);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 7d7c398..2105ab0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -51,6 +51,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
+import java.util.function.Function;
/**
* Tests for the {@link DisplayContent#assignChildLayers(SurfaceControl.Transaction)} method.
@@ -131,7 +132,8 @@
}
}
- private static class HierarchyRecordingBuilderFactory implements SurfaceBuilderFactory {
+ private static class HierarchyRecordingBuilderFactory implements Function<SurfaceSession,
+ SurfaceControl.Builder> {
private LayerRecordingTransaction mTransaction;
HierarchyRecordingBuilderFactory(LayerRecordingTransaction transaction) {
@@ -139,7 +141,7 @@
}
@Override
- public SurfaceControl.Builder make(SurfaceSession s) {
+ public SurfaceControl.Builder apply(SurfaceSession s) {
final LayerRecordingTransaction transaction = mTransaction;
return new HierarchyRecorder(s, transaction);
}
@@ -153,7 +155,7 @@
// which is after construction of the DisplayContent, meaning the HierarchyRecorder
// would miss construction of the top-level layers.
mTransaction = new LayerRecordingTransaction();
- mWm.mSurfaceBuilderFactory = new HierarchyRecordingBuilderFactory(mTransaction);
+ mWm.mSurfaceControlFactory = new HierarchyRecordingBuilderFactory(mTransaction);
mWm.mTransactionFactory = () -> mTransaction;
}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index a8cafb3..1dd3972 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -666,6 +666,23 @@
return ret;
}
}
+
+ @Override
+ @Nullable
+ public ModuleProperties getModuleProperties() {
+ enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+ if (!isInitialized()) return null;
+ if (DEBUG) {
+ Slog.i(TAG, "getModuleProperties()");
+ }
+
+ synchronized (mLock) {
+ ModuleProperties properties = mSoundTriggerHelper.getModuleProperties();
+ sEventLogger.log(new SoundTriggerLogger.StringEvent(
+ "getModuleProperties(): " + properties.toString()));
+ return properties;
+ }
+ }
}
/**
diff --git a/startop/scripts/app_startup/lib/adb_utils.py b/startop/scripts/app_startup/lib/adb_utils.py
index e56a968..3cebc9a 100644
--- a/startop/scripts/app_startup/lib/adb_utils.py
+++ b/startop/scripts/app_startup/lib/adb_utils.py
@@ -42,8 +42,8 @@
def vm_drop_cache():
"""Free pagecache and slab object."""
cmd_utils.run_adb_shell_command('echo 3 > /proc/sys/vm/drop_caches')
- # Sleep a little bit to provide enougth time for cache cleanup.
- time.sleep(2)
+ # Sleep a little bit to provide enough time for cache cleanup.
+ time.sleep(1)
def root():
"""Roots adb and successive adb commands will run under root."""
diff --git a/startop/scripts/iorap/compiler.py b/startop/scripts/iorap/compiler.py
index c940fe9..17b58c1 100755
--- a/startop/scripts/iorap/compiler.py
+++ b/startop/scripts/iorap/compiler.py
@@ -190,6 +190,7 @@
MmFilemapAddToPageCache.raw_ftrace_entry).order_by(
RawFtraceEntry.timestamp).first()
+ # total_seconds() will return a float number.
return first_event.raw_ftrace_entry.timestamp + trace_duration.total_seconds()
def query_add_to_page_cache(trace2db: Trace2Db, trace_duration: Optional[timedelta]):
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 475563d..f25b012 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3132,19 +3132,62 @@
*/
@SystemApi
public int getSimCardState() {
- int simCardState = getSimState();
- switch (simCardState) {
+ int simState = getSimState();
+ return getSimCardStateFromSimState(simState);
+ }
+
+ /**
+ * Returns a constant indicating the state of the device SIM card in a physical slot.
+ *
+ * @param physicalSlotIndex physical slot index
+ *
+ * @see #SIM_STATE_UNKNOWN
+ * @see #SIM_STATE_ABSENT
+ * @see #SIM_STATE_CARD_IO_ERROR
+ * @see #SIM_STATE_CARD_RESTRICTED
+ * @see #SIM_STATE_PRESENT
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public int getSimCardState(int physicalSlotIndex) {
+ int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex));
+ return getSimCardStateFromSimState(simState);
+ }
+
+ /**
+ * Converts SIM state to SIM card state.
+ * @param simState
+ * @return SIM card state
+ */
+ private int getSimCardStateFromSimState(int simState) {
+ switch (simState) {
case SIM_STATE_UNKNOWN:
case SIM_STATE_ABSENT:
case SIM_STATE_CARD_IO_ERROR:
case SIM_STATE_CARD_RESTRICTED:
- return simCardState;
+ return simState;
default:
return SIM_STATE_PRESENT;
}
}
/**
+ * Converts a physical slot index to logical slot index.
+ * @param physicalSlotIndex physical slot index
+ * @return logical slot index
+ */
+ private int getLogicalSlotIndex(int physicalSlotIndex) {
+ UiccSlotInfo[] slotInfos = getUiccSlotsInfo();
+ if (slotInfos != null && physicalSlotIndex >= 0 && physicalSlotIndex < slotInfos.length) {
+ return slotInfos[physicalSlotIndex].getLogicalSlotIdx();
+ }
+
+ return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+ }
+
+ /**
* Returns a constant indicating the state of the card applications on the default SIM card.
*
* @see #SIM_STATE_UNKNOWN
@@ -3159,8 +3202,41 @@
*/
@SystemApi
public int getSimApplicationState() {
- int simApplicationState = getSimStateIncludingLoaded();
- switch (simApplicationState) {
+ int simState = getSimStateIncludingLoaded();
+ return getSimApplicationStateFromSimState(simState);
+ }
+
+ /**
+ * Returns a constant indicating the state of the card applications on the device SIM card in
+ * a physical slot.
+ *
+ * @param physicalSlotIndex physical slot index
+ *
+ * @see #SIM_STATE_UNKNOWN
+ * @see #SIM_STATE_PIN_REQUIRED
+ * @see #SIM_STATE_PUK_REQUIRED
+ * @see #SIM_STATE_NETWORK_LOCKED
+ * @see #SIM_STATE_NOT_READY
+ * @see #SIM_STATE_PERM_DISABLED
+ * @see #SIM_STATE_LOADED
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public int getSimApplicationState(int physicalSlotIndex) {
+ int simState =
+ SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex));
+ return getSimApplicationStateFromSimState(simState);
+ }
+
+ /**
+ * Converts SIM state to SIM application state.
+ * @param simState
+ * @return SIM application state
+ */
+ private int getSimApplicationStateFromSimState(int simState) {
+ switch (simState) {
case SIM_STATE_UNKNOWN:
case SIM_STATE_ABSENT:
case SIM_STATE_CARD_IO_ERROR:
@@ -3171,14 +3247,14 @@
// NOT_READY to either LOCKED or LOADED.
return SIM_STATE_NOT_READY;
default:
- return simApplicationState;
+ return simState;
}
}
/**
- * Returns a constant indicating the state of the device SIM card in a slot.
+ * Returns a constant indicating the state of the device SIM card in a logical slot.
*
- * @param slotIndex
+ * @param slotIndex logical slot index
*
* @see #SIM_STATE_UNKNOWN
* @see #SIM_STATE_ABSENT
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index da32c8c..28b331b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -1496,7 +1496,7 @@
*
* @return true if this is a USIM data download message; false otherwise
*/
- boolean isUsimDataDownload() {
+ public boolean isUsimDataDownload() {
return messageClass == MessageClass.CLASS_2 &&
(mProtocolIdentifier == 0x7f || mProtocolIdentifier == 0x7c);
}
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index c42201f..47fefae 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -782,7 +782,7 @@
Handler handler = new Handler(mTestLooper.getLooper());
PackageWatchdog watchdog =
new PackageWatchdog(mSpyContext, policyFile, handler, handler, controller,
- mConnectivityModuleConnector);
+ mConnectivityModuleConnector, android.os.SystemClock::uptimeMillis);
// Verify controller is not automatically started
assertFalse(controller.mIsEnabled);
if (withPackagesReady) {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 6ae639a..caa3203 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -184,6 +184,7 @@
import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -2187,6 +2188,7 @@
}
@Test
+ @FlakyTest(bugId = 140306320)
public void testPartialConnectivity() throws Exception {
// Register network callback.
NetworkRequest request = new NetworkRequest.Builder()
@@ -3633,6 +3635,7 @@
}
@Test
+ @FlakyTest(bugId = 140305589)
public void testPacketKeepalives() throws Exception {
InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
@@ -5697,6 +5700,7 @@
}
@Test
+ @FlakyTest(bugId = 140305678)
public void testTcpBufferReset() throws Exception {
final String testTcpBufferSizes = "1,2,3,4,5,6";
final NetworkRequest networkRequest = new NetworkRequest.Builder()