Merge "Retire preliminary FGS deferral control API" into sc-dev
diff --git a/Android.bp b/Android.bp
index 9023a19..4d8924d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -273,6 +273,11 @@
installable: false,
}
+filegroup {
+ name: "framework-jarjar-rules",
+ srcs: ["framework-jarjar-rules.txt"],
+}
+
java_defaults {
name: "framework-minus-apex-defaults",
defaults: ["framework-aidl-export-defaults"],
@@ -294,7 +299,7 @@
"--core-library",
"--multi-dex",
],
- jarjar_rules: "framework-jarjar-rules.txt",
+ jarjar_rules: ":framework-jarjar-rules",
javac_shard_size: 150,
plugins: [
"view-inspector-annotation-processor",
diff --git a/StubLibraries.bp b/StubLibraries.bp
index ed24d43..b6c45ed 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -255,7 +255,7 @@
modules_system_stubs = [
"android.net.ipsec.ike.stubs.system",
- "art.module.public.api.stubs", // Only has public stubs
+ "art.module.public.api.stubs.system",
"conscrypt.module.public.api.stubs", // Only has public stubs
"framework-appsearch.stubs.system",
"framework-connectivity.stubs.system",
diff --git a/api/Android.bp b/api/Android.bp
index b85dc46..db1f64c 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -161,6 +161,7 @@
genrule {
name: "frameworks-base-api-system-current.txt",
srcs: [
+ ":art.module.public.api{.system.api.txt}",
":android.net.ipsec.ike{.system.api.txt}",
":framework-appsearch{.system.api.txt}",
":framework-connectivity{.system.api.txt}",
@@ -215,6 +216,7 @@
genrule {
name: "frameworks-base-api-system-removed.txt",
srcs: [
+ ":art.module.public.api{.system.removed-api.txt}",
":android.net.ipsec.ike{.system.removed-api.txt}",
":framework-appsearch{.system.removed-api.txt}",
":framework-connectivity{.system.removed-api.txt}",
@@ -251,6 +253,7 @@
genrule {
name: "frameworks-base-api-module-lib-current.txt",
srcs: [
+ ":art.module.public.api{.module-lib.api.txt}",
":android.net.ipsec.ike{.module-lib.api.txt}",
":framework-appsearch{.module-lib.api.txt}",
":framework-connectivity{.module-lib.api.txt}",
@@ -307,6 +310,7 @@
genrule {
name: "frameworks-base-api-module-lib-removed.txt",
srcs: [
+ ":art.module.public.api{.module-lib.removed-api.txt}",
":android.net.ipsec.ike{.module-lib.removed-api.txt}",
":framework-appsearch{.module-lib.removed-api.txt}",
":framework-connectivity{.module-lib.removed-api.txt}",
diff --git a/boot/Android.bp b/boot/Android.bp
index e8d88a5..3caede4 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -48,57 +48,13 @@
// bootclasspath.
fragments: [
{
- apex: "com.android.appsearch",
- module: "com.android.appsearch-bootclasspath-fragment",
- },
- {
apex: "com.android.art",
module: "art-bootclasspath-fragment",
},
{
- apex: "com.android.conscrypt",
- module: "com.android.conscrypt-bootclasspath-fragment",
- },
- {
apex: "com.android.i18n",
module: "i18n-bootclasspath-fragment",
},
- {
- apex: "com.android.ipsec",
- module: "com.android.ipsec-bootclasspath-fragment",
- },
- {
- apex: "com.android.media",
- module: "com.android.media-bootclasspath-fragment",
- },
- {
- apex: "com.android.mediaprovider",
- module: "com.android.mediaprovider-bootclasspath-fragment",
- },
- {
- apex: "com.android.os.statsd",
- module: "com.android.os.statsd-bootclasspath-fragment",
- },
- {
- apex: "com.android.permission",
- module: "com.android.permission-bootclasspath-fragment",
- },
- {
- apex: "com.android.scheduling",
- module: "com.android.scheduling-bootclasspath-fragment",
- },
- {
- apex: "com.android.sdkext",
- module: "com.android.sdkext-bootclasspath-fragment",
- },
- {
- apex: "com.android.tethering",
- module: "com.android.tethering-bootclasspath-fragment",
- },
- {
- apex: "com.android.wifi",
- module: "com.android.wifi-bootclasspath-fragment",
- },
],
// Additional information needed by hidden api processing.
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index d939438..6f68e3f 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1458,6 +1458,7 @@
method public long getTimestampMillis();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.search.Query> CREATOR;
+ field public static final String EXTRA_IME_HEIGHT = "android.app.search.extra.IME_HEIGHT";
}
public final class SearchAction implements android.os.Parcelable {
@@ -1526,7 +1527,7 @@
method @Nullable public android.content.pm.ShortcutInfo getShortcutInfo();
method @Nullable public android.net.Uri getSliceUri();
method @NonNull public android.os.UserHandle getUserHandle();
- method public boolean shouldHide();
+ method public boolean isHidden();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.search.SearchTarget> CREATOR;
field public static final String LAYOUT_TYPE_ICON = "icon";
@@ -1543,12 +1544,12 @@
method @NonNull public android.app.search.SearchTarget build();
method @NonNull public android.app.search.SearchTarget.Builder setAppWidgetProviderInfo(@NonNull android.appwidget.AppWidgetProviderInfo);
method @NonNull public android.app.search.SearchTarget.Builder setExtras(@NonNull android.os.Bundle);
+ method @NonNull public android.app.search.SearchTarget.Builder setHidden(boolean);
method @NonNull public android.app.search.SearchTarget.Builder setPackageName(@NonNull String);
method @NonNull public android.app.search.SearchTarget.Builder setParentId(@NonNull String);
method @NonNull public android.app.search.SearchTarget.Builder setScore(@FloatRange(from=0.0f, to=1.0f) float);
method @NonNull public android.app.search.SearchTarget.Builder setSearchAction(@Nullable android.app.search.SearchAction);
method @NonNull public android.app.search.SearchTarget.Builder setShortcutInfo(@NonNull android.content.pm.ShortcutInfo);
- method @NonNull public android.app.search.SearchTarget.Builder setShouldHide(boolean);
method @NonNull public android.app.search.SearchTarget.Builder setSliceUri(@NonNull android.net.Uri);
method @NonNull public android.app.search.SearchTarget.Builder setUserHandle(@NonNull android.os.UserHandle);
}
@@ -2246,7 +2247,7 @@
package android.companion {
public final class CompanionDeviceManager {
- method @RequiresPermission(android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES) public void associate(@NonNull String, @NonNull android.net.MacAddress);
+ method @RequiresPermission(android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES) public void associate(@NonNull String, @NonNull android.net.MacAddress, @NonNull byte[]);
method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean canPairWithoutPrompt(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociatedForWifiConnection(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
}
@@ -10416,11 +10417,11 @@
ctor public TranslationService();
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
method public void onConnected();
- method public void onCreateTranslationSession(@NonNull android.view.translation.TranslationContext, int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+ method public abstract void onCreateTranslationSession(@NonNull android.view.translation.TranslationContext, int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method public void onDisconnected();
method public abstract void onFinishTranslationSession(int);
method public abstract void onTranslationCapabilitiesRequest(int, int, @NonNull java.util.function.Consumer<java.util.Set<android.view.translation.TranslationCapability>>);
- method public void onTranslationRequest(@NonNull android.view.translation.TranslationRequest, int, @Nullable android.os.CancellationSignal, @NonNull java.util.function.Consumer<android.view.translation.TranslationResponse>);
+ method public abstract void onTranslationRequest(@NonNull android.view.translation.TranslationRequest, int, @Nullable android.os.CancellationSignal, @NonNull java.util.function.Consumer<android.view.translation.TranslationResponse>);
method public final void updateTranslationCapability(@NonNull android.view.translation.TranslationCapability);
field public static final String SERVICE_INTERFACE = "android.service.translation.TranslationService";
field public static final String SERVICE_META_DATA = "android.translation_service";
@@ -10528,7 +10529,7 @@
method @Nullable public android.media.MediaSyncEvent getMediaSyncEvent();
method public int getPersonalizedScore();
method public int getScore();
- method public boolean isPersonalizedHotwordDetection();
+ method public boolean isHotwordDetectionPersonalized();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field public static final int AUDIO_CHANNEL_UNSET = -1; // 0xffffffff
field public static final int CONFIDENCE_LEVEL_HIGH = 5; // 0x5
@@ -10548,11 +10549,11 @@
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setAudioChannel(int);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setConfidenceLevel(int);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setExtras(@NonNull android.os.PersistableBundle);
+ method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordDetectionPersonalized(boolean);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordDurationMillis(int);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordOffsetMillis(int);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordPhraseId(int);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setMediaSyncEvent(@NonNull android.media.MediaSyncEvent);
- method @NonNull public android.service.voice.HotwordDetectedResult.Builder setPersonalizedHotwordDetection(boolean);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setPersonalizedScore(int);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setScore(int);
}
diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt
index 304f4fe..7cf0076 100644
--- a/core/api/system-removed.txt
+++ b/core/api/system-removed.txt
@@ -58,6 +58,14 @@
method @Deprecated public void destroy();
}
+ public final class SearchTarget implements android.os.Parcelable {
+ method @Deprecated public boolean shouldHide();
+ }
+
+ public static final class SearchTarget.Builder {
+ method @Deprecated @NonNull public android.app.search.SearchTarget.Builder setShouldHide(boolean);
+ }
+
}
package android.bluetooth {
diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java
index be62deb7..edd6047 100644
--- a/core/java/android/app/WallpaperColors.java
+++ b/core/java/android/app/WallpaperColors.java
@@ -101,7 +101,7 @@
// We also check if the image has dark pixels in it,
// to avoid bright images with some dark spots.
private static final float DARK_PIXEL_CONTRAST = 5.5f;
- private static final float MAX_DARK_AREA = 0.025f;
+ private static final float MAX_DARK_AREA = 0.05f;
private final List<Color> mMainColors;
private final Map<Integer, Integer> mAllColors;
diff --git a/core/java/android/app/search/Query.java b/core/java/android/app/search/Query.java
index 34ace48..c64e107 100644
--- a/core/java/android/app/search/Query.java
+++ b/core/java/android/app/search/Query.java
@@ -37,6 +37,14 @@
public final class Query implements Parcelable {
/**
+ * The lookup key for a integer that indicates what the height of the soft keyboard
+ * (e.g., IME, also known as Input Method Editor) was on the client window
+ * in dp (density-independent pixels). This information is to be used by the consumer
+ * of the API in estimating how many search results will be visible above the keyboard.
+ */
+ public static final String EXTRA_IME_HEIGHT = "android.app.search.extra.IME_HEIGHT";
+
+ /**
* string typed from the client.
*/
@NonNull
@@ -45,7 +53,7 @@
private final long mTimestampMillis;
/**
- * Contains other client UI constraints related data
+ * Contains other client UI constraints related data (e.g., {@link #EXTRA_IME_HEIGHT}.
*/
@NonNull
private final Bundle mExtras;
diff --git a/core/java/android/app/search/SearchTarget.java b/core/java/android/app/search/SearchTarget.java
index 6d638d4..a590a5d 100644
--- a/core/java/android/app/search/SearchTarget.java
+++ b/core/java/android/app/search/SearchTarget.java
@@ -50,7 +50,7 @@
* can recommend which layout this target should be rendered in.
*
* The service can also use fields such as {@link #getScore()} to indicate
- * how confidence the search result is and {@link #shouldHide()} to indicate
+ * how confidence the search result is and {@link #isHidden()} to indicate
* whether it is recommended to be shown by default.
*
* Finally, {@link #getId()} is the unique identifier of this search target and a single
@@ -125,7 +125,7 @@
private final float mScore;
- private final boolean mShouldHide;
+ private final boolean mHidden;
@NonNull
private final String mPackageName;
@@ -149,7 +149,7 @@
mId = parcel.readString();
mParentId = parcel.readString();
mScore = parcel.readFloat();
- mShouldHide = parcel.readBoolean();
+ mHidden = parcel.readBoolean();
mPackageName = parcel.readString();
mUserHandle = UserHandle.of(parcel.readInt());
@@ -165,7 +165,7 @@
@NonNull String layoutType,
@NonNull String id,
@Nullable String parentId,
- float score, boolean shouldHide,
+ float score, boolean hidden,
@NonNull String packageName,
@NonNull UserHandle userHandle,
@Nullable SearchAction action,
@@ -178,7 +178,7 @@
mId = Objects.requireNonNull(id);
mParentId = parentId;
mScore = score;
- mShouldHide = shouldHide;
+ mHidden = hidden;
mPackageName = Objects.requireNonNull(packageName);
mUserHandle = Objects.requireNonNull(userHandle);
mSearchAction = action;
@@ -238,9 +238,20 @@
/**
* Indicates whether this object should be hidden and shown only on demand.
+ *
+ * @deprecated will be removed once SDK drops
+ * @removed
*/
+ @Deprecated
public boolean shouldHide() {
- return mShouldHide;
+ return mHidden;
+ }
+
+ /**
+ * Indicates whether this object should be hidden and shown only on demand.
+ */
+ public boolean isHidden() {
+ return mHidden;
}
/**
@@ -311,7 +322,7 @@
parcel.writeString(mId);
parcel.writeString(mParentId);
parcel.writeFloat(mScore);
- parcel.writeBoolean(mShouldHide);
+ parcel.writeBoolean(mHidden);
parcel.writeString(mPackageName);
parcel.writeInt(mUserHandle.getIdentifier());
parcel.writeTypedObject(mSearchAction, flags);
@@ -351,7 +362,7 @@
@Nullable
private String mParentId;
private float mScore;
- private boolean mShouldHide;
+ private boolean mHidden;
@NonNull
private String mPackageName;
@NonNull
@@ -374,7 +385,7 @@
mLayoutType = Objects.requireNonNull(layoutType);
mResultType = resultType;
mScore = 1f;
- mShouldHide = false;
+ mHidden = false;
}
/**
@@ -473,8 +484,20 @@
* Sets whether the result should be hidden (e.g. not visible) by default inside client.
*/
@NonNull
+ public Builder setHidden(boolean hidden) {
+ mHidden = hidden;
+ return this;
+ }
+
+ /**
+ * Sets whether the result should be hidden by default inside client.
+ * @deprecated will be removed once SDK drops
+ * @removed
+ */
+ @NonNull
+ @Deprecated
public Builder setShouldHide(boolean shouldHide) {
- mShouldHide = shouldHide;
+ mHidden = shouldHide;
return this;
}
@@ -485,7 +508,7 @@
*/
@NonNull
public SearchTarget build() {
- return new SearchTarget(mResultType, mLayoutType, mId, mParentId, mScore, mShouldHide,
+ return new SearchTarget(mResultType, mLayoutType, mId, mParentId, mScore, mHidden,
mPackageName, mUserHandle,
mSearchAction, mShortcutInfo, mSliceUri, mAppWidgetProviderInfo,
mExtras);
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index e6ffded..b99ad51 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -442,13 +442,18 @@
/**
* Associates given device with given app for the given user directly, without UI prompt.
*
+ * @param packageName package name of the companion app
+ * @param macAddress mac address of the device to associate
+ * @param certificate The SHA256 digest of the companion app's signing certificate
+ *
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES)
public void associate(
@NonNull String packageName,
- @NonNull MacAddress macAddress) {
+ @NonNull MacAddress macAddress,
+ @NonNull byte[] certificate) {
if (!checkFeaturePresent()) {
return;
}
@@ -458,7 +463,7 @@
UserHandle user = android.os.Process.myUserHandle();
try {
mService.createAssociation(
- packageName, macAddress.toString(), user.getIdentifier());
+ packageName, macAddress.toString(), user.getIdentifier(), certificate);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index cc3749c..d113b92 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -52,5 +52,6 @@
boolean canPairWithoutPrompt(in String packageName, in String deviceMacAddress, int userId);
- void createAssociation(in String packageName, in String macAddress, int userId);
+ void createAssociation(in String packageName, in String macAddress, int userId,
+ in byte[] certificate);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a436fa4..688483a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1983,7 +1983,7 @@
* activities that are not properly protected.
*
* <p>
- * Input: {@link android.Manifest.permission_group} specifies the permission group
+ * Input: {@link #EXTRA_PERMISSION_GROUP_NAME} specifies the permission group
* for which the launched UI would be targeted.
* </p>
* <p>
@@ -2013,12 +2013,12 @@
* Input: {@link #EXTRA_ATTRIBUTION_TAGS} specifies the attribution tags for the usage entry.
* </p>
* <p>
- * Input: {@link #EXTRA_START_TIME} specifies the start time of the period. Both start time and
- * end time are needed and start time must be <= end time.
+ * Input: {@link #EXTRA_START_TIME} specifies the start time of the period (epoch time in
+ * millis). Both start time and end time are needed and start time must be <= end time.
* </p>
* <p>
- * Input: {@link #EXTRA_END_TIME} specifies the end time of the period. Both start time and end
- * time are needed and start time must be <= end time.
+ * Input: {@link #EXTRA_END_TIME} specifies the end time of the period (epoch time in
+ * millis). Both start time and end time are needed and start time must be <= end time.
* </p>
* <p>
* Output: Nothing.
diff --git a/core/java/android/hardware/biometrics/BiometricTestSession.java b/core/java/android/hardware/biometrics/BiometricTestSession.java
index 41672b7..c62680f 100644
--- a/core/java/android/hardware/biometrics/BiometricTestSession.java
+++ b/core/java/android/hardware/biometrics/BiometricTestSession.java
@@ -23,7 +23,6 @@
import android.annotation.RequiresPermission;
import android.annotation.TestApi;
import android.content.Context;
-import android.hardware.fingerprint.FingerprintManager;
import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Log;
@@ -248,6 +247,12 @@
}
}
+ if (!mUsersCleaningUp.isEmpty()) {
+ // TODO(b/186600837): this seems common on multi sensor devices
+ Log.e(getTag(), "Cleanup not finished before shutdown - pending: "
+ + mUsersCleaningUp.size());
+ }
+
// Disable the test HAL after the sensor becomes idle.
setTestHalEnabled(false);
}
diff --git a/core/java/android/service/translation/TranslationService.java b/core/java/android/service/translation/TranslationService.java
index 2f704f4..e1d4a56 100644
--- a/core/java/android/service/translation/TranslationService.java
+++ b/core/java/android/service/translation/TranslationService.java
@@ -230,12 +230,8 @@
*/
// TODO(b/176464808): the session id won't be unique cross client/server process. Need to find
// solution to make it's safe.
- // TODO: make abstract once aiai is implemented.
- public void onCreateTranslationSession(@NonNull TranslationContext translationContext,
- int sessionId, @NonNull Consumer<Boolean> callback) {
- onCreateTranslationSession(translationContext, sessionId);
- callback.accept(true);
- }
+ public abstract void onCreateTranslationSession(@NonNull TranslationContext translationContext,
+ int sessionId, @NonNull Consumer<Boolean> callback);
/**
* TODO: fill in javadoc.
@@ -285,23 +281,9 @@
* @param callback
* @param cancellationSignal
*/
- //TODO: make abstract once aiai transitions.
- public void onTranslationRequest(@NonNull TranslationRequest request, int sessionId,
+ public abstract void onTranslationRequest(@NonNull TranslationRequest request, int sessionId,
@Nullable CancellationSignal cancellationSignal,
- @NonNull Consumer<TranslationResponse> callback) {
- onTranslationRequest(request, sessionId, cancellationSignal,
- new OnTranslationResultCallback() {
- @Override
- public void onTranslationSuccess(@NonNull TranslationResponse response) {
- callback.accept(response);
- }
-
- @Override
- public void onError() {
- // null-op
- }
- });
- }
+ @NonNull Consumer<TranslationResponse> callback);
/**
* TODO: fill in javadoc
diff --git a/core/java/android/service/voice/HotwordDetectedResult.java b/core/java/android/service/voice/HotwordDetectedResult.java
index 95e43f3..846f2f9 100644
--- a/core/java/android/service/voice/HotwordDetectedResult.java
+++ b/core/java/android/service/voice/HotwordDetectedResult.java
@@ -118,7 +118,7 @@
* Returns whether the trigger has happened due to model having been personalized to fit user's
* voice.
*/
- private boolean mPersonalizedHotwordDetection = false;
+ private boolean mHotwordDetectionPersonalized = false;
/**
* Score for the hotword trigger.
@@ -270,7 +270,7 @@
int hotwordOffsetMillis,
int hotwordDurationMillis,
int audioChannel,
- boolean personalizedHotwordDetection,
+ boolean hotwordDetectionPersonalized,
int score,
int personalizedScore,
int hotwordPhraseId,
@@ -282,7 +282,7 @@
this.mHotwordOffsetMillis = hotwordOffsetMillis;
this.mHotwordDurationMillis = hotwordDurationMillis;
this.mAudioChannel = audioChannel;
- this.mPersonalizedHotwordDetection = personalizedHotwordDetection;
+ this.mHotwordDetectionPersonalized = hotwordDetectionPersonalized;
this.mScore = score;
this.mPersonalizedScore = personalizedScore;
this.mHotwordPhraseId = hotwordPhraseId;
@@ -334,8 +334,8 @@
* voice.
*/
@DataClass.Generated.Member
- public boolean isPersonalizedHotwordDetection() {
- return mPersonalizedHotwordDetection;
+ public boolean isHotwordDetectionPersonalized() {
+ return mHotwordDetectionPersonalized;
}
/**
@@ -400,7 +400,7 @@
"hotwordOffsetMillis = " + mHotwordOffsetMillis + ", " +
"hotwordDurationMillis = " + mHotwordDurationMillis + ", " +
"audioChannel = " + mAudioChannel + ", " +
- "personalizedHotwordDetection = " + mPersonalizedHotwordDetection + ", " +
+ "hotwordDetectionPersonalized = " + mHotwordDetectionPersonalized + ", " +
"score = " + mScore + ", " +
"personalizedScore = " + mPersonalizedScore + ", " +
"hotwordPhraseId = " + mHotwordPhraseId + ", " +
@@ -426,7 +426,7 @@
&& mHotwordOffsetMillis == that.mHotwordOffsetMillis
&& mHotwordDurationMillis == that.mHotwordDurationMillis
&& mAudioChannel == that.mAudioChannel
- && mPersonalizedHotwordDetection == that.mPersonalizedHotwordDetection
+ && mHotwordDetectionPersonalized == that.mHotwordDetectionPersonalized
&& mScore == that.mScore
&& mPersonalizedScore == that.mPersonalizedScore
&& mHotwordPhraseId == that.mHotwordPhraseId
@@ -445,7 +445,7 @@
_hash = 31 * _hash + mHotwordOffsetMillis;
_hash = 31 * _hash + mHotwordDurationMillis;
_hash = 31 * _hash + mAudioChannel;
- _hash = 31 * _hash + Boolean.hashCode(mPersonalizedHotwordDetection);
+ _hash = 31 * _hash + Boolean.hashCode(mHotwordDetectionPersonalized);
_hash = 31 * _hash + mScore;
_hash = 31 * _hash + mPersonalizedScore;
_hash = 31 * _hash + mHotwordPhraseId;
@@ -460,7 +460,7 @@
// void parcelFieldName(Parcel dest, int flags) { ... }
int flg = 0;
- if (mPersonalizedHotwordDetection) flg |= 0x20;
+ if (mHotwordDetectionPersonalized) flg |= 0x20;
if (mMediaSyncEvent != null) flg |= 0x2;
dest.writeInt(flg);
dest.writeInt(mConfidenceLevel);
@@ -486,7 +486,7 @@
// static FieldType unparcelFieldName(Parcel in) { ... }
int flg = in.readInt();
- boolean personalizedHotwordDetection = (flg & 0x20) != 0;
+ boolean hotwordDetectionPersonalized = (flg & 0x20) != 0;
int confidenceLevel = in.readInt();
MediaSyncEvent mediaSyncEvent = (flg & 0x2) == 0 ? null : (MediaSyncEvent) in.readTypedObject(MediaSyncEvent.CREATOR);
int hotwordOffsetMillis = in.readInt();
@@ -504,7 +504,7 @@
this.mHotwordOffsetMillis = hotwordOffsetMillis;
this.mHotwordDurationMillis = hotwordDurationMillis;
this.mAudioChannel = audioChannel;
- this.mPersonalizedHotwordDetection = personalizedHotwordDetection;
+ this.mHotwordDetectionPersonalized = hotwordDetectionPersonalized;
this.mScore = score;
this.mPersonalizedScore = personalizedScore;
this.mHotwordPhraseId = hotwordPhraseId;
@@ -541,7 +541,7 @@
private int mHotwordOffsetMillis;
private int mHotwordDurationMillis;
private int mAudioChannel;
- private boolean mPersonalizedHotwordDetection;
+ private boolean mHotwordDetectionPersonalized;
private int mScore;
private int mPersonalizedScore;
private int mHotwordPhraseId;
@@ -618,10 +618,10 @@
* voice.
*/
@DataClass.Generated.Member
- public @NonNull Builder setPersonalizedHotwordDetection(boolean value) {
+ public @NonNull Builder setHotwordDetectionPersonalized(boolean value) {
checkNotUsed();
mBuilderFieldsSet |= 0x20;
- mPersonalizedHotwordDetection = value;
+ mHotwordDetectionPersonalized = value;
return this;
}
@@ -708,7 +708,7 @@
mAudioChannel = AUDIO_CHANNEL_UNSET;
}
if ((mBuilderFieldsSet & 0x20) == 0) {
- mPersonalizedHotwordDetection = false;
+ mHotwordDetectionPersonalized = false;
}
if ((mBuilderFieldsSet & 0x40) == 0) {
mScore = defaultScore();
@@ -728,7 +728,7 @@
mHotwordOffsetMillis,
mHotwordDurationMillis,
mAudioChannel,
- mPersonalizedHotwordDetection,
+ mHotwordDetectionPersonalized,
mScore,
mPersonalizedScore,
mHotwordPhraseId,
@@ -745,10 +745,10 @@
}
@DataClass.Generated(
- time = 1621631039729L,
+ time = 1621943150502L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java",
- inputSignatures = "public static final int CONFIDENCE_LEVEL_NONE\npublic static final int CONFIDENCE_LEVEL_LOW\npublic static final int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final int CONFIDENCE_LEVEL_HIGH\npublic static final int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final int HOTWORD_OFFSET_UNSET\npublic static final int AUDIO_CHANNEL_UNSET\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate int mHotwordOffsetMillis\nprivate int mHotwordDurationMillis\nprivate int mAudioChannel\nprivate boolean mPersonalizedHotwordDetection\nprivate final int mScore\nprivate final int mPersonalizedScore\nprivate final int mHotwordPhraseId\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static int defaultConfidenceLevel()\nprivate static int defaultScore()\nprivate static int defaultPersonalizedScore()\npublic static int getMaxScore()\nprivate static int defaultHotwordPhraseId()\npublic static int getMaxHotwordPhraseId()\nprivate static android.os.PersistableBundle defaultExtras()\npublic static int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
+ inputSignatures = "public static final int CONFIDENCE_LEVEL_NONE\npublic static final int CONFIDENCE_LEVEL_LOW\npublic static final int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final int CONFIDENCE_LEVEL_HIGH\npublic static final int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final int HOTWORD_OFFSET_UNSET\npublic static final int AUDIO_CHANNEL_UNSET\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate int mHotwordOffsetMillis\nprivate int mHotwordDurationMillis\nprivate int mAudioChannel\nprivate boolean mHotwordDetectionPersonalized\nprivate final int mScore\nprivate final int mPersonalizedScore\nprivate final int mHotwordPhraseId\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static int defaultConfidenceLevel()\nprivate static int defaultScore()\nprivate static int defaultPersonalizedScore()\npublic static int getMaxScore()\nprivate static int defaultHotwordPhraseId()\npublic static int getMaxHotwordPhraseId()\nprivate static android.os.PersistableBundle defaultExtras()\npublic static int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/view/TunnelModeEnabledListener.java b/core/java/android/view/TunnelModeEnabledListener.java
new file mode 100644
index 0000000..c158da9
--- /dev/null
+++ b/core/java/android/view/TunnelModeEnabledListener.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Listens for tunnel mode enabled/disabled events from SurfaceFlinger.
+ * {@hide}
+ */
+public abstract class TunnelModeEnabledListener {
+
+ private long mNativeListener;
+ private final Executor mExecutor;
+
+ public TunnelModeEnabledListener(Executor executor) {
+ mExecutor = executor;
+ mNativeListener = nativeCreate(this);
+ }
+
+ /**
+ * Destroys the listener.
+ */
+ public void destroy() {
+ if (mNativeListener == 0) {
+ return;
+ }
+ unregister(this);
+ nativeDestroy(mNativeListener);
+ mNativeListener = 0;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ destroy();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * Reports when tunnel mode has been enabled/disabled.
+ */
+ public abstract void onTunnelModeEnabledChanged(boolean tunnelModeEnabled);
+
+ /**
+ * Registers a listener.
+ */
+ public static void register(TunnelModeEnabledListener listener) {
+ if (listener.mNativeListener == 0) {
+ return;
+ }
+ nativeRegister(listener.mNativeListener);
+ }
+
+ /**
+ * Unregisters a listener.
+ */
+ public static void unregister(TunnelModeEnabledListener listener) {
+ if (listener.mNativeListener == 0) {
+ return;
+ }
+ nativeUnregister(listener.mNativeListener);
+ }
+
+ /**
+ * Dispatch tunnel mode enabled.
+ *
+ * Called from native code on a binder thread.
+ */
+ @VisibleForTesting
+ public static void dispatchOnTunnelModeEnabledChanged(TunnelModeEnabledListener listener,
+ boolean tunnelModeEnabled) {
+ listener.mExecutor.execute(() -> listener.onTunnelModeEnabledChanged(tunnelModeEnabled));
+ }
+
+ private static native long nativeCreate(TunnelModeEnabledListener thiz);
+ private static native void nativeDestroy(long ptr);
+ private static native void nativeRegister(long ptr);
+ private static native void nativeUnregister(long ptr);
+}
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index 5bb8a8e..40cce7c 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AppGlobals;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -61,8 +62,9 @@
@Deprecated
public class AnalogClock extends View {
private static final String LOG_TAG = "AnalogClock";
+
/** How many times per second that the seconds hand advances. */
- private static final long SECONDS_HAND_FPS = 30;
+ private final int mSecondsHandFps;
private Clock mClock;
@Nullable
@@ -106,6 +108,10 @@
public AnalogClock(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ mSecondsHandFps = AppGlobals.getIntCoreSetting(
+ WidgetFlags.KEY_ANALOG_CLOCK_SECONDS_HAND_FPS,
+ WidgetFlags.ANALOG_CLOCK_SECONDS_HAND_FPS_DEFAULT);
+
final TypedArray a = context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.AnalogClock, defStyleAttr, defStyleRes);
saveAttributeDataForStyleable(context, com.android.internal.R.styleable.AnalogClock,
@@ -743,7 +749,7 @@
// n positions between two given numbers, where n is the number of ticks per second. This
// ensures the second hand advances by a consistent distance despite our handler callbacks
// occurring at inconsistent frequencies.
- mSeconds = Math.round(rawSeconds * SECONDS_HAND_FPS) / (float) SECONDS_HAND_FPS;
+ mSeconds = Math.round(rawSeconds * mSecondsHandFps) / (float) mSecondsHandFps;
mMinutes = localTime.getMinute() + mSeconds / 60.0f;
mHour = localTime.getHour() + mMinutes / 60.0f;
mChanged = true;
@@ -781,7 +787,7 @@
// How many milliseconds through the second we currently are.
long millisOfSecond = Duration.ofNanos(localTime.getNano()).toMillis();
// How many milliseconds there are between tick positions for the seconds hand.
- double millisPerTick = 1000 / (double) SECONDS_HAND_FPS;
+ double millisPerTick = 1000 / (double) mSecondsHandFps;
// How many milliseconds we are past the last tick position.
long millisPastLastTick = Math.round(millisOfSecond % millisPerTick);
// How many milliseconds there are until the next tick position.
diff --git a/core/java/android/widget/WidgetFlags.java b/core/java/android/widget/WidgetFlags.java
index 1a49365..0971268 100644
--- a/core/java/android/widget/WidgetFlags.java
+++ b/core/java/android/widget/WidgetFlags.java
@@ -199,6 +199,17 @@
*/
public static final float MAGNIFIER_ASPECT_RATIO_DEFAULT = 5.5f;
+ /** The flag of the fps of the analog clock seconds hand. */
+ public static final String ANALOG_CLOCK_SECONDS_HAND_FPS =
+ "AnalogClockFeature__analog_clock_seconds_hand_fps";
+
+ /** The key name used in app core settings for {@link #ANALOG_CLOCK_SECONDS_HAND_FPS}. */
+ public static final String KEY_ANALOG_CLOCK_SECONDS_HAND_FPS =
+ "widget__analog_clock_seconds_hand_fps";
+
+ /** Default value for the flag {@link #ANALOG_CLOCK_SECONDS_HAND_FPS}. */
+ public static final int ANALOG_CLOCK_SECONDS_HAND_FPS_DEFAULT = 1;
+
private WidgetFlags() {
}
}
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index d4d6125..3aaccdd 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -180,29 +180,28 @@
}
private long getProcessForegroundTimeMs(BatteryStats.Uid uid, long realtimeUs) {
- final long topStateDurationMs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP,
- realtimeUs, BatteryStats.STATS_SINCE_CHARGED) / 1000;
-
- long foregroundActivityDurationMs = 0;
+ final long topStateDurationUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP,
+ realtimeUs, BatteryStats.STATS_SINCE_CHARGED);
+ long foregroundActivityDurationUs = 0;
final BatteryStats.Timer foregroundActivityTimer = uid.getForegroundActivityTimer();
if (foregroundActivityTimer != null) {
- foregroundActivityDurationMs = foregroundActivityTimer.getTotalTimeLocked(realtimeUs,
- BatteryStats.STATS_SINCE_CHARGED) / 1000;
+ foregroundActivityDurationUs = foregroundActivityTimer.getTotalTimeLocked(realtimeUs,
+ BatteryStats.STATS_SINCE_CHARGED);
}
// Use the min value of STATE_TOP time and foreground activity time, since both of these
// times are imprecise
- final long foregroundDurationMs = Math.min(topStateDurationMs,
- foregroundActivityDurationMs);
+ long totalForegroundDurationUs = Math.min(topStateDurationUs, foregroundActivityDurationUs);
- long foregroundServiceDurationMs = 0;
- final BatteryStats.Timer foregroundServiceTimer = uid.getForegroundServiceTimer();
- if (foregroundServiceTimer != null) {
- foregroundServiceDurationMs = foregroundServiceTimer.getTotalTimeLocked(realtimeUs,
- BatteryStats.STATS_SINCE_CHARGED) / 1000;
- }
+ totalForegroundDurationUs += uid.getProcessStateTime(
+ BatteryStats.Uid.PROCESS_STATE_FOREGROUND, realtimeUs,
+ BatteryStats.STATS_SINCE_CHARGED);
- return foregroundDurationMs + foregroundServiceDurationMs;
+ totalForegroundDurationUs += uid.getProcessStateTime(
+ BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE, realtimeUs,
+ BatteryStats.STATS_SINCE_CHARGED);
+
+ return totalForegroundDurationUs / 1000;
}
private long getProcessBackgroundTimeMs(BatteryStats.Uid uid, long realtimeUs) {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 1f805c9..1468633 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -128,6 +128,7 @@
"android_graphics_BLASTBufferQueue.cpp",
"android_view_SurfaceSession.cpp",
"android_view_TextureView.cpp",
+ "android_view_TunnelModeEnabledListener.cpp",
"android_view_VelocityTracker.cpp",
"android_view_VerifiedKeyEvent.cpp",
"android_view_VerifiedMotionEvent.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index f76cccb..7e8fc7e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -127,6 +127,7 @@
extern int register_android_view_SurfaceSession(JNIEnv* env);
extern int register_android_view_CompositionSamplingListener(JNIEnv* env);
extern int register_android_view_TextureView(JNIEnv* env);
+extern int register_android_view_TunnelModeEnabledListener(JNIEnv* env);
extern int register_android_database_CursorWindow(JNIEnv* env);
extern int register_android_database_SQLiteConnection(JNIEnv* env);
extern int register_android_database_SQLiteGlobal(JNIEnv* env);
@@ -1521,6 +1522,7 @@
REG_JNI(register_android_view_SurfaceSession),
REG_JNI(register_android_view_CompositionSamplingListener),
REG_JNI(register_android_view_TextureView),
+ REG_JNI(register_android_view_TunnelModeEnabledListener),
REG_JNI(register_com_google_android_gles_jni_EGLImpl),
REG_JNI(register_com_google_android_gles_jni_GLImpl),
REG_JNI(register_android_opengl_jni_EGL14),
diff --git a/core/jni/android_view_TunnelModeEnabledListener.cpp b/core/jni/android_view_TunnelModeEnabledListener.cpp
new file mode 100644
index 0000000..af7bae8
--- /dev/null
+++ b/core/jni/android_view_TunnelModeEnabledListener.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "TunnelModeEnabledListener"
+
+#include "android_util_Binder.h"
+#include "core_jni_helpers.h"
+
+#include <nativehelper/JNIHelp.h>
+
+#include <android/gui/BnTunnelModeEnabledListener.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/Log.h>
+#include <utils/Log.h>
+
+#include <gui/SurfaceComposerClient.h>
+#include <ui/Rect.h>
+
+namespace android {
+
+namespace {
+
+struct {
+ jclass mClass;
+ jmethodID mDispatchOnTunnelModeEnabledChanged;
+} gListenerClassInfo;
+
+struct TunnelModeEnabledListener : public gui::BnTunnelModeEnabledListener {
+ TunnelModeEnabledListener(JNIEnv* env, jobject listener)
+ : mListener(env->NewWeakGlobalRef(listener)) {}
+
+ binder::Status onTunnelModeEnabledChanged(bool tunnelModeEnabled) override {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ LOG_ALWAYS_FATAL_IF(env == nullptr,
+ "Unable to retrieve JNIEnv in onTunnelModeEnabledChanged.");
+
+ jobject listener = env->NewGlobalRef(mListener);
+ if (listener == NULL) {
+ // Weak reference went out of scope
+ return binder::Status::ok();
+ }
+ env->CallStaticVoidMethod(gListenerClassInfo.mClass,
+ gListenerClassInfo.mDispatchOnTunnelModeEnabledChanged, listener,
+ static_cast<jboolean>(tunnelModeEnabled));
+ env->DeleteGlobalRef(listener);
+
+ if (env->ExceptionCheck()) {
+ ALOGE("TunnelModeEnabledListener.onTunnelModeEnabledChanged() failed.");
+ LOGE_EX(env);
+ env->ExceptionClear();
+ }
+ return binder::Status::ok();
+ }
+
+protected:
+ virtual ~TunnelModeEnabledListener() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->DeleteWeakGlobalRef(mListener);
+ }
+
+private:
+ jweak mListener;
+};
+
+jlong nativeCreate(JNIEnv* env, jclass clazz, jobject obj) {
+ TunnelModeEnabledListener* listener = new TunnelModeEnabledListener(env, obj);
+ listener->incStrong((void*)nativeCreate);
+ return reinterpret_cast<jlong>(listener);
+}
+
+void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
+ TunnelModeEnabledListener* listener = reinterpret_cast<TunnelModeEnabledListener*>(ptr);
+ listener->decStrong((void*)nativeCreate);
+}
+
+void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr) {
+ sp<TunnelModeEnabledListener> listener = reinterpret_cast<TunnelModeEnabledListener*>(ptr);
+ if (SurfaceComposerClient::addTunnelModeEnabledListener(listener) != OK) {
+ constexpr auto error_msg = "Couldn't addTunnelModeEnabledListener";
+ ALOGE(error_msg);
+ jniThrowRuntimeException(env, error_msg);
+ }
+}
+
+void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) {
+ sp<TunnelModeEnabledListener> listener = reinterpret_cast<TunnelModeEnabledListener*>(ptr);
+
+ if (SurfaceComposerClient::removeTunnelModeEnabledListener(listener) != OK) {
+ constexpr auto error_msg = "Couldn't removeTunnelModeEnabledListener";
+ ALOGE(error_msg);
+ jniThrowRuntimeException(env, error_msg);
+ }
+}
+
+const JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ {"nativeCreate", "(Landroid/view/TunnelModeEnabledListener;)J", (void*)nativeCreate},
+ {"nativeDestroy", "(J)V", (void*)nativeDestroy},
+ {"nativeRegister", "(J)V", (void*)nativeRegister},
+ {"nativeUnregister", "(J)V", (void*)nativeUnregister}};
+
+} // namespace
+
+int register_android_view_TunnelModeEnabledListener(JNIEnv* env) {
+ int res = jniRegisterNativeMethods(env, "android/view/TunnelModeEnabledListener", gMethods,
+ NELEM(gMethods));
+ LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+
+ jclass clazz = env->FindClass("android/view/TunnelModeEnabledListener");
+ gListenerClassInfo.mClass = MakeGlobalRefOrDie(env, clazz);
+ gListenerClassInfo.mDispatchOnTunnelModeEnabledChanged =
+ env->GetStaticMethodID(clazz, "dispatchOnTunnelModeEnabledChanged",
+ "(Landroid/view/TunnelModeEnabledListener;Z)V");
+ return 0;
+}
+
+} // namespace android
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
index c207135..0c7218e 100644
--- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
+++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
@@ -124,7 +124,8 @@
for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
final String metricTitle = getPowerMetricTitle(component);
final int powerModel = requestedBatteryConsumer.getPowerModel(component);
- if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE
+ || powerModel == BatteryConsumer.POWER_MODEL_UNDEFINED) {
addEntry(metricTitle, EntryType.UID_POWER_MODELED,
requestedBatteryConsumer.getConsumedPower(component),
totalPowerByComponentMah[component]
@@ -202,7 +203,8 @@
for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
final String metricTitle = getPowerMetricTitle(component);
final int powerModel = deviceBatteryConsumer.getPowerModel(component);
- if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE
+ || powerModel == BatteryConsumer.POWER_MODEL_UNDEFINED) {
addEntry(metricTitle, EntryType.DEVICE_POWER_MODELED,
deviceBatteryConsumer.getConsumedPower(component),
appsBatteryConsumer.getConsumedPower(component));
@@ -237,8 +239,9 @@
private boolean isPowerProfileModelsOnly(BatteryConsumer batteryConsumer) {
for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
- if (batteryConsumer.getPowerModel(component)
- != BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
+ final int powerModel = batteryConsumer.getPowerModel(component);
+ if (powerModel != BatteryConsumer.POWER_MODEL_POWER_PROFILE
+ && powerModel != BatteryConsumer.POWER_MODEL_UNDEFINED) {
return false;
}
}
diff --git a/core/tests/coretests/src/android/view/TunnelModeEnabledListenerTest.java b/core/tests/coretests/src/android/view/TunnelModeEnabledListenerTest.java
new file mode 100644
index 0000000..65dd34f
--- /dev/null
+++ b/core/tests/coretests/src/android/view/TunnelModeEnabledListenerTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+@Presubmit
+public class TunnelModeEnabledListenerTest {
+ private TestableTunnelModeEnabledListener mListener;
+
+ @Before
+ public void init() {
+ mListener = new TestableTunnelModeEnabledListener();
+ }
+
+ @Test
+ public void testRegisterUnregister() {
+ TunnelModeEnabledListener.register(mListener);
+ TunnelModeEnabledListener.unregister(mListener);
+ }
+
+ @Test
+ public void testDispatchUpdatesListener() {
+ TunnelModeEnabledListener.dispatchOnTunnelModeEnabledChanged(mListener, true);
+ assertEquals(true, mListener.mTunnelModeEnabled.get());
+ TunnelModeEnabledListener.dispatchOnTunnelModeEnabledChanged(mListener, false);
+ assertEquals(false, mListener.mTunnelModeEnabled.get());
+ }
+
+ @Test
+ public void testRegisterUpdatesListener() throws Exception {
+ TunnelModeEnabledListener.register(mListener);
+ TimeUnit.SECONDS.sleep(1);
+ assertTrue(mListener.mTunnelModeEnabledUpdated.get());
+ TunnelModeEnabledListener.unregister(mListener);
+ }
+
+ private static class TestableTunnelModeEnabledListener extends TunnelModeEnabledListener {
+ AtomicBoolean mTunnelModeEnabled;
+ AtomicBoolean mTunnelModeEnabledUpdated;
+
+ TestableTunnelModeEnabledListener() {
+ super(Runnable::run);
+ mTunnelModeEnabled = new AtomicBoolean(false);
+ mTunnelModeEnabledUpdated = new AtomicBoolean();
+ }
+
+ @Override
+ public void onTunnelModeEnabledChanged(boolean tunnelModeEnabled) {
+ mTunnelModeEnabled.set(tunnelModeEnabled);
+ mTunnelModeEnabledUpdated.set(true);
+ }
+ }
+
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
index 7f0449b..d83645d 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
@@ -59,8 +59,14 @@
30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS);
batteryStats.noteUidProcessStateLocked(APP_UID, ActivityManager.PROCESS_STATE_SERVICE,
30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS);
- batteryStats.noteUidProcessStateLocked(APP_UID, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
+ batteryStats.noteUidProcessStateLocked(APP_UID,
+ ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE,
40 * MINUTE_IN_MS, 40 * MINUTE_IN_MS);
+ batteryStats.noteUidProcessStateLocked(APP_UID,
+ ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE,
+ 50 * MINUTE_IN_MS, 50 * MINUTE_IN_MS);
+ batteryStats.noteUidProcessStateLocked(APP_UID, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
+ 80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS);
mStatsRule.setCurrentTime(54321);
@@ -74,7 +80,7 @@
batteryUsageStats.getUidBatteryConsumers();
final UidBatteryConsumer uidBatteryConsumer = uidBatteryConsumers.get(0);
assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND))
- .isEqualTo(20 * MINUTE_IN_MS);
+ .isEqualTo(60 * MINUTE_IN_MS);
assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND))
.isEqualTo(10 * MINUTE_IN_MS);
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 19332c7..8d4739d 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -473,6 +473,7 @@
<permission name="android.permission.UPDATE_FONTS" />
<!-- Permission required for hotword detection service CTS tests -->
<permission name="android.permission.MANAGE_HOTWORD_DETECTION" />
+ <permission name="android.permission.BIND_HOTWORD_DETECTION_SERVICE" />
<permission name="android.permission.MANAGE_APP_HIBERNATION"/>
<!-- Permission required for CTS test - ResourceObserverNativeTest -->
<permission name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index 187e104..c37e88a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -277,8 +277,9 @@
// waiting for setContentView before relayoutWindow
SplashScreenView contentView = viewSupplier.get();
final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
- // if record == null, either the starting window added fail or removed already.
- if (record != null) {
+ // If record == null, either the starting window added fail or removed already.
+ // Do not add this view if the token is mismatch.
+ if (record != null && appToken == record.mAppToken) {
// if view == null then creation of content view was failed.
if (contentView != null) {
try {
@@ -297,15 +298,16 @@
try {
final WindowManager wm = context.getSystemService(WindowManager.class);
- postAddWindow(taskId, appToken, rootLayout, wm, params);
-
- // We use the splash screen worker thread to create SplashScreenView while adding the
- // window, as otherwise Choreographer#doFrame might be delayed on this thread.
- // And since Choreographer#doFrame won't happen immediately after adding the window, if
- // the view is not added to the PhoneWindow on the first #doFrame, the view will not be
- // rendered on the first frame. So here we need to synchronize the view on the window
- // before first round relayoutWindow, which will happen after insets animation.
- mChoreographer.postCallback(CALLBACK_INSETS_ANIMATION, setViewSynchronized, null);
+ if (postAddWindow(taskId, appToken, rootLayout, wm, params)) {
+ // We use the splash screen worker thread to create SplashScreenView while adding
+ // the window, as otherwise Choreographer#doFrame might be delayed on this thread.
+ // And since Choreographer#doFrame won't happen immediately after adding the window,
+ // if the view is not added to the PhoneWindow on the first #doFrame, the view will
+ // not be rendered on the first frame. So here we need to synchronize the view on
+ // the window before first round relayoutWindow, which will happen after insets
+ // animation.
+ mChoreographer.postCallback(CALLBACK_INSETS_ANIMATION, setViewSynchronized, null);
+ }
} catch (RuntimeException e) {
// don't crash if something else bad happens, for example a
// failure loading resources because we are loading from an app
@@ -347,7 +349,8 @@
final int taskId = startingWindowInfo.taskInfo.taskId;
final TaskSnapshotWindow surface = TaskSnapshotWindow.create(startingWindowInfo, appToken,
snapshot, mSplashScreenExecutor, () -> removeWindowNoAnimate(taskId));
- final StartingWindowRecord tView = new StartingWindowRecord(null/* decorView */, surface);
+ final StartingWindowRecord tView = new StartingWindowRecord(appToken,
+ null/* decorView */, surface);
mStartingWindowRecords.put(taskId, tView);
}
@@ -382,7 +385,7 @@
ActivityTaskManager.getInstance().onSplashScreenViewCopyFinished(taskId, parcelable);
}
- protected void postAddWindow(int taskId, IBinder appToken, View view, WindowManager wm,
+ protected boolean postAddWindow(int taskId, IBinder appToken, View view, WindowManager wm,
WindowManager.LayoutParams params) {
boolean shouldSaveView = true;
try {
@@ -401,12 +404,13 @@
}
if (shouldSaveView) {
removeWindowNoAnimate(taskId);
- saveSplashScreenRecord(taskId, view);
+ saveSplashScreenRecord(appToken, taskId, view);
}
+ return shouldSaveView;
}
- private void saveSplashScreenRecord(int taskId, View view) {
- final StartingWindowRecord tView = new StartingWindowRecord(view,
+ private void saveSplashScreenRecord(IBinder appToken, int taskId, View view) {
+ final StartingWindowRecord tView = new StartingWindowRecord(appToken, view,
null/* TaskSnapshotWindow */);
mStartingWindowRecords.put(taskId, tView);
}
@@ -468,12 +472,15 @@
* Record the view or surface for a starting window.
*/
private static class StartingWindowRecord {
+ private final IBinder mAppToken;
private final View mDecorView;
private final TaskSnapshotWindow mTaskSnapshotWindow;
private SplashScreenView mContentView;
private boolean mSetSplashScreen;
- StartingWindowRecord(View decorView, TaskSnapshotWindow taskSnapshotWindow) {
+ StartingWindowRecord(IBinder appToken, View decorView,
+ TaskSnapshotWindow taskSnapshotWindow) {
+ mAppToken = appToken;
mDecorView = decorView;
mTaskSnapshotWindow = taskSnapshotWindow;
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index 2623535..4e3e133 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -83,11 +83,12 @@
}
@Override
- protected void postAddWindow(int taskId, IBinder appToken,
+ protected boolean postAddWindow(int taskId, IBinder appToken,
View view, WindowManager wm, WindowManager.LayoutParams params) {
// listen for addView
mAddWindowForTask = taskId;
mViewThemeResId = view.getContext().getThemeResId();
+ return true;
}
@Override
diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp
index 859a555..db3a108 100644
--- a/libs/hwui/HardwareBitmapUploader.cpp
+++ b/libs/hwui/HardwareBitmapUploader.cpp
@@ -24,10 +24,10 @@
#include <GrDirectContext.h>
#include <SkCanvas.h>
#include <SkImage.h>
+#include <gui/TraceUtils.h>
#include <utils/GLUtils.h>
#include <utils/NdkUtils.h>
#include <utils/Trace.h>
-#include <utils/TraceUtils.h>
#include <thread>
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index a9b129f..8a8b418 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -19,6 +19,7 @@
#include <sync/sync.h>
#include <system/window.h>
+#include <gui/TraceUtils.h>
#include "DeferredLayerUpdater.h"
#include "Properties.h"
#include "hwui/Bitmap.h"
@@ -28,7 +29,6 @@
#include "utils/Color.h"
#include "utils/MathUtils.h"
#include "utils/NdkUtils.h"
-#include "utils/TraceUtils.h"
using namespace android::uirenderer::renderthread;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index ded7994..9a9e6d4 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -27,9 +27,9 @@
#include "DamageAccumulator.h"
#include "pipeline/skia/SkiaDisplayList.h"
#endif
+#include <gui/TraceUtils.h>
#include "utils/MathUtils.h"
#include "utils/StringUtils.h"
-#include "utils/TraceUtils.h"
#include <SkPathOps.h>
#include <algorithm>
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index 4a21ad6..55f434f 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -30,8 +30,8 @@
#include "renderthread/RenderThread.h"
#endif
+#include <gui/TraceUtils.h>
#include "utils/Macros.h"
-#include "utils/TraceUtils.h"
#include "utils/VectorDrawableUtils.h"
namespace android {
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp
index 0d3d3e3..876f5c8 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.cpp
+++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp
@@ -19,7 +19,7 @@
#include "AnimatedImageThread.h"
#endif
-#include "utils/TraceUtils.h"
+#include <gui/TraceUtils.h>
#include "pipeline/skia/SkiaUtils.h"
#include <SkPicture.h>
diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp
index f928baa..ee7b260 100644
--- a/libs/hwui/jni/Typeface.cpp
+++ b/libs/hwui/jni/Typeface.cpp
@@ -15,19 +15,19 @@
*/
#define ATRACE_TAG ATRACE_TAG_VIEW
-#include "FontUtils.h"
-#include "GraphicsJNI.h"
-#include "fonts/Font.h"
-#include <nativehelper/ScopedPrimitiveArray.h>
-#include <nativehelper/ScopedUtfChars.h>
-#include "SkData.h"
-#include "SkTypeface.h"
+#include <gui/TraceUtils.h>
#include <hwui/Typeface.h>
#include <minikin/FontCollection.h>
#include <minikin/FontFamily.h>
#include <minikin/FontFileParser.h>
#include <minikin/SystemFonts.h>
-#include <utils/TraceUtils.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include "FontUtils.h"
+#include "GraphicsJNI.h"
+#include "SkData.h"
+#include "SkTypeface.h"
+#include "fonts/Font.h"
#include <mutex>
#include <unordered_map>
@@ -37,7 +37,6 @@
#endif
using namespace android;
-using android::uirenderer::TraceUtils;
static inline Typeface* toTypeface(jlong ptr) {
return reinterpret_cast<Typeface*>(ptr);
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 82bc5a1..4289c45 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -24,6 +24,7 @@
#include <Properties.h>
#include <RootRenderNode.h>
#include <dlfcn.h>
+#include <gui/TraceUtils.h>
#include <inttypes.h>
#include <media/NdkImage.h>
#include <media/NdkImageReader.h>
@@ -39,7 +40,6 @@
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
#include <utils/Timers.h>
-#include <utils/TraceUtils.h>
#include <pthread.h>
diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp
index 002bd83..e1da169 100644
--- a/libs/hwui/jni/android_graphics_RenderNode.cpp
+++ b/libs/hwui/jni/android_graphics_RenderNode.cpp
@@ -26,8 +26,8 @@
#endif
#include <TreeInfo.h>
#include <effects/StretchEffect.h>
+#include <gui/TraceUtils.h>
#include <hwui/Paint.h>
-#include <utils/TraceUtils.h>
namespace android {
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index c8247e7..d7546d8 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -16,11 +16,11 @@
#include "RenderNodeDrawable.h"
#include <SkPaintFilterCanvas.h>
-#include "StretchMask.h"
+#include <gui/TraceUtils.h>
#include "RenderNode.h"
#include "SkiaDisplayList.h"
+#include "StretchMask.h"
#include "TransformCanvas.h"
-#include "utils/TraceUtils.h"
#include <include/effects/SkImageFilters.h>
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index 3baff7e..c482fc1 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -16,6 +16,7 @@
#include "ShaderCache.h"
#include <GrDirectContext.h>
+#include <gui/TraceUtils.h>
#include <log/log.h>
#include <openssl/sha.h>
#include <algorithm>
@@ -23,7 +24,6 @@
#include <thread>
#include "FileBlobCache.h"
#include "Properties.h"
-#include "utils/TraceUtils.h"
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 50eea31..a78cd83 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -16,6 +16,7 @@
#include "SkiaOpenGLPipeline.h"
+#include <gui/TraceUtils.h>
#include "DeferredLayerUpdater.h"
#include "LayerDrawable.h"
#include "LightingInfo.h"
@@ -27,7 +28,6 @@
#include "renderthread/EglManager.h"
#include "renderthread/Frame.h"
#include "utils/GLUtils.h"
-#include "utils/TraceUtils.h"
#include <GLES3/gl3.h>
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 1f73ac9..039b0f9 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -31,13 +31,13 @@
#include <sstream>
+#include <gui/TraceUtils.h>
#include "LightingInfo.h"
#include "VectorDrawable.h"
#include "thread/CommonPool.h"
#include "tools/SkSharingProc.h"
#include "utils/Color.h"
#include "utils/String8.h"
-#include "utils/TraceUtils.h"
using namespace android::uirenderer::renderthread;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 30a3fc5..0e4a1f9 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -16,6 +16,7 @@
#include "SkiaVulkanPipeline.h"
+#include <gui/TraceUtils.h>
#include "DeferredLayerUpdater.h"
#include "LightingInfo.h"
#include "Readback.h"
@@ -25,7 +26,6 @@
#include "VkInteropFunctorDrawable.h"
#include "renderstate/RenderState.h"
#include "renderthread/Frame.h"
-#include "utils/TraceUtils.h"
#include <SkSurface.h>
#include <SkTypes.h>
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
index 6efe176..8abf4534 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
@@ -21,9 +21,9 @@
#include <SkAndroidFrameworkUtils.h>
#include <SkImage.h>
#include <SkM44.h>
+#include <gui/TraceUtils.h>
#include <utils/Color.h>
#include <utils/Trace.h>
-#include <utils/TraceUtils.h>
#include <vk/GrVkTypes.h>
#include <thread>
#include "renderthread/RenderThread.h"
diff --git a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
index bae11f7..ddfb66f 100644
--- a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
@@ -21,11 +21,11 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES3/gl3.h>
+#include <gui/TraceUtils.h>
#include <private/hwui/DrawGlInfo.h>
#include <utils/Color.h>
#include <utils/GLUtils.h>
#include <utils/Trace.h>
-#include <utils/TraceUtils.h>
#include <thread>
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index c1f61e08..d317305 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -26,6 +26,7 @@
#include <cstdlib>
#include <functional>
+#include <gui/TraceUtils.h>
#include "../Properties.h"
#include "AnimationContext.h"
#include "Frame.h"
@@ -39,7 +40,6 @@
#include "thread/CommonPool.h"
#include "utils/GLUtils.h"
#include "utils/TimeUtils.h"
-#include "utils/TraceUtils.h"
#define TRIM_MEMORY_COMPLETE 80
#define TRIM_MEMORY_UI_HIDDEN 20
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 8448b87..5c4b901 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -16,8 +16,8 @@
#include "DrawFrameTask.h"
+#include <gui/TraceUtils.h>
#include <utils/Log.h>
-#include <utils/TraceUtils.h>
#include <algorithm>
#include "../DeferredLayerUpdater.h"
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 95aa29d..ac19a15 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -16,6 +16,7 @@
#include "RenderProxy.h"
+#include <gui/TraceUtils.h>
#include "DeferredLayerUpdater.h"
#include "DisplayList.h"
#include "Properties.h"
@@ -27,7 +28,6 @@
#include "renderthread/RenderThread.h"
#include "utils/Macros.h"
#include "utils/TimeUtils.h"
-#include "utils/TraceUtils.h"
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index a648f98..4ba7748 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -16,6 +16,7 @@
#include "RenderThread.h"
+#include <gui/TraceUtils.h>
#include "../HardwareBitmapUploader.h"
#include "CanvasContext.h"
#include "DeviceInfo.h"
@@ -29,7 +30,6 @@
#include "pipeline/skia/SkiaVulkanPipeline.h"
#include "renderstate/RenderState.h"
#include "utils/TimeUtils.h"
-#include "utils/TraceUtils.h"
#include <GrContextOptions.h>
#include <gl/GrGLInterface.h>
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 07146e8..5a71833 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -29,11 +29,11 @@
#include <cstring>
+#include <gui/TraceUtils.h>
#include "Properties.h"
#include "RenderThread.h"
#include "pipeline/skia/ShaderCache.h"
#include "renderstate/RenderState.h"
-#include "utils/TraceUtils.h"
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index c559425..01a2ec5 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -20,9 +20,9 @@
#include <SkSurface.h>
#include <algorithm>
+#include <gui/TraceUtils.h>
#include "VulkanManager.h"
#include "utils/Color.h"
-#include "utils/TraceUtils.h"
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index b640b90..de2c621 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <gui/TraceUtils.h>
#include "AnimationContext.h"
#include "RenderNode.h"
#include "renderthread/RenderProxy.h"
@@ -21,7 +22,6 @@
#include "tests/common/TestContext.h"
#include "tests/common/TestScene.h"
#include "tests/common/scenes/TestSceneBase.h"
-#include "utils/TraceUtils.h"
#include <benchmark/benchmark.h>
#include <gui/Surface.h>
diff --git a/libs/hwui/utils/TraceUtils.h b/libs/hwui/utils/TraceUtils.h
deleted file mode 100644
index e61b4be..0000000
--- a/libs/hwui/utils/TraceUtils.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef TRACE_UTILS_H
-#define TRACE_UTILS_H
-
-#include <cutils/trace.h>
-#include <utils/Trace.h>
-
-#define ATRACE_FORMAT(fmt, ...) \
- TraceUtils::TraceEnder __traceEnder = \
- (TraceUtils::atraceFormatBegin(fmt, ##__VA_ARGS__), TraceUtils::TraceEnder())
-
-#define ATRACE_FORMAT_BEGIN(fmt, ...) TraceUtils::atraceFormatBegin(fmt, ##__VA_ARGS__)
-
-namespace android {
-namespace uirenderer {
-
-class TraceUtils {
-public:
- class TraceEnder {
- public:
- ~TraceEnder() { ATRACE_END(); }
- };
-
- static void atraceFormatBegin(const char* fmt, ...) {
- if (CC_LIKELY(!ATRACE_ENABLED())) return;
-
- const int BUFFER_SIZE = 256;
- va_list ap;
- char buf[BUFFER_SIZE];
-
- va_start(ap, fmt);
- vsnprintf(buf, BUFFER_SIZE, fmt, ap);
- va_end(ap);
-
- ATRACE_BEGIN(buf);
- }
-
-}; // class TraceUtils
-
-} /* namespace uirenderer */
-} /* namespace android */
-
-#endif /* TRACE_UTILS_H */
diff --git a/packages/SettingsLib/SettingsTransition/src/com/android/settingslib/transition/SettingsTransitionHelper.java b/packages/SettingsLib/SettingsTransition/src/com/android/settingslib/transition/SettingsTransitionHelper.java
index ed447f8..3d93964 100644
--- a/packages/SettingsLib/SettingsTransition/src/com/android/settingslib/transition/SettingsTransitionHelper.java
+++ b/packages/SettingsLib/SettingsTransition/src/com/android/settingslib/transition/SettingsTransitionHelper.java
@@ -16,6 +16,7 @@
package com.android.settingslib.transition;
+import androidx.annotation.IntDef;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
@@ -29,11 +30,31 @@
import com.google.android.material.transition.platform.MaterialSharedAxis;
import com.google.android.material.transition.platform.SlideDistanceProvider;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* A helper class to apply Settings Transition
*/
public class SettingsTransitionHelper {
+ /**
+ * Flags indicating the type of the transition.
+ */
+ @IntDef({
+ TransitionType.TRANSITION_NONE,
+ TransitionType.TRANSITION_SHARED_AXIS,
+ TransitionType.TRANSITION_SLIDE,
+ TransitionType.TRANSITION_FADE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TransitionType {
+ int TRANSITION_NONE = -1;
+ int TRANSITION_SHARED_AXIS = 0;
+ int TRANSITION_SLIDE = 1;
+ int TRANSITION_FADE = 2;
+ }
+
private static final String TAG = "SettingsTransitionHelper";
private static final long DURATION = 450L;
private static final float FADE_THROUGH_THRESHOLD = 0.22F;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 4558a8a..fe92e26 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -1222,19 +1222,22 @@
*/
public Pair<Drawable, String> getDrawableWithDescription() {
Uri uri = BluetoothUtils.getUriMetaData(mDevice, BluetoothDevice.METADATA_MAIN_ICON);
+ Pair<Drawable, String> pair = BluetoothUtils.getBtClassDrawableWithDescription(
+ mContext, this);
+
if (BluetoothUtils.isAdvancedDetailsHeader(mDevice) && uri != null) {
BitmapDrawable drawable = mDrawableCache.get(uri.toString());
if (drawable != null) {
Resources resources = mContext.getResources();
return new Pair<>(new AdaptiveOutlineDrawable(
- resources, drawable.getBitmap()),
- BluetoothUtils.getBtClassDrawableWithDescription(mContext, this).second);
+ resources, drawable.getBitmap()), pair.second);
}
refresh();
}
- return BluetoothUtils.getBtRainbowDrawableWithDescription(mContext, this);
+ return new Pair<>(BluetoothUtils.buildBtRainbowDrawable(
+ mContext, pair.first, getAddress().hashCode()), pair.second);
}
void releaseLruCache() {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 38172f7..f523354 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -31,7 +31,9 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
+import android.graphics.drawable.BitmapDrawable;
import android.media.AudioManager;
+import android.util.LruCache;
import com.android.settingslib.R;
import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
@@ -961,6 +963,10 @@
@Test
public void getDrawableWithDescription_isAdvancedDevice_returnAdvancedIcon() {
+ LruCache lruCache = mock(LruCache.class);
+ mCachedDevice.mDrawableCache = lruCache;
+ BitmapDrawable drawable = mock(BitmapDrawable.class);
+ when(lruCache.get("fake_uri")).thenReturn(drawable);
when(mDevice.getMetadata(BluetoothDevice.METADATA_MAIN_ICON))
.thenReturn("fake_uri".getBytes());
when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 6e256c1..d2947c6 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -528,6 +528,7 @@
<!-- Permission required for hotword detection service CTS tests -->
<uses-permission android:name="android.permission.MANAGE_HOTWORD_DETECTION" />
+ <uses-permission android:name="android.permission.BIND_HOTWORD_DETECTION_SERVICE" />
<uses-permission android:name="android.permission.MANAGE_APP_HIBERNATION"/>
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index 1cf0c5f..2b87737 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -4,12 +4,15 @@
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.app.ActivityManager
+import android.app.ActivityTaskManager
import android.app.PendingIntent
import android.content.Context
import android.graphics.Matrix
import android.graphics.Rect
+import android.graphics.RectF
import android.os.Looper
import android.os.RemoteException
+import android.util.Log
import android.util.MathUtils
import android.view.IRemoteAnimationFinishedCallback
import android.view.IRemoteAnimationRunner
@@ -30,6 +33,8 @@
* nicely into the starting window.
*/
class ActivityLaunchAnimator(context: Context) {
+ private val TAG = this::class.java.simpleName
+
companion object {
const val ANIMATION_DURATION = 500L
const val ANIMATION_DURATION_FADE_OUT_CONTENT = 183L
@@ -78,29 +83,49 @@
* If [controller] is null or [animate] is false, then the intent will be started and no
* animation will run.
*
+ * If possible, you should pass the [packageName] of the intent that will be started so that
+ * trampoline activity launches will also be animated.
+ *
* This method will throw any exception thrown by [intentStarter].
*/
@JvmOverloads
- inline fun startIntentWithAnimation(
+ fun startIntentWithAnimation(
controller: Controller?,
animate: Boolean = true,
+ packageName: String? = null,
intentStarter: (RemoteAnimationAdapter?) -> Int
) {
if (controller == null || !animate) {
+ Log.d(TAG, "Starting intent with no animation")
intentStarter(null)
controller?.callOnIntentStartedOnMainThread(willAnimate = false)
return
}
+ Log.d(TAG, "Starting intent with a launch animation")
val runner = Runner(controller)
val animationAdapter = RemoteAnimationAdapter(
runner,
ANIMATION_DURATION,
ANIMATION_DURATION - 150 /* statusBarTransitionDelay */
)
+
+ // Register the remote animation for the given package to also animate trampoline
+ // activity launches.
+ if (packageName != null) {
+ try {
+ ActivityTaskManager.getService().registerRemoteAnimationForNextActivityStart(
+ packageName, animationAdapter)
+ } catch (e: RemoteException) {
+ Log.w(TAG, "Unable to register the remote animation", e)
+ }
+ }
+
val launchResult = intentStarter(animationAdapter)
val willAnimate = launchResult == ActivityManager.START_TASK_TO_FRONT ||
launchResult == ActivityManager.START_SUCCESS
+
+ Log.d(TAG, "launchResult=$launchResult willAnimate=$willAnimate")
controller.callOnIntentStartedOnMainThread(willAnimate)
// If we expect an animation, post a timeout to cancel it in case the remote animation is
@@ -110,7 +135,6 @@
}
}
- @PublishedApi
internal fun Controller.callOnIntentStartedOnMainThread(willAnimate: Boolean) {
if (Looper.myLooper() != Looper.getMainLooper()) {
this.launchContainer.context.mainExecutor.execute {
@@ -125,15 +149,21 @@
* Same as [startIntentWithAnimation] but allows [intentStarter] to throw a
* [PendingIntent.CanceledException] which must then be handled by the caller. This is useful
* for Java caller starting a [PendingIntent].
+ *
+ * If possible, you should pass the [packageName] of the intent that will be started so that
+ * trampoline activity launches will also be animated.
*/
@Throws(PendingIntent.CanceledException::class)
@JvmOverloads
fun startPendingIntentWithAnimation(
controller: Controller?,
animate: Boolean = true,
+ packageName: String? = null,
intentStarter: PendingIntentStarter
) {
- startIntentWithAnimation(controller, animate) { intentStarter.startPendingIntent(it) }
+ startIntentWithAnimation(controller, animate, packageName) {
+ intentStarter.startPendingIntent(it)
+ }
}
/** Create a new animation [Runner] controlled by [controller]. */
@@ -278,11 +308,14 @@
@VisibleForTesting
inner class Runner(private val controller: Controller) : IRemoteAnimationRunner.Stub() {
private val launchContainer = controller.launchContainer
- @PublishedApi internal val context = launchContainer.context
+ private val context = launchContainer.context
private val transactionApplier = SyncRtSurfaceTransactionApplier(launchContainer)
private var animator: ValueAnimator? = null
+ private val matrix = Matrix()
+ private val invertMatrix = Matrix()
private var windowCrop = Rect()
+ private var windowCropF = RectF()
private var timedOut = false
private var cancelled = false
@@ -294,7 +327,6 @@
// posting it.
private var onTimeout = Runnable { onAnimationTimedOut() }
- @PublishedApi
internal fun postTimeout() {
launchContainer.postDelayed(onTimeout, LAUNCH_TIMEOUT)
}
@@ -336,11 +368,13 @@
remoteAnimationNonAppTargets: Array<out RemoteAnimationTarget>,
iCallback: IRemoteAnimationFinishedCallback
) {
+ Log.d(TAG, "Remote animation started")
val window = remoteAnimationTargets.firstOrNull {
it.mode == RemoteAnimationTarget.MODE_OPENING
}
if (window == null) {
+ Log.d(TAG, "Aborting the animation as no window is opening")
removeTimeout()
invokeCallback(iCallback)
controller.onLaunchAnimationCancelled()
@@ -399,10 +433,12 @@
animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator?, isReverse: Boolean) {
+ Log.d(TAG, "Animation started")
controller.onLaunchAnimationStart(isExpandingFullyAbove)
}
override fun onAnimationEnd(animation: Animator?) {
+ Log.d(TAG, "Animation ended")
invokeCallback(iCallback)
controller.onLaunchAnimationEnd(isExpandingFullyAbove)
}
@@ -447,19 +483,52 @@
}
private fun applyStateToWindow(window: RemoteAnimationTarget, state: State) {
- val m = Matrix()
- m.postTranslate(0f, (state.top - window.sourceContainerBounds.top).toFloat())
- windowCrop.set(state.left, 0, state.right, state.height)
+ val screenBounds = window.screenSpaceBounds
+ val centerX = (screenBounds.left + screenBounds.right) / 2f
+ val centerY = (screenBounds.top + screenBounds.bottom) / 2f
+ val width = screenBounds.right - screenBounds.left
+ val height = screenBounds.bottom - screenBounds.top
- val cornerRadius = minOf(state.topCornerRadius, state.bottomCornerRadius)
+ // Scale the window. We use the max of (widthRatio, heightRatio) so that there is no
+ // blank space on any side.
+ val widthRatio = state.width.toFloat() / width
+ val heightRatio = state.height.toFloat() / height
+ val scale = maxOf(widthRatio, heightRatio)
+ matrix.reset()
+ matrix.setScale(scale, scale, centerX, centerY)
+
+ // Align it to the top and center it in the x-axis.
+ val heightChange = height * scale - height
+ val translationX = state.centerX - centerX
+ val translationY = state.top - screenBounds.top + heightChange / 2f
+ matrix.postTranslate(translationX, translationY)
+
+ // Crop it. The matrix will also be applied to the crop, so we apply the inverse
+ // operation. Given that we only scale (by factor > 0) then translate, we can assume
+ // that the matrix is invertible.
+ val cropX = state.left.toFloat() - screenBounds.left
+ val cropY = state.top.toFloat() - screenBounds.top
+ windowCropF.set(cropX, cropY, cropX + state.width, cropY + state.height)
+ matrix.invert(invertMatrix)
+ invertMatrix.mapRect(windowCropF)
+ windowCrop.set(
+ windowCropF.left.roundToInt(),
+ windowCropF.top.roundToInt(),
+ windowCropF.right.roundToInt(),
+ windowCropF.bottom.roundToInt()
+ )
+
+ // The scale will also be applied to the corner radius, so we divide by the scale to
+ // keep the original radius.
+ val cornerRadius = minOf(state.topCornerRadius, state.bottomCornerRadius) / scale
val params = SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(window.leash)
- .withAlpha(1f)
- .withMatrix(m)
- .withWindowCrop(windowCrop)
- .withLayer(window.prefixOrderIndex)
- .withCornerRadius(cornerRadius)
- .withVisibility(true)
- .build()
+ .withAlpha(1f)
+ .withMatrix(matrix)
+ .withWindowCrop(windowCrop)
+ .withLayer(window.prefixOrderIndex)
+ .withCornerRadius(cornerRadius)
+ .withVisibility(true)
+ .build()
transactionApplier.scheduleApply(params)
}
@@ -474,12 +543,13 @@
val params = SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(navigationBar.leash)
if (fadeInProgress > 0) {
- val m = Matrix()
- m.postTranslate(0f, (state.top - navigationBar.sourceContainerBounds.top).toFloat())
+ matrix.reset()
+ matrix.setTranslate(
+ 0f, (state.top - navigationBar.sourceContainerBounds.top).toFloat())
windowCrop.set(state.left, 0, state.right, state.height)
params
.withAlpha(NAV_FADE_IN_INTERPOLATOR.getInterpolation(fadeInProgress))
- .withMatrix(m)
+ .withMatrix(matrix)
.withWindowCrop(windowCrop)
.withVisibility(true)
} else {
@@ -496,6 +566,7 @@
return
}
+ Log.d(TAG, "Remote animation timed out")
timedOut = true
controller.onLaunchAnimationCancelled()
}
@@ -505,6 +576,7 @@
return
}
+ Log.d(TAG, "Remote animation was cancelled")
cancelled = true
removeTimeout()
context.mainExecutor.execute {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java b/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java
index 044b5ed..e1f72c1 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java
@@ -96,13 +96,18 @@
/**
* Interpolate alpha for notifications background scrim during shade expansion.
* @param fraction Shade expansion fraction
+ * @param forNotification If we want the alpha of the notification shade or the scrim.
*/
- public static float getNotificationScrimAlpha(float fraction) {
+ public static float getNotificationScrimAlpha(float fraction, boolean forNotification) {
+ if (!forNotification) {
+ fraction = MathUtils.saturate(1.7f * fraction);
+ }
fraction = fraction * 1.2f - 0.2f;
if (fraction <= 0) {
return 0;
} else {
- return (float) (1f - 0.5f * (1f - Math.cos(3.14159f * Math.pow(1f - fraction, 2f))));
+ final float oneMinusFrac = 1f - fraction;
+ return (float) (1f - 0.5f * (1f - Math.cos(3.14159f * oneMinusFrac * oneMinusFrac)));
}
}
}
diff --git a/packages/SystemUI/res/drawable/ic_cake.xml b/packages/SystemUI/res/drawable/ic_cake.xml
new file mode 100644
index 0000000..9c83b43
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_cake.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M19,14v-4c0,-1.1 -0.9,-2 -2,-2h-4L13,6.55c0.15,-0.09 0.29,-0.18 0.41,-0.31 0.39,-0.39 0.59,-0.92 0.59,-1.42s-0.2,-1.02 -0.59,-1.41L12,2l-1.41,1.41c-0.39,0.39 -0.59,0.91 -0.59,1.41s0.2,1.03 0.59,1.42c0.13,0.13 0.27,0.22 0.41,0.31L11,8L7,8c-1.1,0 -2,0.9 -2,2v4c-1.1,0 -2,0.9 -2,2v4c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2v-4c0,-1.1 -0.9,-2 -2,-2zM7,10h10v4L7,14v-4zM19,20L5,20v-4h14v4z"
+ android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_celebration.xml b/packages/SystemUI/res/drawable/ic_celebration.xml
new file mode 100644
index 0000000..10fe406
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_celebration.xml
@@ -0,0 +1,37 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M2,22l14,-5L7,8L2,22zM12.35,16.18L5.3,18.7l2.52,-7.05L12.35,16.18z"
+ android:fillColor="#FFFFFFFF"/>
+ <path
+ android:pathData="M14.53,12.53l5.59,-5.59c0.49,-0.49 1.28,-0.49 1.77,0l0.59,0.59l1.06,-1.06l-0.59,-0.59c-1.07,-1.07 -2.82,-1.07 -3.89,0l-5.59,5.59L14.53,12.53z"
+ android:fillColor="#FFFFFFFF"/>
+ <path
+ android:pathData="M10.06,6.88L9.47,7.47l1.06,1.06l0.59,-0.59c1.07,-1.07 1.07,-2.82 0,-3.89l-0.59,-0.59L9.47,4.53l0.59,0.59C10.54,5.6 10.54,6.4 10.06,6.88z"
+ android:fillColor="#FFFFFFFF"/>
+ <path
+ android:pathData="M17.06,11.88l-1.59,1.59l1.06,1.06l1.59,-1.59c0.49,-0.49 1.28,-0.49 1.77,0l1.61,1.61l1.06,-1.06l-1.61,-1.61C19.87,10.81 18.13,10.81 17.06,11.88z"
+ android:fillColor="#FFFFFFFF"/>
+ <path
+ android:pathData="M15.06,5.88l-3.59,3.59l1.06,1.06l3.59,-3.59c1.07,-1.07 1.07,-2.82 0,-3.89l-1.59,-1.59l-1.06,1.06l1.59,1.59C15.54,4.6 15.54,5.4 15.06,5.88z"
+ android:fillColor="#FFFFFFFF"/>
+</vector>
+
diff --git a/packages/SystemUI/res/drawable/ic_gift.xml b/packages/SystemUI/res/drawable/ic_gift.xml
new file mode 100644
index 0000000..fab36c3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_gift.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M22,5h-5.18C16.93,4.69 17,4.35 17,4c0,-1.65 -1.35,-3 -3,-3c-0.77,0 -1.47,0.3 -2,0.78C11.47,1.3 10.77,1 10,1C8.35,1 7,2.35 7,4c0,0.35 0.07,0.69 0.18,1H2v6h2v11h16V11h2V5zM14,3c0.55,0 1,0.45 1,1s-0.45,1 -1,1s-1,-0.45 -1,-1S13.45,3 14,3zM9,4c0,-0.55 0.45,-1 1,-1s1,0.45 1,1s-0.45,1 -1,1S9,4.55 9,4zM4,7h7v2H4V7zM6,11h5v9H6V11zM18,20h-5v-9h5V20zM20,9h-7V7h7V9z"
+ android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_pages.xml b/packages/SystemUI/res/drawable/ic_pages.xml
new file mode 100644
index 0000000..9cd076d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_pages.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M19,5v14L5,19L5,5h14m0,-2L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM12,17l1.57,-3.43L17,12l-3.43,-1.57L12,7l-1.57,3.43L7,12l3.43,1.57L12,17z"
+ android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_play_games.xml b/packages/SystemUI/res/drawable/ic_play_games.xml
new file mode 100644
index 0000000..20096f4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_play_games.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M20.47,8c-0.39,-2.3 -2.4,-4 -4.81,-4L8.34,4C5.93,4 3.93,5.7 3.53,8 3.53,8 2,16.8 2,16.93 2,18.07 2.93,19 4.07,19c0.57,0 1.09,-0.2 1.47,-0.58L9,15h6l3.46,3.42c0.38,0.38 0.89,0.58 1.47,0.58 1.15,0 2.07,-0.93 2.07,-2.07C22,16.8 20.47,8 20.47,8zM11,10L9,10v2L8,12v-2L6,10L6,9h2L8,7h1v2h2v1zM13.8,10.3c-0.44,0 -0.8,-0.36 -0.8,-0.8 0,-0.44 0.36,-0.8 0.8,-0.8 0.44,0 0.8,0.36 0.8,0.8 0,0.44 -0.36,0.8 -0.8,0.8zM15.49,12c-0.44,0 -0.8,-0.36 -0.8,-0.8 0,-0.44 0.36,-0.8 0.8,-0.8 0.44,0 0.8,0.36 0.8,0.8 0,0.44 -0.36,0.8 -0.8,0.8zM15.49,8.6c-0.44,0 -0.8,-0.36 -0.8,-0.8s0.36,-0.8 0.8,-0.8c0.44,0 0.8,0.36 0.8,0.8s-0.36,0.8 -0.8,0.8zM17.2,10.3c-0.44,0 -0.8,-0.36 -0.8,-0.8 0,-0.44 0.36,-0.8 0.8,-0.8s0.8,0.36 0.8,0.8c0,0.44 -0.36,0.8 -0.8,0.8z"
+ android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_video.xml b/packages/SystemUI/res/drawable/ic_video.xml
new file mode 100644
index 0000000..3668338
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_video.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M9,7v8l7,-4zM21,3L3,3c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h5v2h8v-2h5c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM21,17L3,17L3,5h18v12z"
+ android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/people_tile_large_with_content.xml b/packages/SystemUI/res/layout/people_tile_large_with_content.xml
index 4994c69..e294dad 100644
--- a/packages/SystemUI/res/layout/people_tile_large_with_content.xml
+++ b/packages/SystemUI/res/layout/people_tile_large_with_content.xml
@@ -34,8 +34,6 @@
<ImageView
android:id="@+id/person_icon"
- android:layout_marginStart="-2dp"
- android:layout_marginTop="-2dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
@@ -73,12 +71,12 @@
<include layout="@layout/people_tile_emoji_background_large" />
<TextView
- android:layout_gravity="top"
android:id="@+id/name"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/below_name_text_padding"
- android:gravity="start|top"
+ android:layout_gravity="start|center_vertical"
+ android:gravity="start|center_vertical"
android:singleLine="true"
android:ellipsize="end"
android:text="@string/empty_user_name"
@@ -103,7 +101,7 @@
<ImageView
android:id="@+id/predefined_icon"
- android:tint="?android:attr/colorAccent"
+ android:tint="?android:attr/textColorTertiary"
android:gravity="start|center_vertical"
android:layout_width="@dimen/regular_predefined_icon"
android:layout_height="@dimen/regular_predefined_icon" />
diff --git a/packages/SystemUI/res/layout/people_tile_medium_empty.xml b/packages/SystemUI/res/layout/people_tile_medium_empty.xml
index bebc872..8b2fddc 100644
--- a/packages/SystemUI/res/layout/people_tile_medium_empty.xml
+++ b/packages/SystemUI/res/layout/people_tile_medium_empty.xml
@@ -27,19 +27,23 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
- <ImageView
- android:id="@+id/person_icon"
- android:layout_marginTop="-2dp"
- android:layout_marginStart="-2dp"
- android:layout_width="64dp"
- android:layout_height="64dp" />
- <ImageView
- android:id="@+id/availability"
- android:gravity="top"
- android:layout_marginStart="-2dp"
- android:layout_width="10dp"
- android:layout_height="10dp"
- android:background="@drawable/availability_dot_10dp" />
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <ImageView
+ android:id="@+id/person_icon"
+ android:layout_width="64dp"
+ android:layout_height="64dp" />
+ <ImageView
+ android:id="@+id/availability"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:gravity="top"
+ android:layout_gravity="top"
+ android:layout_marginStart="-2dp"
+ android:background="@drawable/availability_dot_10dp" />
+ </LinearLayout>
<LinearLayout
android:orientation="vertical"
android:paddingStart="4dp"
diff --git a/packages/SystemUI/res/layout/people_tile_medium_with_content.xml b/packages/SystemUI/res/layout/people_tile_medium_with_content.xml
index a7a6354..47cab42 100644
--- a/packages/SystemUI/res/layout/people_tile_medium_with_content.xml
+++ b/packages/SystemUI/res/layout/people_tile_medium_with_content.xml
@@ -47,8 +47,6 @@
<ImageView
android:gravity="start"
android:id="@+id/person_icon"
- android:layout_marginStart="-2dp"
- android:layout_marginTop="-2dp"
android:layout_width="52dp"
android:layout_height="52dp" />
@@ -112,7 +110,8 @@
android:clipToOutline="true">
<TextView
android:id="@+id/name"
- android:gravity="center_vertical"
+ android:layout_gravity="start|center_vertical"
+ android:gravity="start|center_vertical"
android:layout_weight="1"
android:text="@string/empty_user_name"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
@@ -140,7 +139,7 @@
/>
<ImageView
android:id="@+id/predefined_icon"
- android:tint="?android:attr/colorAccent"
+ android:tint="?android:attr/textColorTertiary"
android:gravity="end|center_vertical"
android:layout_width="@dimen/regular_predefined_icon"
android:layout_height="@dimen/regular_predefined_icon" />
diff --git a/packages/SystemUI/res/layout/people_tile_small.xml b/packages/SystemUI/res/layout/people_tile_small.xml
index 4e5c04c..7a1371d 100644
--- a/packages/SystemUI/res/layout/people_tile_small.xml
+++ b/packages/SystemUI/res/layout/people_tile_small.xml
@@ -39,7 +39,7 @@
<ImageView
android:id="@+id/predefined_icon"
- android:tint="?android:attr/colorAccent"
+ android:tint="?android:attr/textColorTertiary"
android:layout_gravity="center"
android:layout_width="18dp"
android:layout_height="22dp" />
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 3543fd1..c16f13e 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -64,10 +64,6 @@
android:clipToPadding="false"
android:clipChildren="false">
- <include
- layout="@layout/keyguard_status_view"
- android:visibility="gone"/>
-
<com.android.systemui.scrim.ScrimView
android:id="@+id/scrim_notifications"
android:layout_width="0dp"
@@ -78,7 +74,11 @@
systemui:layout_constraintEnd_toEndOf="parent"
systemui:layout_constraintTop_toTopOf="parent"
systemui:layout_constraintBottom_toBottomOf="parent"
- />
+ />
+
+ <include
+ layout="@layout/keyguard_status_view"
+ android:visibility="gone"/>
<include layout="@layout/dock_info_overlay" />
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
index ee7eb4b..964b135 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
@@ -16,6 +16,7 @@
package com.android.systemui.accessibility;
+import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
import android.annotation.NonNull;
@@ -70,7 +71,7 @@
private final ImageView mImageView;
private final Runnable mWindowInsetChangeRunnable;
private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
- private int mMagnificationMode = Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+ private int mMagnificationMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
private final LayoutParams mParams;
@VisibleForTesting
final Rect mDraggableWindowBounds = new Rect();
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 9871b4e..146f430 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -54,14 +54,16 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import com.android.systemui.SystemUI;
+import com.android.systemui.assist.ui.DisplayUtils;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.doze.DozeReceiver;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import javax.inject.Inject;
import javax.inject.Provider;
@@ -79,13 +81,14 @@
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final CommandQueue mCommandQueue;
- private final StatusBarStateController mStatusBarStateController;
private final ActivityTaskManager mActivityTaskManager;
@Nullable private final FingerprintManager mFingerprintManager;
@Nullable private final FaceManager mFaceManager;
private final Provider<UdfpsController> mUdfpsControllerFactory;
private final Provider<SidefpsController> mSidefpsControllerFactory;
@Nullable private final PointF mFaceAuthSensorLocation;
+ @Nullable private final PointF mFingerprintLocation;
+ private final Set<Callback> mCallbacks = new HashSet<>();
// TODO: These should just be saved from onSaveState
private SomeArgs mCurrentDialogArgs;
@@ -142,6 +145,10 @@
if (mSidefpsProps != null) {
mSidefpsController = mSidefpsControllerFactory.get();
}
+
+ for (Callback cb : mCallbacks) {
+ cb.onAllAuthenticatorsRegistered();
+ }
}
};
@@ -195,6 +202,20 @@
}
}
+ /**
+ * Adds a callback. See {@link Callback}.
+ */
+ public void addCallback(@NonNull Callback callback) {
+ mCallbacks.add(callback);
+ }
+
+ /**
+ * Removes a callback. See {@link Callback}.
+ */
+ public void removeCallback(@NonNull Callback callback) {
+ mCallbacks.remove(callback);
+ }
+
@Override
public void dozeTimeTick() {
if (mUdfpsController != null) {
@@ -335,6 +356,17 @@
}
/**
+ * @return where the fingerprint sensor exists in pixels in portrait mode. devices without an
+ * overridden value will use the default value even if they don't have a fingerprint sensor
+ */
+ @Nullable public PointF getFingerprintSensorLocation() {
+ if (getUdfpsSensorLocation() != null) {
+ return getUdfpsSensorLocation();
+ }
+ return mFingerprintLocation;
+ }
+
+ /**
* @return where the face authentication sensor exists relative to the screen in pixels in
* portrait mode.
*/
@@ -387,7 +419,6 @@
@Inject
public AuthController(Context context, CommandQueue commandQueue,
- StatusBarStateController statusBarStateController,
ActivityTaskManager activityTaskManager,
@Nullable FingerprintManager fingerprintManager,
@Nullable FaceManager faceManager,
@@ -395,7 +426,6 @@
Provider<SidefpsController> sidefpsControllerFactory) {
super(context);
mCommandQueue = commandQueue;
- mStatusBarStateController = statusBarStateController;
mActivityTaskManager = activityTaskManager;
mFingerprintManager = fingerprintManager;
mFaceManager = faceManager;
@@ -414,6 +444,10 @@
(float) faceAuthLocation[1]);
}
+ mFingerprintLocation = new PointF(DisplayUtils.getWidth(mContext) / 2,
+ mContext.getResources().getDimensionPixelSize(
+ com.android.systemui.R.dimen.physical_fingerprint_sensor_center_screen_location_y));
+
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
@@ -481,14 +515,24 @@
*/
@Override
public void onBiometricAuthenticated() {
- mCurrentDialog.onAuthenticationSucceeded();
+ if (DEBUG) Log.d(TAG, "onBiometricAuthenticated: ");
+
+ if (mCurrentDialog != null) {
+ mCurrentDialog.onAuthenticationSucceeded();
+ } else {
+ Log.w(TAG, "onBiometricAuthenticated callback but dialog gone");
+ }
}
@Override
public void onBiometricHelp(String message) {
if (DEBUG) Log.d(TAG, "onBiometricHelp: " + message);
- mCurrentDialog.onHelp(message);
+ if (mCurrentDialog != null) {
+ mCurrentDialog.onHelp(message);
+ } else {
+ Log.w(TAG, "onBiometricHelp callback but dialog gone");
+ }
}
@Nullable
@@ -527,19 +571,23 @@
final boolean isSoftError = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED
|| error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT);
- if (mCurrentDialog.isAllowDeviceCredentials() && isLockout) {
- if (DEBUG) Log.d(TAG, "onBiometricError, lockout");
- mCurrentDialog.animateToCredentialUI();
- } else if (isSoftError) {
- final String errorMessage = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED)
- ? mContext.getString(R.string.biometric_not_recognized)
- : getErrorString(modality, error, vendorCode);
- if (DEBUG) Log.d(TAG, "onBiometricError, soft error: " + errorMessage);
- mCurrentDialog.onAuthenticationFailed(errorMessage);
+ if (mCurrentDialog != null) {
+ if (mCurrentDialog.isAllowDeviceCredentials() && isLockout) {
+ if (DEBUG) Log.d(TAG, "onBiometricError, lockout");
+ mCurrentDialog.animateToCredentialUI();
+ } else if (isSoftError) {
+ final String errorMessage = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED)
+ ? mContext.getString(R.string.biometric_not_recognized)
+ : getErrorString(modality, error, vendorCode);
+ if (DEBUG) Log.d(TAG, "onBiometricError, soft error: " + errorMessage);
+ mCurrentDialog.onAuthenticationFailed(errorMessage);
+ } else {
+ final String errorMessage = getErrorString(modality, error, vendorCode);
+ if (DEBUG) Log.d(TAG, "onBiometricError, hard error: " + errorMessage);
+ mCurrentDialog.onError(errorMessage);
+ }
} else {
- final String errorMessage = getErrorString(modality, error, vendorCode);
- if (DEBUG) Log.d(TAG, "onBiometricError, hard error: " + errorMessage);
- mCurrentDialog.onError(errorMessage);
+ Log.w(TAG, "onBiometricError callback but dialog is gone");
}
onCancelUdfps();
@@ -697,4 +745,12 @@
.setMultiSensorConfig(multiSensorConfig)
.build(sensorIds, credentialAllowed, mFpProps, mFaceProps);
}
+
+ interface Callback {
+ /**
+ * Called when authenticators are registered. If authenticators are already
+ * registered before this call, this callback will never be triggered.
+ */
+ void onAllAuthenticatorsRegistered();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
index 257bd25..cf577a3 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
@@ -28,6 +28,7 @@
import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.phone.StatusBar
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.ViewController
@@ -40,6 +41,7 @@
*/
@StatusBarScope
class AuthRippleController @Inject constructor(
+ private val statusBar: StatusBar,
private val sysuiContext: Context,
private val authController: AuthController,
private val configurationController: ConfigurationController,
@@ -49,13 +51,14 @@
private val bypassController: KeyguardBypassController,
rippleView: AuthRippleView?
) : ViewController<AuthRippleView>(rippleView) {
- private var fingerprintSensorLocation: PointF? = null
+ var fingerprintSensorLocation: PointF? = null
private var faceSensorLocation: PointF? = null
@VisibleForTesting
public override fun onViewAttached() {
updateRippleColor()
updateSensorLocation()
+ authController.addCallback(authControllerCallback)
configurationController.addCallback(configurationChangedListener)
keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
commandRegistry.registerCommand("auth-ripple") { AuthRippleCommand() }
@@ -63,6 +66,7 @@
@VisibleForTesting
public override fun onViewDetached() {
+ authController.removeCallback(authControllerCallback)
keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
configurationController.removeCallback(configurationChangedListener)
commandRegistry.unregisterCommand("auth-ripple")
@@ -97,9 +101,10 @@
})
}
- private fun updateSensorLocation() {
- fingerprintSensorLocation = authController.udfpsSensorLocation
+ fun updateSensorLocation() {
+ fingerprintSensorLocation = authController.fingerprintSensorLocation
faceSensorLocation = authController.faceAuthSensorLocation
+ statusBar.updateCircleReveal()
}
private fun updateRippleColor() {
@@ -134,6 +139,8 @@
}
}
+ private val authControllerCallback = AuthController.Callback { updateSensorLocation() }
+
inner class AuthRippleCommand : Command {
override fun execute(pw: PrintWriter, args: List<String>) {
if (args.isEmpty()) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index 374ddae..01fbe39 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -23,7 +23,11 @@
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.PointF
+import android.media.AudioAttributes
+import android.os.VibrationEffect
+import android.os.Vibrator
import android.util.AttributeSet
+import android.util.MathUtils
import android.view.View
import android.view.animation.PathInterpolator
import com.android.internal.graphics.ColorUtils
@@ -31,15 +35,26 @@
private const val RIPPLE_ANIMATION_DURATION: Long = 1533
private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f
+private const val RIPPLE_VIBRATION_PRIMITIVE: Int = VibrationEffect.Composition.PRIMITIVE_LOW_TICK
+private const val RIPPLE_VIBRATION_SIZE: Int = 60
+private const val RIPPLE_VIBRATION_SCALE_START: Float = 0.6f
+private const val RIPPLE_VIBRATION_SCALE_DECAY: Float = -0.1f
/**
* Expanding ripple effect on the transition from biometric authentication success to showing
* launcher.
*/
class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
+ private val vibrator: Vibrator? = context?.getSystemService(Vibrator::class.java)
private var rippleInProgress: Boolean = false
private val rippleShader = RippleShader()
private val ripplePaint = Paint()
+ private val rippleVibrationEffect = createVibrationEffect(vibrator)
+ private val rippleVibrationAttrs =
+ AudioAttributes.Builder()
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+ .build()
init {
rippleShader.color = 0xffffffff.toInt() // default color
@@ -95,6 +110,7 @@
visibility = GONE
}
})
+ vibrate()
animatorSet.start()
visibility = VISIBLE
rippleInProgress = true
@@ -108,4 +124,23 @@
// draw over the entire screen
canvas?.drawRect(0f, 0f, width.toFloat(), height.toFloat(), ripplePaint)
}
+
+ private fun vibrate() {
+ if (rippleVibrationEffect != null) {
+ vibrator?.vibrate(rippleVibrationEffect, rippleVibrationAttrs)
+ }
+ }
+
+ private fun createVibrationEffect(vibrator: Vibrator?): VibrationEffect? {
+ if (vibrator?.areAllPrimitivesSupported(RIPPLE_VIBRATION_PRIMITIVE) == false) {
+ return null
+ }
+ val composition = VibrationEffect.startComposition()
+ for (i in 0 until RIPPLE_VIBRATION_SIZE) {
+ val scale =
+ RIPPLE_VIBRATION_SCALE_START * MathUtils.exp(RIPPLE_VIBRATION_SCALE_DECAY * i)
+ composition.addPrimitive(RIPPLE_VIBRATION_PRIMITIVE, scale, 0 /* delay */)
+ }
+ return composition.compose()
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 3075617..5c360a6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -496,7 +496,6 @@
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
checkArgument(mSensorProps != null);
- mStatusBar.setSensorRect(getSensorLocation());
mCoreLayoutParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index 98d8866..6a025a7 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -184,10 +184,4 @@
// Refresh tile views to sync new conversations.
buildActivity();
}
-
- @Override
- protected void onPause() {
- super.onPause();
- finish();
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleStoryIconFactory.java b/packages/SystemUI/src/com/android/systemui/people/PeopleStoryIconFactory.java
index f3cb359..96aeb60 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleStoryIconFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleStoryIconFactory.java
@@ -29,6 +29,8 @@
import android.util.IconDrawableFactory;
import android.util.Log;
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+
import com.android.settingslib.Utils;
import com.android.systemui.R;
@@ -58,7 +60,7 @@
mIconDrawableFactory = iconDrawableFactory;
mImportantConversationColor = context.getColor(R.color.important_conversation);
mAccentColor = Utils.getColorAttr(context,
- com.android.internal.R.attr.colorAccentPrimary).getDefaultColor();
+ com.android.internal.R.attr.colorAccentPrimaryVariant).getDefaultColor();
mContext = context;
}
@@ -83,7 +85,8 @@
* Returns a {@link Drawable} for the entire conversation. The shortcut icon will be badged
* with the launcher icon of the app specified by packageName.
*/
- public Drawable getPeopleTileDrawable(Drawable headDrawable, String packageName, int userId,
+ public Drawable getPeopleTileDrawable(RoundedBitmapDrawable headDrawable, String packageName,
+ int userId,
boolean important, boolean newStory) {
return new PeopleStoryIconDrawable(headDrawable, getAppBadge(packageName, userId),
mIconBitmapSize, mImportantConversationColor, important, mIconSize, mDensity,
@@ -96,7 +99,7 @@
*/
public static class PeopleStoryIconDrawable extends Drawable {
private float mFullIconSize;
- private Drawable mAvatar;
+ private RoundedBitmapDrawable mAvatar;
private Drawable mBadgeIcon;
private int mIconSize;
private Paint mPriorityRingPaint;
@@ -105,12 +108,13 @@
private Paint mStoryPaint;
private float mDensity;
- PeopleStoryIconDrawable(Drawable avatar,
+ PeopleStoryIconDrawable(RoundedBitmapDrawable avatar,
Drawable badgeIcon,
int iconSize,
@ColorInt int ringColor,
boolean showImportantRing, float fullIconSize, float density,
@ColorInt int accentColor, boolean showStoryRing) {
+ avatar.setCircular(true);
mAvatar = avatar;
mBadgeIcon = badgeIcon;
mIconSize = iconSize;
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
index 59c7fd1..72d382a 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
@@ -45,9 +45,6 @@
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
-import android.icu.text.MeasureFormat;
-import android.icu.util.Measure;
-import android.icu.util.MeasureUnit;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
@@ -61,6 +58,9 @@
import android.widget.RemoteViews;
import android.widget.TextView;
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.launcher3.icons.FastBitmapDrawable;
import com.android.systemui.R;
@@ -72,6 +72,7 @@
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
@@ -94,6 +95,8 @@
public static final int LAYOUT_LARGE = 2;
private static final int MIN_CONTENT_MAX_LINES = 2;
+ private static final int NAME_MAX_LINES_WITHOUT_LAST_INTERACTION = 3;
+ private static final int NAME_MAX_LINES_WITH_LAST_INTERACTION = 1;
private static final int FIXED_HEIGHT_DIMENS_FOR_LARGE_NOTIF_CONTENT = 16 + 22 + 8 + 16;
private static final int FIXED_HEIGHT_DIMENS_FOR_LARGE_STATUS_CONTENT = 16 + 16 + 24 + 4 + 16;
@@ -225,7 +228,9 @@
Log.d(TAG,
"Create status view for: " + statusesForEntireView.get(0).getActivity());
}
- return createStatusRemoteViews(statusesForEntireView.get(0));
+ ConversationStatus mostRecentlyStartedStatus = statusesForEntireView.stream().max(
+ Comparator.comparing(s -> s.getStartTimeMillis())).get();
+ return createStatusRemoteViews(mostRecentlyStartedStatus);
}
return createLastInteractionRemoteViews();
@@ -579,11 +584,33 @@
setMaxLines(views, false);
}
setAvailabilityDotPadding(views, R.dimen.availability_dot_status_padding);
- // TODO: Set status pre-defined icons
- views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_person);
+ views.setImageViewResource(R.id.predefined_icon, getDrawableForStatus(status));
return views;
}
+ private int getDrawableForStatus(ConversationStatus status) {
+ switch (status.getActivity()) {
+ case ACTIVITY_NEW_STORY:
+ return R.drawable.ic_pages;
+ case ACTIVITY_ANNIVERSARY:
+ return R.drawable.ic_celebration;
+ case ACTIVITY_UPCOMING_BIRTHDAY:
+ return R.drawable.ic_gift;
+ case ACTIVITY_BIRTHDAY:
+ return R.drawable.ic_cake;
+ case ACTIVITY_LOCATION:
+ return R.drawable.ic_location;
+ case ACTIVITY_GAME:
+ return R.drawable.ic_play_games;
+ case ACTIVITY_VIDEO:
+ return R.drawable.ic_video;
+ case ACTIVITY_AUDIO:
+ return R.drawable.ic_music_note;
+ default:
+ return R.drawable.ic_person;
+ }
+ }
+
/**
* Update the padding of the availability dot. The padding on the availability dot decreases
* on the status layouts compared to all other layouts.
@@ -658,7 +685,6 @@
}
private RemoteViews decorateBackground(RemoteViews views, CharSequence content) {
- int visibility = View.GONE;
CharSequence emoji = getDoubleEmoji(content);
if (!TextUtils.isEmpty(emoji)) {
setEmojiBackground(views, emoji);
@@ -768,6 +794,7 @@
}
private RemoteViews setViewForContentLayout(RemoteViews views) {
+ views = decorateBackground(views, "");
if (mLayoutSize == LAYOUT_SMALL) {
views.setViewVisibility(R.id.predefined_icon, View.VISIBLE);
views.setViewVisibility(R.id.name, View.GONE);
@@ -819,6 +846,7 @@
private RemoteViews createLastInteractionRemoteViews() {
RemoteViews views = new RemoteViews(mContext.getPackageName(), getEmptyLayout());
+ views.setInt(R.id.name, "setMaxLines", NAME_MAX_LINES_WITH_LAST_INTERACTION);
if (mLayoutSize == LAYOUT_SMALL) {
views.setViewVisibility(R.id.name, View.VISIBLE);
views.setViewVisibility(R.id.predefined_icon, View.GONE);
@@ -836,6 +864,9 @@
} else {
if (DEBUG) Log.d(TAG, "Hide last interaction");
views.setViewVisibility(R.id.last_interaction, View.GONE);
+ if (mLayoutSize == LAYOUT_MEDIUM) {
+ views.setInt(R.id.name, "setMaxLines", NAME_MAX_LINES_WITHOUT_LAST_INTERACTION);
+ }
}
return views;
}
@@ -891,8 +922,9 @@
context.getPackageManager(),
IconDrawableFactory.newInstance(context, false),
maxAvatarSize);
- Drawable drawable = icon.loadDrawable(context);
- Drawable personDrawable = storyIcon.getPeopleTileDrawable(drawable,
+ RoundedBitmapDrawable roundedDrawable = RoundedBitmapDrawableFactory.create(
+ context.getResources(), icon.getBitmap());
+ Drawable personDrawable = storyIcon.getPeopleTileDrawable(roundedDrawable,
tile.getPackageName(), getUserId(tile), tile.isImportantConversation(),
hasNewStory);
return convertDrawableToBitmap(personDrawable);
@@ -907,14 +939,11 @@
}
long now = System.currentTimeMillis();
Duration durationSinceLastInteraction = Duration.ofMillis(now - lastInteraction);
- MeasureFormat formatter = MeasureFormat.getInstance(Locale.getDefault(),
- MeasureFormat.FormatWidth.WIDE);
if (durationSinceLastInteraction.toDays() <= ONE_DAY) {
return null;
} else if (durationSinceLastInteraction.toDays() < DAYS_IN_A_WEEK) {
- return context.getString(R.string.days_timestamp, formatter.formatMeasures(
- new Measure(durationSinceLastInteraction.toDays(),
- MeasureUnit.DAY)));
+ return context.getString(R.string.days_timestamp,
+ durationSinceLastInteraction.toDays());
} else if (durationSinceLastInteraction.toDays() == DAYS_IN_A_WEEK) {
return context.getString(R.string.one_week_timestamp);
} else if (durationSinceLastInteraction.toDays() < DAYS_IN_A_WEEK * 2) {
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
index 9e0dd72..2602d7a 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -667,12 +667,16 @@
if (icon != null) {
updatedTile.setUserIcon(icon);
}
+ if (DEBUG) Log.d(TAG, "Statuses: " + conversation.getStatuses().toString());
+ NotificationChannel channel = conversation.getParentNotificationChannel();
+ if (channel != null) {
+ if (DEBUG) Log.d(TAG, "Important:" + channel.isImportantConversation());
+ updatedTile.setIsImportantConversation(channel.isImportantConversation());
+ }
updatedTile
.setContactUri(uri)
.setStatuses(conversation.getStatuses())
- .setLastInteractionTimestamp(conversation.getLastEventTimestamp())
- .setIsImportantConversation(conversation.getParentNotificationChannel() != null
- && conversation.getParentNotificationChannel().isImportantConversation());
+ .setLastInteractionTimestamp(conversation.getLastEventTimestamp());
updateAppWidgetOptionsAndView(appWidgetId, updatedTile.build());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index b93da4b..99c0f4e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -31,8 +31,8 @@
import android.view.accessibility.AccessibilityNodeInfo;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -180,7 +180,7 @@
if (ambientState.isExpansionChanging() && !ambientState.isOnKeyguard()) {
viewState.alpha = Interpolators.getNotificationScrimAlpha(
- ambientState.getExpansionFraction());
+ ambientState.getExpansionFraction(), true /* notification */);
} else {
viewState.alpha = 1f - ambientState.getHideAmount();
}
@@ -255,7 +255,6 @@
int backgroundTop = 0;
int clipTopAmount = 0;
float firstElementRoundness = 0.0f;
- ActivatableNotificationView previousAnv = null;
for (int i = 0; i < mHostLayoutController.getChildCount(); i++) {
ExpandableView child = mHostLayoutController.getChildAt(i);
@@ -327,52 +326,10 @@
notGoneIndex++;
}
- final float viewEnd = viewStart + child.getActualHeight();
- final float cornerAnimationDistance = mCornerAnimationDistance
- * mAmbientState.getExpansionFraction();
- final float cornerAnimationTop = shelfStart - cornerAnimationDistance;
-
if (child instanceof ActivatableNotificationView) {
ActivatableNotificationView anv =
(ActivatableNotificationView) child;
-
- final boolean isUnlockedHeadsUp = !mAmbientState.isOnKeyguard()
- && !mAmbientState.isShadeExpanded()
- && child instanceof ExpandableView
- && ((ExpandableNotificationRow) child).isHeadsUp();
- if (viewStart < shelfStart
- && !mHostLayoutController.isViewAffectedBySwipe(anv)
- && !isUnlockedHeadsUp
- && !mAmbientState.isPulsing()
- && !mAmbientState.isDozing()) {
-
- if (viewEnd >= cornerAnimationTop) {
- // Round bottom corners within animation bounds
- final float changeFraction = MathUtils.saturate(
- (viewEnd - cornerAnimationTop) / cornerAnimationDistance);
- final float roundness = anv.isLastInSection() ? 1f : changeFraction * 1f;
- anv.setBottomRoundness(roundness, false);
-
- } else if (viewEnd < cornerAnimationTop) {
- // Fast scroll skips frames and leaves corners with unfinished rounding.
- // Reset top and bottom corners outside of animation bounds.
- anv.setBottomRoundness(anv.isLastInSection() ? 1f : 0f, false);
- }
-
- if (viewStart >= cornerAnimationTop) {
- // Round top corners within animation bounds
- final float changeFraction = MathUtils.saturate(
- (viewStart - cornerAnimationTop) / cornerAnimationDistance);
- final float roundness = anv.isFirstInSection() ? 1f : changeFraction * 1f;
- anv.setTopRoundness(roundness, false);
-
- } else if (viewStart < cornerAnimationTop) {
- // Fast scroll skips frames and leaves corners with unfinished rounding.
- // Reset top and bottom corners outside of animation bounds.
- anv.setTopRoundness(anv.isFirstInSection() ? 1f : 0f, false);
- }
- }
- previousAnv = anv;
+ updateCornerRoundnessOnScroll(anv, viewStart, shelfStart);
}
}
@@ -408,6 +365,58 @@
}
}
+ private void updateCornerRoundnessOnScroll(ActivatableNotificationView anv, float viewStart,
+ float shelfStart) {
+
+ final boolean isUnlockedHeadsUp = !mAmbientState.isOnKeyguard()
+ && !mAmbientState.isShadeExpanded()
+ && anv instanceof ExpandableNotificationRow
+ && ((ExpandableNotificationRow) anv).isHeadsUp();
+
+ final boolean shouldUpdateCornerRoundness = viewStart < shelfStart
+ && !mHostLayoutController.isViewAffectedBySwipe(anv)
+ && !isUnlockedHeadsUp
+ && !mAmbientState.isPulsing()
+ && !mAmbientState.isDozing();
+
+ if (!shouldUpdateCornerRoundness) {
+ return;
+ }
+
+ final float viewEnd = viewStart + anv.getActualHeight();
+ final float cornerAnimationDistance = mCornerAnimationDistance
+ * mAmbientState.getExpansionFraction();
+ final float cornerAnimationTop = shelfStart - cornerAnimationDistance;
+
+ if (viewEnd >= cornerAnimationTop) {
+ // Round bottom corners within animation bounds
+ final float changeFraction = MathUtils.saturate(
+ (viewEnd - cornerAnimationTop) / cornerAnimationDistance);
+ anv.setBottomRoundness(anv.isLastInSection() ? 1f : changeFraction,
+ false /* animate */);
+
+ } else if (viewEnd < cornerAnimationTop) {
+ // Fast scroll skips frames and leaves corners with unfinished rounding.
+ // Reset top and bottom corners outside of animation bounds.
+ anv.setBottomRoundness(anv.isLastInSection() ? 1f : 0f,
+ false /* animate */);
+ }
+
+ if (viewStart >= cornerAnimationTop) {
+ // Round top corners within animation bounds
+ final float changeFraction = MathUtils.saturate(
+ (viewStart - cornerAnimationTop) / cornerAnimationDistance);
+ anv.setTopRoundness(anv.isFirstInSection() ? 1f : changeFraction,
+ false /* animate */);
+
+ } else if (viewStart < cornerAnimationTop) {
+ // Fast scroll skips frames and leaves corners with unfinished rounding.
+ // Reset top and bottom corners outside of animation bounds.
+ anv.setTopRoundness(anv.isFirstInSection() ? 1f : 0f,
+ false /* animate */);
+ }
+ }
+
/**
* Clips transient views to the top of the shelf - Transient views are only used for
* disappearing views/animations and need to be clipped correctly by the shelf to ensure they
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index e931ec4..0d34e90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -24,8 +24,8 @@
import android.view.View;
import android.view.ViewGroup;
-import com.android.systemui.animation.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.dagger.SilentHeader;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -382,7 +382,7 @@
if (ambientState.isExpansionChanging() && !ambientState.isOnKeyguard()) {
viewState.alpha = Interpolators.getNotificationScrimAlpha(
- ambientState.getExpansionFraction());
+ ambientState.getExpansionFraction(), true /* notification */);
} else {
viewState.alpha = 1f - ambientState.getHideAmount();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 7c63763..b92f7c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -548,8 +548,11 @@
*/
public void setNotificationsBounds(float left, float top, float right, float bottom) {
if (mClipsQsScrim) {
- // "top - 1" to have 1 px of scrims overlap, see: b/186644628
- mNotificationsScrim.setDrawableBounds(left, top - 1, right, bottom);
+ // notification scrim's rounded corners are anti-aliased, but clipping of the QS scrim
+ // can't be and it's causing jagged corners. That's why notification scrim needs
+ // to overlap QS scrim by one pixel - both vertically (top - 1) and
+ // horizontally (left - 1 and right + 1), see: b/186644628
+ mNotificationsScrim.setDrawableBounds(left - 1, top - 1, right + 1, bottom);
mScrimBehind.setBottomEdgePosition((int) top);
} else {
mNotificationsScrim.setDrawableBounds(left, top, right, bottom);
@@ -883,7 +886,7 @@
}
private float getInterpolatedFraction() {
- return Interpolators.getNotificationScrimAlpha(mPanelExpansion);
+ return Interpolators.getNotificationScrimAlpha(mPanelExpansion, false /* notification */);
}
private void setScrimAlpha(ScrimView scrim, float alpha) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index eec896a..1364d47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -73,9 +73,9 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
-import android.graphics.RectF;
import android.media.AudioAttributes;
import android.metrics.LogMaker;
import android.net.Uri;
@@ -150,6 +150,7 @@
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.DelegateLaunchAnimatorController;
import com.android.systemui.assist.AssistManager;
+import com.android.systemui.biometrics.AuthRippleController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.camera.CameraIntents;
import com.android.systemui.charging.WirelessChargingAnimation;
@@ -326,9 +327,15 @@
public static final int FADE_KEYGUARD_DURATION = 300;
public static final int FADE_KEYGUARD_DURATION_PULSING = 96;
+ public static final long[] CAMERA_LAUNCH_GESTURE_VIBRATION_TIMINGS =
+ new long[]{20, 20, 20, 20, 100, 20};
+ public static final int[] CAMERA_LAUNCH_GESTURE_VIBRATION_AMPLITUDES =
+ new int[]{39, 82, 139, 213, 0, 127};
- /** If true, the system is in the half-boot-to-decryption-screen state.
- * Prudently disable QS and notifications. */
+ /**
+ * If true, the system is in the half-boot-to-decryption-screen state.
+ * Prudently disable QS and notifications.
+ */
public static final boolean ONLY_CORE_APPS;
/** If true, the lockscreen will show a distinct wallpaper */
@@ -380,6 +387,7 @@
protected NotificationShadeWindowView mNotificationShadeWindowView;
protected StatusBarWindowView mPhoneStatusBarWindow;
protected PhoneStatusBarView mStatusBarView;
+ private AuthRippleController mAuthRippleController;
private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
protected NotificationShadeWindowController mNotificationShadeWindowController;
protected StatusBarWindowController mStatusBarWindowController;
@@ -600,7 +608,7 @@
private int mLastCameraLaunchSource;
protected PowerManager.WakeLock mGestureWakeLock;
private Vibrator mVibrator;
- private long[] mCameraLaunchGestureVibePattern;
+ private VibrationEffect mCameraLaunchGestureVibrationEffect;
private final int[] mTmpInt2 = new int[2];
@@ -1311,12 +1319,8 @@
mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
"GestureWakeLock");
mVibrator = mContext.getSystemService(Vibrator.class);
- int[] pattern = mContext.getResources().getIntArray(
- R.array.config_cameraLaunchGestureVibePattern);
- mCameraLaunchGestureVibePattern = new long[pattern.length];
- for (int i = 0; i < pattern.length; i++) {
- mCameraLaunchGestureVibePattern[i] = pattern[i];
- }
+ mCameraLaunchGestureVibrationEffect = getCameraGestureVibrationEffect(
+ mVibrator, context.getResources());
// receive broadcasts
registerBroadcastReceiver();
@@ -1556,7 +1560,9 @@
mPhoneStatusBarWindow = mSuperStatusBarViewFactory.getStatusBarWindowView();
mNotificationPanelViewController = statusBarComponent.getNotificationPanelViewController();
statusBarComponent.getLockIconViewController().init();
- statusBarComponent.getAuthRippleController().init();
+
+ mAuthRippleController = statusBarComponent.getAuthRippleController();
+ mAuthRippleController.init();
}
protected void startKeyguard() {
@@ -2801,7 +2807,7 @@
int[] result = new int[]{ActivityManager.START_CANCELED};
mActivityLaunchAnimator.startIntentWithAnimation(animController,
- areLaunchAnimationsEnabled(), (adapter) -> {
+ areLaunchAnimationsEnabled(), intent.getPackage(), (adapter) -> {
ActivityOptions options = new ActivityOptions(
getActivityOptions(mDisplayId, adapter));
options.setDisallowEnterPictureInPictureWhileLaunching(
@@ -3791,7 +3797,8 @@
@Override
public void onDozeAmountChanged(float linear, float eased) {
- if (mFeatureFlags.useNewLockscreenAnimations()) {
+ if (mFeatureFlags.useNewLockscreenAnimations()
+ && !mCircleRevealAnimator.isRunning()) {
mLightRevealScrim.setRevealAmount(1f - linear);
}
}
@@ -3828,6 +3835,23 @@
Trace.endSection();
}
+ /**
+ * Update the parameters for the dozing circle reveal that animates when the user authenticates
+ * from AOD using the fingerprint sensor.
+ */
+ public void updateCircleReveal() {
+ final PointF fpLocation = mAuthRippleController.getFingerprintSensorLocation();
+ if (fpLocation != null) {
+ mCircleReveal =
+ new CircleReveal(
+ fpLocation.x,
+ fpLocation.y,
+ 0,
+ Math.max(Math.max(fpLocation.x, getDisplayWidth() - fpLocation.x),
+ Math.max(fpLocation.y, getDisplayHeight() - fpLocation.y)));
+ }
+ }
+
private void startCircleReveal() {
mLightRevealScrim.setRevealEffect(mCircleReveal);
mCircleRevealAnimator.cancel();
@@ -3840,7 +3864,6 @@
private boolean shouldShowCircleReveal() {
return mCircleReveal != null && !mCircleRevealAnimator.isRunning()
- && mKeyguardUpdateMonitor.isUdfpsEnrolled()
&& mBiometricUnlockController.getBiometricType() == FINGERPRINT;
}
@@ -4062,12 +4085,37 @@
private void vibrateForCameraGesture() {
// Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
- mVibrator.vibrate(mCameraLaunchGestureVibePattern, -1 /* repeat */);
+ mVibrator.vibrate(mCameraLaunchGestureVibrationEffect);
+ }
+
+ private static VibrationEffect getCameraGestureVibrationEffect(Vibrator vibrator,
+ Resources resources) {
+ if (vibrator.areAllPrimitivesSupported(
+ VibrationEffect.Composition.PRIMITIVE_QUICK_RISE,
+ VibrationEffect.Composition.PRIMITIVE_CLICK)) {
+ return VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 50)
+ .compose();
+ }
+ if (vibrator.hasAmplitudeControl()) {
+ return VibrationEffect.createWaveform(
+ CAMERA_LAUNCH_GESTURE_VIBRATION_TIMINGS,
+ CAMERA_LAUNCH_GESTURE_VIBRATION_AMPLITUDES,
+ /* repeat= */ -1);
+ }
+
+ int[] pattern = resources.getIntArray(R.array.config_cameraLaunchGestureVibePattern);
+ long[] timings = new long[pattern.length];
+ for (int i = 0; i < pattern.length; i++) {
+ timings[i] = pattern[i];
+ }
+ return VibrationEffect.createWaveform(timings, /* repeat= */ -1);
}
/**
* @return true if the screen is currently fully off, i.e. has finished turning off and has
- * since not started turning on.
+ * since not started turning on.
*/
public boolean isScreenFullyOff() {
return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_OFF;
@@ -4278,15 +4326,6 @@
updateScrimController();
}
- /**
- * Set the location of the sensor on UDFPS if existent.
- */
- public void setSensorRect(RectF rect) {
- final float startRadius = (rect.right - rect.left) / 2f;
- mCircleReveal = new CircleReveal(rect.centerX(), rect.centerY(),
- startRadius, rect.centerY() - startRadius);
- }
-
@VisibleForTesting
public void updateScrimController() {
Trace.beginSection("StatusBar#updateScrimController");
@@ -4565,7 +4604,7 @@
animationController, this, intent.isActivity()) : null;
mActivityLaunchAnimator.startPendingIntentWithAnimation(
- controller, areLaunchAnimationsEnabled(),
+ controller, areLaunchAnimationsEnabled(), intent.getCreatorPackage(),
(animationAdapter) -> intent.sendAndReturnResult(null, 0, null, null, null,
null, getActivityOptions(mDisplayId, animationAdapter)));
} catch (PendingIntent.CanceledException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index ab58aae6..5cd4e13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -437,7 +437,7 @@
mActivityLaunchAnimator.startPendingIntentWithAnimation(animationController,
!wasOccluded && mStatusBar.areLaunchAnimationsEnabled(),
- (adapter) -> {
+ intent.getCreatorPackage(), (adapter) -> {
long eventTime = row.getAndResetLastActionUpTime();
Bundle options = eventTime > 0
? getActivityOptions(
@@ -469,6 +469,7 @@
mActivityLaunchAnimator.startIntentWithAnimation(
animationController, mStatusBar.areLaunchAnimationsEnabled(),
+ intent.getPackage(),
(adapter) -> TaskStackBuilder.create(mContext)
.addNextIntentWithParentStack(intent)
.startActivities(getActivityOptions(
@@ -499,7 +500,7 @@
true /* isActivityIntent */);
mActivityLaunchAnimator.startIntentWithAnimation(animationController,
- mStatusBar.areLaunchAnimationsEnabled(),
+ mStatusBar.areLaunchAnimationsEnabled(), intent.getPackage(),
(adapter) -> tsb.startActivities(
getActivityOptions(mStatusBar.getDisplayId(), adapter),
UserHandle.CURRENT));
diff --git a/packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt b/packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
index 603d690..8187956 100644
--- a/packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
+++ b/packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
@@ -76,29 +76,41 @@
}
val linearInterp = LinearInterpolator()
val scaleInterp = PathInterpolator(0.3f, 0f, 1f, 1f)
- val sX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.9f).apply {
+ val viewScaleX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.9f).apply {
interpolator = scaleInterp
duration = 250
}
- val sY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.9f).apply {
+ val viewScaleY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.9f).apply {
interpolator = scaleInterp
duration = 250
}
- val vA = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f).apply {
+ val viewElevation = ObjectAnimator.ofFloat(view, "elevation",
+ view.elevation, 0f).apply {
+ interpolator = linearInterp
+ duration = 40
+ startDelay = 150
+ }
+ val viewAlpha = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f).apply {
interpolator = linearInterp
duration = 100
startDelay = 150
}
- val tA = ObjectAnimator.ofFloat(text, "alpha", 1f, 0f).apply {
+ val textAlpha = ObjectAnimator.ofFloat(text, "alpha", 1f, 0f).apply {
interpolator = linearInterp
duration = 166
}
- val iA = ObjectAnimator.ofFloat(icon, "alpha", 1f, 0f).apply {
+ val iconAlpha = ObjectAnimator.ofFloat(icon, "alpha", 1f, 0f).apply {
interpolator = linearInterp
duration = 166
}
return AnimatorSet().apply {
- playTogether(sX, sY, vA, tA, iA)
+ playTogether(
+ viewScaleX,
+ viewScaleY,
+ viewElevation,
+ viewAlpha,
+ textAlpha,
+ iconAlpha)
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
index d9a240f..936ec80 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
@@ -100,8 +100,6 @@
private AccessibilityManager mAccessibilityManager;
@Mock
private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
- @Mock
- private Handler mHandler;
private TestableWindowManager mWindowManager;
private ViewPropertyAnimator mViewPropertyAnimator;
private MagnificationModeSwitch mMagnificationModeSwitch;
@@ -152,12 +150,12 @@
}
@Test
- public void showWindowModeButton_fullscreenMode_addViewAndSetImageResource() {
- mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+ public void showFullscreenModeButton_addViewAndSetImageResource() {
+ mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
verify(mSpyImageView).setImageResource(
- getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW));
- verify(mWindowManager).addView(eq(mSpyImageView), any(WindowManager.LayoutParams.class));
+ getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN));
+ assertEquals(mSpyImageView, mWindowManager.getAttachedView());
assertShowFadingAnimation(FADE_IN_ALPHA);
assertShowFadingAnimation(FADE_OUT_ALPHA);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
index 897d78b..f2ef5c3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
@@ -51,7 +51,11 @@
// We start in a new thread so that we can ensure that the callbacks are called in the main
// thread.
thread {
- activityLaunchAnimator.startIntentWithAnimation(controller, animate, intentStarter)
+ activityLaunchAnimator.startIntentWithAnimation(
+ controller = controller,
+ animate = animate,
+ intentStarter = intentStarter
+ )
}.join()
}
@@ -135,11 +139,14 @@
verify(controller).onLaunchAnimationStart(anyBoolean())
}
- private fun fakeWindow() = RemoteAnimationTarget(
- 0, RemoteAnimationTarget.MODE_OPENING, SurfaceControl(), false, Rect(), Rect(), 0,
- Point(), Rect(), Rect(), WindowConfiguration(), false, SurfaceControl(), Rect(),
- ActivityManager.RunningTaskInfo()
- )
+ private fun fakeWindow(): RemoteAnimationTarget {
+ val bounds = Rect(10 /* left */, 20 /* top */, 30 /* right */, 40 /* bottom */)
+ return RemoteAnimationTarget(
+ 0, RemoteAnimationTarget.MODE_OPENING, SurfaceControl(), false, Rect(), Rect(), 0,
+ Point(), Rect(), bounds, WindowConfiguration(), false, SurfaceControl(), Rect(),
+ ActivityManager.RunningTaskInfo()
+ )
+ }
}
/**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
index 36a031a..06f9253 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
@@ -26,6 +26,7 @@
import static org.mockito.Mockito.verify;
import android.content.Context;
+import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.PromptInfo;
import android.os.Bundle;
import android.test.suitebuilder.annotation.SmallTest;
@@ -202,7 +203,7 @@
waitForIdleSync();
verify(mCallback).onAction(AuthBiometricView.Callback.ACTION_ERROR);
- assertEquals(AuthBiometricView.STATE_ERROR, mBiometricView.mState);
+ assertEquals(AuthBiometricView.STATE_IDLE, mBiometricView.mState);
}
@Test
@@ -253,6 +254,12 @@
public TextView getIndicatorView() {
return indicatorView;
}
+
+ @Override
+ public int getDelayAfterError() {
+ // keep a real delay to test saving in the error state
+ return BiometricPrompt.HIDE_DIALOG_DELAY;
+ }
});
final String failureMessage = "testFailureMessage";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index bb2e55f..db5648a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -62,7 +62,6 @@
import com.android.internal.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import org.junit.Before;
@@ -96,8 +95,6 @@
@Mock
private CommandQueue mCommandQueue;
@Mock
- private StatusBarStateController mStatusBarStateController;
- @Mock
private ActivityTaskManager mActivityTaskManager;
@Mock
private FingerprintManager mFingerprintManager;
@@ -152,7 +149,7 @@
when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(props);
mAuthController = new TestableAuthController(context, mCommandQueue,
- mStatusBarStateController, mActivityTaskManager, mFingerprintManager, mFaceManager,
+ mActivityTaskManager, mFingerprintManager, mFaceManager,
() -> mUdfpsController, () -> mSidefpsController);
mAuthController.start();
@@ -561,13 +558,12 @@
private PromptInfo mLastBiometricPromptInfo;
TestableAuthController(Context context, CommandQueue commandQueue,
- StatusBarStateController statusBarStateController,
ActivityTaskManager activityTaskManager,
FingerprintManager fingerprintManager,
FaceManager faceManager,
Provider<UdfpsController> udfpsControllerFactory,
Provider<SidefpsController> sidefpsControllerFactory) {
- super(context, commandQueue, statusBarStateController, activityTaskManager,
+ super(context, commandQueue, activityTaskManager,
fingerprintManager, faceManager, udfpsControllerFactory,
sidefpsControllerFactory);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
index 247748a..240fdf3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
@@ -26,6 +26,7 @@
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.phone.StatusBar
import com.android.systemui.statusbar.policy.ConfigurationController
import org.junit.Before
import org.junit.Test
@@ -44,6 +45,7 @@
@RunWith(AndroidTestingRunner::class)
class AuthRippleControllerTest : SysuiTestCase() {
private lateinit var controller: AuthRippleController
+ @Mock private lateinit var statusBar: StatusBar
@Mock private lateinit var rippleView: AuthRippleView
@Mock private lateinit var commandRegistry: CommandRegistry
@Mock private lateinit var configurationController: ConfigurationController
@@ -56,6 +58,7 @@
fun setUp() {
MockitoAnnotations.initMocks(this)
controller = AuthRippleController(
+ statusBar,
context,
authController,
configurationController,
@@ -72,7 +75,7 @@
fun testFingerprintTrigger_Ripple() {
// GIVEN fp exists, keyguard is visible, user doesn't need strong auth
val fpsLocation = PointF(5f, 5f)
- `when`(authController.udfpsSensorLocation).thenReturn(fpsLocation)
+ `when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
@@ -193,7 +196,7 @@
@Test
fun testNullFingerprintSensorLocationDoesNothing() {
- `when`(authController.udfpsSensorLocation).thenReturn(null)
+ `when`(authController.fingerprintSensorLocation).thenReturn(null)
controller.onViewAttached()
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
index 3b56f22..67505c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
@@ -69,6 +69,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.time.Duration;
import java.util.Arrays;
@RunWith(AndroidTestingRunner.class)
@@ -185,6 +186,30 @@
}
@Test
+ public void testLastInteractionTime() {
+ long now = System.currentTimeMillis();
+ long fiveDaysAgo = now - Duration.ofDays(5).toMillis();
+ String lastInteractionString = PeopleTileViewHelper.getLastInteractionString(mContext,
+ fiveDaysAgo);
+ assertThat(lastInteractionString).isEqualTo("5 days ago");
+
+ long lessThanOneDayAgo = now - Duration.ofHours(20).toMillis();
+ lastInteractionString = PeopleTileViewHelper.getLastInteractionString(mContext,
+ lessThanOneDayAgo);
+ assertThat(lastInteractionString).isNull();
+
+ long overOneWeekAgo = now - Duration.ofDays(8).toMillis();
+ lastInteractionString = PeopleTileViewHelper.getLastInteractionString(mContext,
+ overOneWeekAgo);
+ assertThat(lastInteractionString).isEqualTo("Over 1 week ago");
+
+ long overTwoWeeksAgo = now - Duration.ofDays(15).toMillis();
+ lastInteractionString = PeopleTileViewHelper.getLastInteractionString(mContext,
+ overTwoWeeksAgo);
+ assertThat(lastInteractionString).isEqualTo("Over 2 weeks ago");
+ }
+
+ @Test
public void testCreateRemoteViewsWithLastInteractionTime() {
PeopleSpaceTile tileWithLastInteraction =
PERSON_TILE_WITHOUT_NOTIFICATION.toBuilder().setLastInteractionTimestamp(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index a431a78..8b0b579 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -1118,7 +1118,7 @@
public void testNotificationTransparency_inKeyguardState() {
mScrimController.transitionTo(ScrimState.KEYGUARD);
- assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.2f, /* expansion */ 0.8f);
+ assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.2f, /* expansion */ 0.4f);
assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.8f, /* expansion */ 0.2f);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index be86af5..407afbe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -269,7 +269,7 @@
verify(mShadeController, atLeastOnce()).collapsePanel();
verify(mActivityLaunchAnimator).startPendingIntentWithAnimation(any(),
- eq(false) /* animate */, any());
+ eq(false) /* animate */, any(), any());
verify(mAssistManager).hideAssist();
diff --git a/services/Android.bp b/services/Android.bp
index 1dd2192..f2e0b20 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -141,7 +141,6 @@
libs: [
"android.hidl.manager-V1.0-java",
"framework-tethering.stubs.module_lib",
- "service-art.stubs.system_server",
],
// Uncomment to enable output of certain warnings (deprecated, unchecked)
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index ab85b5e..83dfe8e 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -20,6 +20,7 @@
import static android.bluetooth.le.ScanSettings.CALLBACK_TYPE_ALL_MATCHES;
import static android.bluetooth.le.ScanSettings.SCAN_MODE_BALANCED;
import static android.content.Context.BIND_IMPORTANT;
+import static android.content.pm.PackageManager.CERT_INPUT_SHA256;
import static android.content.pm.PackageManager.MATCH_ALL;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -657,7 +658,14 @@
}
@Override
- public void createAssociation(String packageName, String macAddress, int userId) {
+ public void createAssociation(String packageName, String macAddress, int userId,
+ byte[] certificate) {
+ if (!getContext().getPackageManager().hasSigningCertificate(
+ packageName, certificate, CERT_INPUT_SHA256)) {
+ Slog.e(LOG_TAG, "Given certificate doesn't match the package certificate.");
+ return;
+ }
+
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES, "createAssociation");
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 6e7771d..e336b6b 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -39,11 +39,9 @@
import libcore.io.IoUtils;
import java.io.DataInputStream;
-import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
@@ -377,11 +375,16 @@
try {
FileChannel channel = getBlockOutputChannel();
- ByteBuffer buf = ByteBuffer.allocate(DIGEST_SIZE_BYTES + HEADER_SIZE);
+ int header_size = DIGEST_SIZE_BYTES + HEADER_SIZE;
+ ByteBuffer buf = ByteBuffer.allocate(header_size);
buf.put(new byte[DIGEST_SIZE_BYTES]);
buf.putInt(PARTITION_TYPE_MARKER);
buf.putInt(0);
channel.write(buf);
+ // corrupt the payload explicitly
+ int payload_size = (int) getBlockDeviceSize() - header_size;
+ buf = ByteBuffer.allocate(payload_size);
+ channel.write(buf);
channel.force(true);
} catch (IOException e) {
Slog.e(TAG, "failed to format block", e);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 0f3aa65..562f8f44 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -21,38 +21,40 @@
import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND;
import static android.app.ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
+import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST;
+import static android.os.PowerExemptionManager.REASON_ACTIVITY_STARTER;
import static android.os.PowerExemptionManager.REASON_ACTIVITY_VISIBILITY_GRACE_PERIOD;
+import static android.os.PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE;
+import static android.os.PowerExemptionManager.REASON_BACKGROUND_ACTIVITY_PERMISSION;
+import static android.os.PowerExemptionManager.REASON_BACKGROUND_FGS_PERMISSION;
+import static android.os.PowerExemptionManager.REASON_COMPANION_DEVICE_MANAGER;
+import static android.os.PowerExemptionManager.REASON_DENIED;
+import static android.os.PowerExemptionManager.REASON_DEVICE_DEMO_MODE;
+import static android.os.PowerExemptionManager.REASON_DEVICE_OWNER;
+import static android.os.PowerExemptionManager.REASON_FGS_BINDING;
+import static android.os.PowerExemptionManager.REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION;
+import static android.os.PowerExemptionManager.REASON_INSTR_BACKGROUND_FGS_PERMISSION;
import static android.os.PowerExemptionManager.REASON_OPT_OUT_REQUESTED;
import static android.os.PowerExemptionManager.REASON_OP_ACTIVATE_PLATFORM_VPN;
import static android.os.PowerExemptionManager.REASON_OP_ACTIVATE_VPN;
+import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT;
+import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI;
+import static android.os.PowerExemptionManager.REASON_PROC_STATE_TOP;
+import static android.os.PowerExemptionManager.REASON_PROFILE_OWNER;
+import static android.os.PowerExemptionManager.REASON_SERVICE_LAUNCH;
+import static android.os.PowerExemptionManager.REASON_START_ACTIVITY_FLAG;
+import static android.os.PowerExemptionManager.REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
+import static android.os.PowerExemptionManager.REASON_SYSTEM_ALLOW_LISTED;
+import static android.os.PowerExemptionManager.REASON_SYSTEM_UID;
import static android.os.PowerExemptionManager.REASON_TEMP_ALLOWED_WHILE_IN_USE;
-import static android.os.PowerWhitelistManager.REASON_ACTIVITY_STARTER;
-import static android.os.PowerWhitelistManager.REASON_ALLOWLISTED_PACKAGE;
-import static android.os.PowerWhitelistManager.REASON_BACKGROUND_ACTIVITY_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_BACKGROUND_FGS_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_COMPANION_DEVICE_MANAGER;
-import static android.os.PowerWhitelistManager.REASON_DENIED;
-import static android.os.PowerWhitelistManager.REASON_DEVICE_DEMO_MODE;
-import static android.os.PowerWhitelistManager.REASON_DEVICE_OWNER;
-import static android.os.PowerWhitelistManager.REASON_FGS_BINDING;
-import static android.os.PowerWhitelistManager.REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_INSTR_BACKGROUND_FGS_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_PROC_STATE_PERSISTENT;
-import static android.os.PowerWhitelistManager.REASON_PROC_STATE_PERSISTENT_UI;
-import static android.os.PowerWhitelistManager.REASON_PROC_STATE_TOP;
-import static android.os.PowerWhitelistManager.REASON_PROFILE_OWNER;
-import static android.os.PowerWhitelistManager.REASON_START_ACTIVITY_FLAG;
-import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALLOW_LISTED;
-import static android.os.PowerWhitelistManager.REASON_SYSTEM_UID;
-import static android.os.PowerWhitelistManager.REASON_UID_VISIBLE;
-import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
-import static android.os.PowerWhitelistManager.getReasonCodeFromProcState;
-import static android.os.PowerWhitelistManager.reasonCodeToString;
+import static android.os.PowerExemptionManager.REASON_UID_VISIBLE;
+import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.os.PowerExemptionManager.getReasonCodeFromProcState;
+import static android.os.PowerExemptionManager.reasonCodeToString;
import static android.os.Process.INVALID_UID;
import static android.os.Process.NFC_UID;
import static android.os.Process.ROOT_UID;
@@ -118,8 +120,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
-import android.os.PowerWhitelistManager;
-import android.os.PowerWhitelistManager.ReasonCode;
+import android.os.PowerExemptionManager.ReasonCode;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
@@ -135,6 +136,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
+import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
@@ -3614,8 +3616,9 @@
+ " for fg-service launch");
}
mAm.tempAllowlistUidLocked(r.appInfo.uid,
- SERVICE_START_FOREGROUND_TIMEOUT, PowerWhitelistManager.REASON_SERVICE_LAUNCH,
- "fg-service-launch", TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+ SERVICE_START_FOREGROUND_TIMEOUT, REASON_SERVICE_LAUNCH,
+ "fg-service-launch",
+ TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
r.mRecentCallingUid);
}
@@ -5740,6 +5743,66 @@
int ret = shouldAllowFgsStartForegroundLocked(allowWhileInUse, callingPid, callingUid,
callingPackage, r);
+ String bindFromPackage = null;
+ if (ret == REASON_DENIED) {
+ // If the callingUid is not allowed to start FGS, check if the callingUid has any
+ // service that is bound by a clientUid, the clientUid can propagate its BG-FGS-start
+ // capability down to the callingUid.
+ final ArraySet<Integer> checkedClientUids = new ArraySet<>();
+ final Pair<Integer, String> isAllowed = mAm.mProcessList.searchEachLruProcessesLOSP(
+ false, pr -> {
+ if (pr.uid == callingUid) {
+ final ProcessServiceRecord psr = pr.mServices;
+ final int serviceCount = psr.mServices.size();
+ for (int svc = 0; svc < serviceCount; svc++) {
+ final ArrayMap<IBinder, ArrayList<ConnectionRecord>> conns =
+ psr.mServices.valueAt(svc).getConnections();
+ final int size = conns.size();
+ for (int conni = 0; conni < size; conni++) {
+ final ArrayList<ConnectionRecord> crs = conns.valueAt(conni);
+ for (int con = 0; con < crs.size(); con++) {
+ final ConnectionRecord cr = crs.get(con);
+ final ProcessRecord clientPr = cr.binding.client;
+ // Persistent process does not propagate BG-FGS-start capability
+ // down to service over binding.
+ if (clientPr.mState.getCurProcState()
+ <= PROCESS_STATE_PERSISTENT_UI) {
+ continue;
+ }
+ final int clientPid = clientPr.mPid;
+ final int clientUid = clientPr.uid;
+ // An UID can bind to itself, do not check on itself again.
+ // Also skip already checked clientUid.
+ if (clientUid == callingUid
+ || checkedClientUids.contains(clientUid)) {
+ continue;
+ }
+ final String clientPackageName = cr.clientPackageName;
+ final @ReasonCode int allowWhileInUse2 =
+ shouldAllowFgsWhileInUsePermissionLocked(clientPackageName,
+ clientPid, clientUid, null /* serviceRecord */,
+ false /* allowBackgroundActivityStarts */);
+ final @ReasonCode int allowStartFgs =
+ shouldAllowFgsStartForegroundLocked(allowWhileInUse2,
+ clientPid, clientUid, clientPackageName, null /* targetService */);
+ if (allowStartFgs != REASON_DENIED) {
+ return new Pair<>(allowStartFgs, clientPackageName);
+ } else {
+ checkedClientUids.add(clientUid);
+ }
+
+ }
+ }
+ }
+ }
+ return null;
+ });
+ if (isAllowed != null) {
+ ret = REASON_FGS_BINDING;
+ bindFromPackage = isAllowed.second;
+ }
+ }
+
final int uidState = mAm.getUidStateLocked(callingUid);
int callerTargetSdkVersion = INVALID_UID;
try {
@@ -5765,6 +5828,7 @@
+ "; targetSdkVersion:" + r.appInfo.targetSdkVersion
+ "; callerTargetSdkVersion:" + callerTargetSdkVersion
+ "; startForegroundCount:" + r.mStartForegroundCount
+ + "; bindFromPackage:" + bindFromPackage
+ "]";
if (!debugInfo.equals(r.mInfoAllowStartForeground)) {
r.mLoggedInfoAllowStartForeground = false;
@@ -5790,9 +5854,7 @@
final Integer allowedType = mAm.mProcessList.searchEachLruProcessesLOSP(false, app -> {
if (app.uid == callingUid) {
final ProcessStateRecord state = app.mState;
- if (state.getAllowedStartFgs() != REASON_DENIED) {
- return state.getAllowedStartFgs();
- } else if (state.isAllowedStartFgsState()) {
+ if (state.isAllowedStartFgsState()) {
return getReasonCodeFromProcState(state.getAllowStartFgsState());
} else if (state.areBackgroundFgsStartsAllowedByToken()) {
return REASON_FGS_BINDING;
@@ -5891,6 +5953,7 @@
}
if (ret == REASON_DENIED) {
if (mAm.mConstants.mFgsAllowOptOut
+ && targetService != null
&& targetService.appInfo.hasRequestForegroundServiceExemption()) {
ret = REASON_OPT_OUT_REQUESTED;
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 85e8315..6cb374a 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -139,7 +139,7 @@
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE)
.replaceWith("?");
- private static final int MAX_LOW_POWER_STATS_SIZE = 8192;
+ private static final int MAX_LOW_POWER_STATS_SIZE = 16384;
private static final int POWER_STATS_QUERY_TIMEOUT_MILLIS = 2000;
private static final String EMPTY = "Empty";
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index f32423f..b325ea3 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -159,6 +159,10 @@
DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.MAGNIFIER_ASPECT_RATIO,
WidgetFlags.KEY_MAGNIFIER_ASPECT_RATIO, float.class,
WidgetFlags.MAGNIFIER_ASPECT_RATIO_DEFAULT));
+ sDeviceConfigEntries.add(new DeviceConfigEntry<>(
+ DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ANALOG_CLOCK_SECONDS_HAND_FPS,
+ WidgetFlags.KEY_ANALOG_CLOCK_SECONDS_HAND_FPS, int.class,
+ WidgetFlags.ANALOG_CLOCK_SECONDS_HAND_FPS_DEFAULT));
// add other device configs here...
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 2e2a297..661e0b8 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -42,7 +42,6 @@
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
-import static android.os.PowerWhitelistManager.REASON_DENIED;
import static android.os.Process.SCHED_OTHER;
import static android.os.Process.THREAD_GROUP_BACKGROUND;
import static android.os.Process.THREAD_GROUP_DEFAULT;
@@ -1574,8 +1573,7 @@
state.setAdjTarget(null);
state.setEmpty(false);
state.setCached(false);
- state.setAllowStartFgsState(PROCESS_STATE_NONEXISTENT);
- state.resetAllowStartFgs();
+ state.resetAllowStartFgsState();
app.mOptRecord.setShouldNotFreeze(false);
final int appUid = app.info.uid;
@@ -1630,7 +1628,6 @@
state.setCurAdj(state.getMaxAdj());
state.setCompletedAdjSeq(state.getAdjSeq());
state.bumpAllowStartFgsState(state.getCurProcState());
- state.setAllowStartFgs();
// if curAdj is less than prevAppAdj, then this process was promoted
return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState;
}
@@ -2028,12 +2025,6 @@
final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP;
- // pass client's mAllowStartFgs to the app if client is not persistent process.
- if (cstate.getAllowedStartFgs() != REASON_DENIED
- && cstate.getMaxAdj() >= ProcessList.FOREGROUND_APP_ADJ) {
- state.setAllowStartFgs(cstate.getAllowedStartFgs());
- }
-
if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
if (shouldSkipDueToCycle(state, cstate, procState, adj, cycleReEval)) {
continue;
@@ -2524,7 +2515,6 @@
state.updateLastInvisibleTime(hasVisibleActivities);
state.setHasForegroundActivities(foregroundActivities);
state.setCompletedAdjSeq(mAdjSeq);
- state.setAllowStartFgs();
// if curAdj or curProcState improved, then this process was promoted
return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState
diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java
index 5c3bf60..8f77b87 100644
--- a/services/core/java/com/android/server/am/ProcessServiceRecord.java
+++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java
@@ -89,7 +89,7 @@
/**
* All ServiceRecord running in this process.
*/
- private final ArraySet<ServiceRecord> mServices = new ArraySet<>();
+ final ArraySet<ServiceRecord> mServices = new ArraySet<>();
/**
* Services that are currently executing code (need to remain foreground).
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index 801e382..d83e13c 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -16,28 +16,9 @@
package com.android.server.am;
-import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
-import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND;
-import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.os.PowerWhitelistManager.REASON_BACKGROUND_ACTIVITY_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_BACKGROUND_FGS_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_DENIED;
-import static android.os.PowerWhitelistManager.REASON_DEVICE_OWNER;
-import static android.os.PowerWhitelistManager.REASON_PROFILE_OWNER;
-import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALLOW_LISTED;
-import static android.os.PowerWhitelistManager.REASON_SYSTEM_UID;
-import static android.os.PowerWhitelistManager.ReasonCode;
-import static android.os.PowerWhitelistManager.getReasonCodeFromProcState;
-import static android.os.PowerWhitelistManager.reasonCodeToString;
-import static android.os.Process.NFC_UID;
-import static android.os.Process.ROOT_UID;
-import static android.os.Process.SHELL_UID;
-import static android.os.Process.SYSTEM_UID;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
import static com.android.server.am.ProcessRecord.TAG;
@@ -47,7 +28,6 @@
import android.content.ComponentName;
import android.os.Binder;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Slog;
import android.util.TimeUtils;
@@ -56,7 +36,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.FrameworkStatsLog;
-
import java.io.PrintWriter;
/**
@@ -327,20 +306,6 @@
private final ArraySet<Binder> mBackgroundFgsStartTokens = new ArraySet<>();
/**
- * Does the process has permission to start FGS from background.
- */
- @GuardedBy("mService")
- private @ReasonCode int mAllowStartFgsByPermission = REASON_DENIED;
-
- /**
- * Can this process start FGS from background?
- * If this process has the ability to start FGS from background, this ability can be passed to
- * another process through service binding.
- */
- @GuardedBy("mService")
- private @ReasonCode int mAllowStartFgs = REASON_DENIED;
-
- /**
* Whether or not this process has been in forced-app-standby state.
*/
@GuardedBy("mService")
@@ -435,7 +400,6 @@
mApp = app;
mService = app.mService;
mProcLock = mService.mProcLock;
- setAllowStartFgsByPermission();
}
void init(long now) {
@@ -1152,9 +1116,8 @@
}
@GuardedBy("mService")
- void resetAllowStartFgs() {
+ void resetAllowStartFgsState() {
mAllowStartFgsState = PROCESS_STATE_NONEXISTENT;
- mAllowStartFgs = mAllowStartFgsByPermission;
}
@GuardedBy("mService")
@@ -1165,11 +1128,6 @@
}
@GuardedBy("mService")
- void setAllowStartFgsState(int allowStartFgsState) {
- mAllowStartFgsState = allowStartFgsState;
- }
-
- @GuardedBy("mService")
int getAllowStartFgsState() {
return mAllowStartFgsState;
}
@@ -1180,98 +1138,6 @@
}
@GuardedBy("mService")
- void setAllowStartFgsByPermission() {
- int ret = REASON_DENIED;
- boolean isSystem = false;
- final int uid = UserHandle.getAppId(mApp.info.uid);
- switch (uid) {
- case ROOT_UID:
- case SYSTEM_UID:
- case NFC_UID:
- case SHELL_UID:
- isSystem = true;
- break;
- default:
- isSystem = false;
- break;
- }
-
- if (isSystem) {
- ret = REASON_SYSTEM_UID;
- }
-
- if (ret == REASON_DENIED) {
- if (ActivityManager.checkComponentPermission(START_ACTIVITIES_FROM_BACKGROUND,
- mApp.info.uid, -1, true) == PERMISSION_GRANTED) {
- ret = REASON_BACKGROUND_ACTIVITY_PERMISSION;
- } else if (ActivityManager.checkComponentPermission(
- START_FOREGROUND_SERVICES_FROM_BACKGROUND,
- mApp.info.uid, -1, true) == PERMISSION_GRANTED) {
- ret = REASON_BACKGROUND_FGS_PERMISSION;
- } else if (ActivityManager.checkComponentPermission(SYSTEM_ALERT_WINDOW,
- mApp.info.uid, -1, true) == PERMISSION_GRANTED) {
- ret = REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
- }
- }
- mAllowStartFgs = mAllowStartFgsByPermission = ret;
- }
-
- // TODO(b/188063200) Clean up this method. Why do we need to duplicate only some of the checks?
- @GuardedBy("mService")
- void setAllowStartFgs() {
- if (mAllowStartFgs != REASON_DENIED) {
- return;
- }
- if (mAllowStartFgs == REASON_DENIED) {
- if (isAllowedStartFgsState()) {
- mAllowStartFgs = getReasonCodeFromProcState(mAllowStartFgsState);
- }
- }
-
- if (mAllowStartFgs == REASON_DENIED) {
- // Is the calling UID a device owner app?
- if (mService.mInternal != null) {
- if (mService.mInternal.isDeviceOwner(mApp.info.uid)) {
- mAllowStartFgs = REASON_DEVICE_OWNER;
- }
- }
- }
-
- if (mAllowStartFgs == REASON_DENIED) {
- // Is the calling UID a profile owner app?
- if (mService.mInternal != null) {
- if (mService.mInternal.isProfileOwner(mApp.info.uid)) {
- mAllowStartFgs = REASON_PROFILE_OWNER;
- }
- }
- }
-
- if (mAllowStartFgs == REASON_DENIED) {
- // uid is on DeviceIdleController's user/system allowlist
- // or AMS's FgsStartTempAllowList.
- ActivityManagerService.FgsTempAllowListItem item =
- mService.isAllowlistedForFgsStartLOSP(mApp.info.uid);
- if (item != null) {
- if (item == ActivityManagerService.FAKE_TEMP_ALLOW_LIST_ITEM) {
- mAllowStartFgs = REASON_SYSTEM_ALLOW_LISTED;
- } else {
- mAllowStartFgs = item.mReasonCode;
- }
- }
- }
- }
-
- @GuardedBy("mService")
- void setAllowStartFgs(@ReasonCode int allowStartFgs) {
- mAllowStartFgs = allowStartFgs;
- }
-
- @GuardedBy("mService")
- @ReasonCode int getAllowedStartFgs() {
- return mAllowStartFgs;
- }
-
- @GuardedBy("mService")
void setForcedAppStandby(boolean standby) {
mForcedAppStandby = standby;
}
@@ -1334,10 +1200,6 @@
pw.println();
pw.print(prefix); pw.print("allowStartFgsState=");
pw.println(mAllowStartFgsState);
- if (mAllowStartFgs != REASON_DENIED) {
- pw.print(prefix); pw.print("allowStartFgs=");
- pw.println(reasonCodeToString(mAllowStartFgs));
- }
if (mHasShownUi || mApp.mProfile.hasPendingUiClean()) {
pw.print(prefix); pw.print("hasShownUi="); pw.print(mHasShownUi);
pw.print(" pendingUiClean="); pw.println(mApp.mProfile.hasPendingUiClean());
diff --git a/services/core/java/com/android/server/biometrics/BiometricStrengthController.java b/services/core/java/com/android/server/biometrics/BiometricStrengthController.java
index 270621c..768dc36 100644
--- a/services/core/java/com/android/server/biometrics/BiometricStrengthController.java
+++ b/services/core/java/com/android/server/biometrics/BiometricStrengthController.java
@@ -48,16 +48,9 @@
*/
private static final String KEY_BIOMETRIC_STRENGTHS = "biometric_strengths";
- /**
- * Default (no-op) value of the flag KEY_BIOMETRIC_STRENGTHS
- */
- public static final String DEFAULT_BIOMETRIC_STRENGTHS = null;
-
private DeviceConfig.OnPropertiesChangedListener mDeviceConfigListener = properties -> {
- for (String name : properties.getKeyset()) {
- if (KEY_BIOMETRIC_STRENGTHS.equals(name)) {
- updateStrengths();
- }
+ if (properties.getKeyset().contains(KEY_BIOMETRIC_STRENGTHS)) {
+ updateStrengths();
}
};
@@ -75,7 +68,17 @@
* has been changed.
*/
public void updateStrengths() {
- final Map<Integer, Integer> idToStrength = getIdToStrengthMap();
+ final String newValue = DeviceConfig.getString(DeviceConfig.NAMESPACE_BIOMETRICS,
+ KEY_BIOMETRIC_STRENGTHS, "null");
+ if ("null".equals(newValue) || newValue.isEmpty()) {
+ revertStrengths();
+ } else {
+ updateStrengths(newValue);
+ }
+ }
+
+ private void updateStrengths(String flags) {
+ final Map<Integer, Integer> idToStrength = getIdToStrengthMap(flags);
if (idToStrength == null) {
return;
}
@@ -91,12 +94,18 @@
}
}
+ private void revertStrengths() {
+ for (BiometricSensor sensor : mService.mSensors) {
+ Slog.d(TAG, "updateStrengths: revert sensorId=" + sensor.id + " to oemStrength="
+ + sensor.oemStrength);
+ sensor.updateStrength(sensor.oemStrength);
+ }
+ }
+
/**
* @return a map of <ID, Strength>
*/
- private Map<Integer, Integer> getIdToStrengthMap() {
- final String flags = DeviceConfig.getString(DeviceConfig.NAMESPACE_BIOMETRICS,
- KEY_BIOMETRIC_STRENGTHS, DEFAULT_BIOMETRIC_STRENGTHS);
+ private static Map<Integer, Integer> getIdToStrengthMap(String flags) {
if (flags == null || flags.isEmpty()) {
Slog.d(TAG, "Flags are null or empty");
return null;
diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
index 6482a2e..99f4e2c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
@@ -82,7 +82,20 @@
private final int mCookie;
boolean mAlreadyDone;
- @NonNull protected Callback mCallback;
+ // Use an empty callback by default since delayed operations can receive events
+ // before they are started and cause NPE in subclasses that access this field directly.
+ @NonNull protected Callback mCallback = new Callback() {
+ @Override
+ public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
+ Slog.e(TAG, "mCallback onClientStarted: called before set (should not happen)");
+ }
+
+ @Override
+ public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
+ boolean success) {
+ Slog.e(TAG, "mCallback onClientFinished: called before set (should not happen)");
+ }
+ };
/**
* @return A ClientMonitorEnum constant defined in biometrics.proto
diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java
index d29a0c7..0f97b90 100644
--- a/services/core/java/com/android/server/compat/CompatChange.java
+++ b/services/core/java/com/android/server/compat/CompatChange.java
@@ -26,9 +26,7 @@
import android.compat.annotation.Disabled;
import android.compat.annotation.EnabledSince;
import android.compat.annotation.Overridable;
-import android.content.Context;
import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
import com.android.internal.compat.AndroidBuildClassifier;
import com.android.internal.compat.CompatibilityChangeInfo;
@@ -161,15 +159,17 @@
*
* @param packageName Package name to tentatively enable the change for.
* @param override The package override to be set
+ * @param allowedState Whether the override is allowed.
+ * @param versionCode The version code of the package.
*/
void addPackageOverride(String packageName, PackageOverride override,
- OverrideAllowedState allowedState, Context context) {
+ OverrideAllowedState allowedState, @Nullable Long versionCode) {
if (getLoggingOnly()) {
throw new IllegalArgumentException(
"Can't add overrides for a logging only change " + toString());
}
mRawOverrides.put(packageName, override);
- recheckOverride(packageName, allowedState, context);
+ recheckOverride(packageName, allowedState, versionCode);
}
/**
@@ -179,32 +179,24 @@
* overrides, check if they need to be demoted to deferred.</p>
*
* @param packageName Package name to apply deferred overrides for.
- * @param allowed Whether the override is allowed.
+ * @param allowedState Whether the override is allowed.
+ * @param versionCode The version code of the package.
*
* @return {@code true} if the recheck yielded a result that requires invalidating caches
* (a deferred override was consolidated or a regular override was removed).
*/
boolean recheckOverride(String packageName, OverrideAllowedState allowedState,
- Context context) {
+ @Nullable Long versionCode) {
boolean allowed = (allowedState.state == OverrideAllowedState.ALLOWED);
- Long version = null;
- try {
- ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo(
- packageName, 0);
- version = applicationInfo.longVersionCode;
- } catch (PackageManager.NameNotFoundException e) {
- // Do nothing
- }
-
// If the app is not installed or no longer has raw overrides, evaluate to false
- if (version == null || !hasRawOverride(packageName) || !allowed) {
+ if (versionCode == null || !hasRawOverride(packageName) || !allowed) {
removePackageOverrideInternal(packageName);
return false;
}
// Evaluate the override based on its version
- int overrideValue = mRawOverrides.get(packageName).evaluate(version);
+ int overrideValue = mRawOverrides.get(packageName).evaluate(versionCode);
switch (overrideValue) {
case VALUE_UNDEFINED:
removePackageOverrideInternal(packageName);
@@ -229,11 +221,13 @@
* <p>Note, this method is not thread safe so callers must ensure thread safety.
*
* @param pname Package name to reset to defaults for.
+ * @param allowedState Whether the override is allowed.
+ * @param versionCode The version code of the package.
*/
boolean removePackageOverride(String pname, OverrideAllowedState allowedState,
- Context context) {
+ @Nullable Long versionCode) {
if (mRawOverrides.remove(pname) != null) {
- recheckOverride(pname, allowedState, context);
+ recheckOverride(pname, allowedState, versionCode);
return true;
}
return false;
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index 9247568..909ed11 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -16,11 +16,13 @@
package com.android.server.compat;
+import android.annotation.Nullable;
import android.app.compat.ChangeIdStateCache;
import android.app.compat.PackageOverride;
import android.compat.Compatibility.ChangeConfig;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.os.Environment;
import android.text.TextUtils;
import android.util.LongArray;
@@ -51,7 +53,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
-import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -249,6 +250,7 @@
OverrideAllowedState allowedState =
mOverrideValidator.getOverrideAllowedState(changeId, packageName);
allowedState.enforce(changeId, packageName);
+ Long versionCode = getVersionCodeOrNull(packageName);
synchronized (mChanges) {
CompatChange c = mChanges.get(changeId);
if (c == null) {
@@ -256,7 +258,7 @@
c = new CompatChange(changeId);
addChange(c);
}
- c.addPackageOverride(packageName, overrides, allowedState, mContext);
+ c.addPackageOverride(packageName, overrides, allowedState, versionCode);
invalidateCache();
}
return alreadyKnown;
@@ -336,6 +338,7 @@
* It does not invalidate the cache nor save the overrides.
*/
private boolean removeOverrideUnsafe(long changeId, String packageName) {
+ Long versionCode = getVersionCodeOrNull(packageName);
synchronized (mChanges) {
CompatChange c = mChanges.get(changeId);
if (c != null) {
@@ -343,7 +346,7 @@
mOverrideValidator.getOverrideAllowedState(changeId, packageName);
if (c.hasPackageOverride(packageName)) {
allowedState.enforce(changeId, packageName);
- c.removePackageOverride(packageName, allowedState, mContext);
+ c.removePackageOverride(packageName, allowedState, versionCode);
invalidateCache();
return true;
}
@@ -653,26 +656,33 @@
* Rechecks all the existing overrides for a package.
*/
void recheckOverrides(String packageName) {
- // Local cache of compat changes. Holding a lock on mChanges for the whole duration of the
- // method will cause a deadlock.
- List<CompatChange> changes;
+ Long versionCode = getVersionCodeOrNull(packageName);
synchronized (mChanges) {
- changes = new ArrayList<>(mChanges.size());
+ boolean shouldInvalidateCache = false;
for (int idx = 0; idx < mChanges.size(); ++idx) {
- changes.add(mChanges.valueAt(idx));
+ CompatChange c = mChanges.valueAt(idx);
+ if (!c.hasPackageOverride(packageName)) {
+ continue;
+ }
+ OverrideAllowedState allowedState =
+ mOverrideValidator.getOverrideAllowedStateForRecheck(c.getId(),
+ packageName);
+ shouldInvalidateCache |= c.recheckOverride(packageName, allowedState, versionCode);
+ }
+ if (shouldInvalidateCache) {
+ invalidateCache();
}
}
- boolean shouldInvalidateCache = false;
- for (CompatChange c: changes) {
- if (!c.hasPackageOverride(packageName)) {
- continue;
- }
- OverrideAllowedState allowedState =
- mOverrideValidator.getOverrideAllowedStateForRecheck(c.getId(), packageName);
- shouldInvalidateCache |= c.recheckOverride(packageName, allowedState, mContext);
- }
- if (shouldInvalidateCache) {
- invalidateCache();
+ }
+
+ @Nullable
+ private Long getVersionCodeOrNull(String packageName) {
+ try {
+ ApplicationInfo applicationInfo = mContext.getPackageManager().getApplicationInfo(
+ packageName, 0);
+ return applicationInfo.longVersionCode;
+ } catch (PackageManager.NameNotFoundException e) {
+ return null;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c947463..14861c2d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -780,7 +780,6 @@
private static final String COMPANION_PACKAGE_NAME = "com.android.companiondevicemanager";
// Compilation reasons.
- public static final int REASON_UNKNOWN = -1;
public static final int REASON_FIRST_BOOT = 0;
public static final int REASON_BOOT_AFTER_OTA = 1;
public static final int REASON_POST_BOOT = 2;
@@ -793,7 +792,8 @@
public static final int REASON_BACKGROUND_DEXOPT = 9;
public static final int REASON_AB_OTA = 10;
public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 11;
- public static final int REASON_SHARED = 12;
+ public static final int REASON_CMDLINE = 12;
+ public static final int REASON_SHARED = 13;
public static final int REASON_LAST = REASON_SHARED;
@@ -8472,7 +8472,7 @@
libInfo.getPackageName(), libInfo.getAllCodePaths(),
libInfo.getName(), libInfo.getLongVersion(),
libInfo.getType(), libInfo.getDeclaringPackage(),
- getPackagesUsingSharedLibraryLPr(libInfo, flags, userId),
+ getPackagesUsingSharedLibraryLPr(libInfo, flags, callingUid, userId),
(libInfo.getDependencies() == null
? null
: new ArrayList<>(libInfo.getDependencies())),
@@ -8544,9 +8544,11 @@
libraryInfo.getPath(), libraryInfo.getPackageName(),
libraryInfo.getAllCodePaths(), libraryInfo.getName(),
libraryInfo.getLongVersion(), libraryInfo.getType(),
- libraryInfo.getDeclaringPackage(), getPackagesUsingSharedLibraryLPr(
- libraryInfo, flags, userId), libraryInfo.getDependencies() == null
- ? null : new ArrayList<>(libraryInfo.getDependencies()),
+ libraryInfo.getDeclaringPackage(),
+ getPackagesUsingSharedLibraryLPr(
+ libraryInfo, flags, callingUid, userId),
+ libraryInfo.getDependencies() == null
+ ? null : new ArrayList<>(libraryInfo.getDependencies()),
libraryInfo.isNative());
if (result == null) {
@@ -8562,7 +8564,7 @@
@GuardedBy("mLock")
private List<VersionedPackage> getPackagesUsingSharedLibraryLPr(
- SharedLibraryInfo libInfo, int flags, int userId) {
+ SharedLibraryInfo libInfo, int flags, int callingUid, int userId) {
List<VersionedPackage> versionedPackages = null;
final int packageCount = mSettings.getPackagesLocked().size();
for (int i = 0; i < packageCount; i++) {
@@ -8585,6 +8587,9 @@
if (ps.usesStaticLibrariesVersions[libIdx] != libInfo.getLongVersion()) {
continue;
}
+ if (shouldFilterApplicationLocked(ps, callingUid, userId)) {
+ continue;
+ }
if (versionedPackages == null) {
versionedPackages = new ArrayList<>();
}
@@ -8597,6 +8602,9 @@
} else if (ps.pkg != null) {
if (ArrayUtils.contains(ps.pkg.getUsesLibraries(), libName)
|| ArrayUtils.contains(ps.pkg.getUsesOptionalLibraries(), libName)) {
+ if (shouldFilterApplicationLocked(ps, callingUid, userId)) {
+ continue;
+ }
if (versionedPackages == null) {
versionedPackages = new ArrayList<>();
}
@@ -11942,7 +11950,7 @@
int flags = (checkProfiles ? DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES : 0) |
(force ? DexoptOptions.DEXOPT_FORCE : 0) |
(bootComplete ? DexoptOptions.DEXOPT_BOOT_COMPLETE : 0);
- return performDexOpt(new DexoptOptions(packageName, REASON_UNKNOWN,
+ return performDexOpt(new DexoptOptions(packageName, REASON_CMDLINE,
targetCompilerFilter, splitName, flags));
}
@@ -14321,7 +14329,7 @@
// Remove the shared library overlays from its dependent packages.
for (int currentUserId : UserManagerService.getInstance().getUserIds()) {
final List<VersionedPackage> dependents = getPackagesUsingSharedLibraryLPr(
- libraryInfo, 0, currentUserId);
+ libraryInfo, 0, Process.SYSTEM_UID, currentUserId);
if (dependents == null) {
continue;
}
@@ -20684,7 +20692,7 @@
continue;
}
List<VersionedPackage> libClientPackages = getPackagesUsingSharedLibraryLPr(
- libraryInfo, MATCH_KNOWN_PACKAGES, currUserId);
+ libraryInfo, MATCH_KNOWN_PACKAGES, Process.SYSTEM_UID, currUserId);
if (!ArrayUtils.isEmpty(libClientPackages)) {
Slog.w(TAG, "Not removing package " + pkg.getManifestPackageName()
+ " hosting lib " + libraryInfo.getName() + " version "
@@ -26795,7 +26803,7 @@
continue;
}
final List<VersionedPackage> dependents = getPackagesUsingSharedLibraryLPr(
- info, 0, userId);
+ info, 0, Process.SYSTEM_UID, userId);
if (dependents == null) {
continue;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
index 636db11..7c1f054 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
@@ -40,6 +40,7 @@
"bg-dexopt",
"ab-ota",
"inactive",
+ "cmdline",
// "shared" must be the last entry
"shared"
};
@@ -141,9 +142,6 @@
}
public static String getReasonName(int reason) {
- if (reason == PackageManagerService.REASON_UNKNOWN) {
- return "unknown";
- }
if (reason < 0 || reason >= REASON_STRINGS.length) {
throw new IllegalArgumentException("reason " + reason + " invalid");
}
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index 3576950..1859b4c 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -607,6 +607,7 @@
TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED_WITH_DM = 19;
private static final int TRON_COMPILATION_REASON_BOOT_AFTER_OTA = 20;
private static final int TRON_COMPILATION_REASON_POST_BOOT = 21;
+ private static final int TRON_COMPILATION_REASON_CMDLINE = 22;
// The annotation to add as a suffix to the compilation reason when dexopt was
// performed with dex metadata.
@@ -617,7 +618,7 @@
*/
private static int getCompilationReasonTronValue(String compilationReason) {
switch (compilationReason) {
- case "unknown" : return TRON_COMPILATION_REASON_UNKNOWN;
+ case "cmdline" : return TRON_COMPILATION_REASON_CMDLINE;
case "error" : return TRON_COMPILATION_REASON_ERROR;
case "first-boot" : return TRON_COMPILATION_REASON_FIRST_BOOT;
case "boot-after-ota": return TRON_COMPILATION_REASON_BOOT_AFTER_OTA;
diff --git a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
index 091d820..946f8d5 100644
--- a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
+++ b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
@@ -58,8 +58,6 @@
private static final Map<Integer, Integer> COMPILATION_REASON_MAP = new HashMap();
static {
- COMPILATION_REASON_MAP.put(PackageManagerService.REASON_UNKNOWN, ArtStatsLog.
- ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_UNKNOWN);
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_FIRST_BOOT, ArtStatsLog.
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_FIRST_BOOT);
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_BOOT_AFTER_OTA, ArtStatsLog.
@@ -85,6 +83,8 @@
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE,
ArtStatsLog.
ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INACTIVE);
+ COMPILATION_REASON_MAP.put(PackageManagerService.REASON_CMDLINE,
+ ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_CMDLINE);
COMPILATION_REASON_MAP.put(PackageManagerService.REASON_SHARED,
ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_SHARED);
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 065dc6e..38966b9 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
@@ -90,7 +89,6 @@
import static android.content.pm.ActivityInfo.SIZE_CHANGES_UNSUPPORTED_OVERRIDE;
import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.res.Configuration.ASSETS_SEQ_UNDEFINED;
import static android.content.res.Configuration.EMPTY;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
@@ -279,7 +277,6 @@
import android.os.Trace;
import android.os.UserHandle;
import android.os.storage.StorageManager;
-import android.permission.PermissionManager;
import android.service.dreams.DreamActivity;
import android.service.dreams.DreamManagerInternal;
import android.service.voice.IVoiceInteractionSession;
@@ -7457,11 +7454,9 @@
@Override
public boolean providesMaxBounds() {
- // System and SystemUI should always be able to access the physical display bounds,
- // so do not provide it with the overridden maximum bounds.
- // TODO(b/179179513) check WindowState#mOwnerCanAddInternalSystemWindow instead
- if (getUid() == SYSTEM_UID || PermissionManager.checkPermission(INTERNAL_SYSTEM_WINDOW,
- getPid(), info.applicationInfo.uid) == PERMISSION_GRANTED) {
+ // System should always be able to access the DisplayArea bounds, so do not provide it with
+ // compat max window bounds.
+ if (getUid() == SYSTEM_UID) {
return false;
}
// Do not sandbox to activity window bounds if the feature is disabled.
diff --git a/services/core/java/com/android/server/wm/BlurController.java b/services/core/java/com/android/server/wm/BlurController.java
index ff10168..0363944 100644
--- a/services/core/java/com/android/server/wm/BlurController.java
+++ b/services/core/java/com/android/server/wm/BlurController.java
@@ -29,6 +29,7 @@
import android.os.RemoteException;
import android.provider.Settings;
import android.view.ICrossWindowBlurEnabledListener;
+import android.view.TunnelModeEnabledListener;
/**
* Keeps track of the different factors that determine whether cross-window blur is enabled
@@ -45,6 +46,16 @@
private volatile boolean mBlurEnabled;
private boolean mInPowerSaveMode;
private boolean mBlurDisabledSetting;
+ private boolean mTunnelModeEnabled = false;
+
+ private TunnelModeEnabledListener mTunnelModeListener =
+ new TunnelModeEnabledListener(Runnable::run) {
+ @Override
+ public void onTunnelModeEnabledChanged(boolean tunnelModeEnabled) {
+ mTunnelModeEnabled = tunnelModeEnabled;
+ updateBlurEnabled();
+ }
+ };
BlurController(Context context, PowerManager powerManager) {
mContext = context;
@@ -78,6 +89,8 @@
});
mBlurDisabledSetting = getBlurDisabledSetting();
+ TunnelModeEnabledListener.register(mTunnelModeListener);
+
updateBlurEnabled();
}
@@ -99,7 +112,7 @@
private void updateBlurEnabled() {
synchronized (mLock) {
final boolean newEnabled = CROSS_WINDOW_BLUR_SUPPORTED && !mBlurDisabledSetting
- && !mInPowerSaveMode;
+ && !mInPowerSaveMode && !mTunnelModeEnabled;
if (mBlurEnabled == newEnabled) {
return;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0251537..7df5744 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8105,11 +8105,10 @@
// This could prevent if there is no container animation, we still have to apply the
// pending transaction and exit waiting.
mAnimator.mNotifyWhenNoAnimation = true;
- WindowContainer animatingContainer = null;
- while (mAnimator.isAnimationScheduled() || timeoutRemaining > 0) {
- animatingContainer = mRoot.getAnimatingContainer(TRANSITION | CHILDREN,
- ANIMATION_TYPE_ALL);
- if (animatingContainer == null) {
+ while (timeoutRemaining > 0) {
+ boolean isAnimating = mAnimator.isAnimationScheduled()
+ || mRoot.isAnimating(TRANSITION | CHILDREN, ANIMATION_TYPE_ALL);
+ if (!isAnimating) {
break;
}
long startTime = System.currentTimeMillis();
@@ -8121,6 +8120,9 @@
}
mAnimator.mNotifyWhenNoAnimation = false;
+ WindowContainer animatingContainer;
+ animatingContainer = mRoot.getAnimatingContainer(TRANSITION | CHILDREN,
+ ANIMATION_TYPE_ALL);
if (mAnimator.isAnimationScheduled() || animatingContainer != null) {
Slog.w(TAG, "Timed out waiting for animations to complete,"
+ " animatingContainer=" + animatingContainer
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index 8d43bbb..ce8f6df 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -1190,7 +1190,7 @@
pw.println(mEnrollmentSpecificId);
}
- pw.print("mAdminCanGrantSensorsPermissions");
+ pw.print("mAdminCanGrantSensorsPermissions=");
pw.println(mAdminCanGrantSensorsPermissions);
pw.print("mUsbDataSignaling=");
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 891ed3d..bc130e2 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -8579,6 +8579,7 @@
final DevicePolicyData policyData = getUserData(userId);
policyData.mCurrentInputMethodSet = false;
saveSettingsLocked(userId);
+ mPolicyCache.onUserRemoved(userId);
final DevicePolicyData systemPolicyData = getUserData(UserHandle.USER_SYSTEM);
systemPolicyData.mLastSecurityLogRetrievalTime = -1;
systemPolicyData.mLastBugReportRequestTime = -1;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ad89e96..d487483 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -103,7 +103,6 @@
import com.android.internal.widget.ILockSettings;
import com.android.server.am.ActivityManagerService;
import com.android.server.appbinding.AppBindingService;
-import com.android.server.art.ArtManagerLocal;
import com.android.server.attention.AttentionManagerService;
import com.android.server.audio.AudioService;
import com.android.server.biometrics.AuthService;
@@ -2632,10 +2631,6 @@
mSystemServiceManager.startService(GAME_MANAGER_SERVICE_CLASS);
t.traceEnd();
- t.traceBegin("ArtManagerLocal");
- LocalManagerRegistry.addManager(ArtManagerLocal.class, new ArtManagerLocal());
- t.traceEnd();
-
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB)) {
t.traceBegin("UwbService");
mSystemServiceManager.startService(UWB_SERVICE_CLASS);
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index 47505a3..e31be82 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -43,6 +43,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.util.EventLog;
import android.util.Log;
import com.android.internal.content.PackageMonitor;
@@ -736,13 +737,19 @@
@Override
public MidiDeviceInfo getServiceDeviceInfo(String packageName, String className) {
+ int uid = Binder.getCallingUid();
synchronized (mDevicesByInfo) {
for (Device device : mDevicesByInfo.values()) {
ServiceInfo serviceInfo = device.getServiceInfo();
if (serviceInfo != null &&
packageName.equals(serviceInfo.packageName) &&
className.equals(serviceInfo.name)) {
- return device.getDeviceInfo();
+ if (device.isUidAllowed(uid)) {
+ return device.getDeviceInfo();
+ } else {
+ EventLog.writeEvent(0x534e4554, "185796676", -1, "");
+ return null;
+ }
}
}
return null;
diff --git a/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java b/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java
index c631026..49d5e50 100644
--- a/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java
+++ b/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java
@@ -20,26 +20,18 @@
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.PendingIntent;
-import android.app.job.JobInfo;
-import android.app.job.JobParameters;
-import android.app.job.JobScheduler;
-import android.app.job.JobService;
import android.app.people.ConversationStatus;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
+import android.os.Binder;
import android.os.CancellationSignal;
-import android.os.SystemClock;
import com.android.server.LocalServices;
-import com.android.server.notification.NotificationRecord;
import com.android.server.people.PeopleServiceInternal;
-import java.util.concurrent.TimeUnit;
-
/**
* If a {@link ConversationStatus} is added to the system with an expiration time, remove that
* status at that time
@@ -53,18 +45,22 @@
void scheduleExpiration(Context context, @UserIdInt int userId, String pkg,
String conversationId, ConversationStatus status) {
-
- final PendingIntent pi = PendingIntent.getBroadcast(context,
- REQUEST_CODE,
- new Intent(ACTION)
- .setData(new Uri.Builder().scheme(SCHEME)
- .appendPath(getKey(userId, pkg, conversationId, status))
- .build())
- .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
- .putExtra(EXTRA_USER_ID, userId),
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
- context.getSystemService(AlarmManager.class).setExactAndAllowWhileIdle(
- AlarmManager.RTC_WAKEUP, status.getEndTimeMillis(), pi);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final PendingIntent pi = PendingIntent.getBroadcast(context,
+ REQUEST_CODE,
+ new Intent(ACTION)
+ .setData(new Uri.Builder().scheme(SCHEME)
+ .appendPath(getKey(userId, pkg, conversationId, status))
+ .build())
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+ .putExtra(EXTRA_USER_ID, userId),
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+ context.getSystemService(AlarmManager.class).setExactAndAllowWhileIdle(
+ AlarmManager.RTC_WAKEUP, status.getEndTimeMillis(), pi);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
private static String getKey(@UserIdInt int userId, String pkg,
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 9be1ac4..2206b0a 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -22,6 +22,7 @@
import static android.app.ActivityManager.START_VOICE_NOT_ACTIVE_SESSION;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -36,7 +37,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
-import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
@@ -414,11 +414,31 @@
Slog.w(TAG, "Hotword detection service name not found");
throw new IllegalStateException("Hotword detection service name not found");
}
- if (!isIsolatedProcessLocked(mHotwordDetectionComponentName)) {
+ ServiceInfo hotwordDetectionServiceInfo = getServiceInfoLocked(
+ mHotwordDetectionComponentName, mUser);
+ if (hotwordDetectionServiceInfo == null) {
+ Slog.w(TAG, "Hotword detection service info not found");
+ throw new IllegalStateException("Hotword detection service info not found");
+ }
+ if (!isIsolatedProcessLocked(hotwordDetectionServiceInfo)) {
Slog.w(TAG, "Hotword detection service not in isolated process");
throw new IllegalStateException("Hotword detection service not in isolated process");
}
- // TODO : Need to check related permissions for hotword detection service
+ if (!Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE.equals(
+ hotwordDetectionServiceInfo.permission)) {
+ Slog.w(TAG, "Hotword detection service does not require permission "
+ + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE);
+ throw new SecurityException("Hotword detection service does not require permission "
+ + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE);
+ }
+ if (mContext.getPackageManager().checkPermission(
+ Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE,
+ mInfo.getServiceInfo().packageName) == PackageManager.PERMISSION_GRANTED) {
+ Slog.w(TAG, "Voice interaction service should not hold permission "
+ + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE);
+ throw new SecurityException("Voice interaction service should not hold permission "
+ + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE);
+ }
if (sharedMemory != null && !sharedMemory.setProtect(OsConstants.PROT_READ)) {
Slog.w(TAG, "Can't set sharedMemory to be read-only");
@@ -522,23 +542,24 @@
mHotwordDetectionConnection);
}
- boolean isIsolatedProcessLocked(ComponentName componentName) {
- IPackageManager pm = AppGlobals.getPackageManager();
+ private static ServiceInfo getServiceInfoLocked(@NonNull ComponentName componentName,
+ int userHandle) {
try {
- ServiceInfo serviceInfo = pm.getServiceInfo(componentName,
+ return AppGlobals.getPackageManager().getServiceInfo(componentName,
PackageManager.GET_META_DATA
| PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, mUser);
- if (serviceInfo != null) {
- return (serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
- && (serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) == 0;
- }
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
} catch (RemoteException e) {
if (DEBUG) {
- Slog.w(TAG, "isIsolatedProcess RemoteException : " + e);
+ Slog.w(TAG, "getServiceInfoLocked RemoteException : " + e);
}
}
- return false;
+ return null;
+ }
+
+ boolean isIsolatedProcessLocked(@NonNull ServiceInfo serviceInfo) {
+ return (serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
+ && (serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) == 0;
}
public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
diff --git a/telecomm/java/android/telecom/CallDiagnosticService.java b/telecomm/java/android/telecom/CallDiagnosticService.java
index 011dc17..336a8ea 100644
--- a/telecomm/java/android/telecom/CallDiagnosticService.java
+++ b/telecomm/java/android/telecom/CallDiagnosticService.java
@@ -294,6 +294,10 @@
CallDiagnostics callDiagnostics;
synchronized (mLock) {
callDiagnostics = mDiagnosticCallByTelecomCallId.get(telecomCallId);
+ if (callDiagnostics == null) {
+ // Possible to get a call update after a call is removed.
+ return;
+ }
mCallByTelecomCallId.put(telecomCallId, newCallDetails);
}
getExecutor().execute(() -> callDiagnostics.handleCallUpdated(newCallDetails));
@@ -306,12 +310,12 @@
private void handleCallRemoved(@NonNull String telecomCallId) {
Log.i(this, "handleCallRemoved: callId=%s - removed", telecomCallId);
- if (mCallByTelecomCallId.containsKey(telecomCallId)) {
- mCallByTelecomCallId.remove(telecomCallId);
- }
-
CallDiagnostics callDiagnostics;
synchronized (mLock) {
+ if (mCallByTelecomCallId.containsKey(telecomCallId)) {
+ mCallByTelecomCallId.remove(telecomCallId);
+ }
+
if (mDiagnosticCallByTelecomCallId.containsKey(telecomCallId)) {
callDiagnostics = mDiagnosticCallByTelecomCallId.remove(telecomCallId);
} else {
@@ -353,7 +357,10 @@
private void handleCallDisconnected(@NonNull String callId,
@NonNull DisconnectCause disconnectCause) {
Log.i(this, "handleCallDisconnected: call=%s; cause=%s", callId, disconnectCause);
- CallDiagnostics callDiagnostics = mDiagnosticCallByTelecomCallId.get(callId);
+ CallDiagnostics callDiagnostics;
+ synchronized (mLock) {
+ callDiagnostics = mDiagnosticCallByTelecomCallId.get(callId);
+ }
CharSequence message;
if (disconnectCause.getImsReasonInfo() != null) {
message = callDiagnostics.onCallDisconnected(disconnectCause.getImsReasonInfo());
@@ -391,7 +398,9 @@
@NonNull CallQuality callQuality) {
Log.i(this, "handleCallQualityChanged; call=%s, cq=%s", callId, callQuality);
CallDiagnostics callDiagnostics;
- callDiagnostics = mDiagnosticCallByTelecomCallId.get(callId);
+ synchronized(mLock) {
+ callDiagnostics = mDiagnosticCallByTelecomCallId.get(callId);
+ }
if (callDiagnostics != null) {
callDiagnostics.onCallQualityReceived(callQuality);
}