Merge "Dismiss keyguard when target user has no password"
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/TareBill.java b/apex/jobscheduler/service/java/com/android/server/alarm/TareBill.java
index e2f5ee1..a348136 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/TareBill.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/TareBill.java
@@ -37,7 +37,7 @@
import java.util.List;
/**
- * Container to maintain alarm TARE {@link ActionBill}s and their related methods.
+ * Container to maintain alarm TARE {@link ActionBill ActionBills} and their related methods.
*/
final class TareBill {
/**
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 714c90b..ef442f0 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -2299,7 +2299,7 @@
}
/**
- * Check if a job is restricted by any of the declared {@link JobRestriction}s.
+ * Check if a job is restricted by any of the declared {@link JobRestriction JobRestrictions}.
* Note, that the jobs with {@link JobInfo#BIAS_FOREGROUND_SERVICE} bias or higher may not
* be restricted, thus we won't even perform the check, but simply return null early.
*
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 29c1108..b02e801 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -148,8 +148,9 @@
public int bgJobCountInMaxPeriod;
/**
- * The number of {@link TimingSession}s within the bucket window size. This will include
- * sessions that started before the window as long as they end within the window.
+ * The number of {@link TimingSession TimingSessions} within the bucket window size.
+ * This will include sessions that started before the window as long as they end within
+ * the window.
*/
public int sessionCountInWindow;
@@ -183,7 +184,7 @@
public long sessionRateLimitExpirationTimeElapsed;
/**
- * The number of {@link TimingSession}s that ran in at least the last
+ * The number of {@link TimingSession TimingSessions} that ran in at least the last
* {@link #mRateLimitingWindowMs}. It may contain a few stale entries since cleanup won't
* happen exactly every {@link #mRateLimitingWindowMs}. This should only be considered
* valid before elapsed realtime has reached {@link #sessionRateLimitExpirationTimeElapsed}.
@@ -363,8 +364,8 @@
QcConstants.DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW;
/**
- * The maximum number of {@link TimingSession}s that can run within the past {@link
- * #mRateLimitingWindowMs}.
+ * The maximum number of {@link TimingSession TimingSessions} that can run within the past
+ * {@link #mRateLimitingWindowMs}.
*/
private int mMaxSessionCountPerRateLimitingWindow =
QcConstants.DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW;
@@ -434,9 +435,10 @@
};
/**
- * The maximum number of {@link TimingSession}s based on its standby bucket. For each max value
- * count in the array, the app will not be allowed to have more than that many number of
- * {@link TimingSession}s within the latest time interval of its rolling window size.
+ * The maximum number of {@link TimingSession TimingSessions} based on its standby bucket.
+ * For each max value count in the array, the app will not be allowed to have more than that
+ * many number of {@link TimingSession TimingSessions} within the latest time interval of its
+ * rolling window size.
*
* @see #mBucketPeriodsMs
*/
@@ -450,8 +452,8 @@
};
/**
- * Treat two distinct {@link TimingSession}s as the same if they start and end within this
- * amount of time of each other.
+ * Treat two distinct {@link TimingSession TimingSessions} as the same if they start and end
+ * within this amount of time of each other.
*/
private long mTimingSessionCoalescingDurationMs =
QcConstants.DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS;
@@ -997,8 +999,8 @@
/**
* Returns the amount of time, in milliseconds, until the package would have reached its
* duration quota, assuming it has a job counting towards its quota the entire time. This takes
- * into account any {@link TimingSession}s that may roll out of the window as the job is
- * running.
+ * into account any {@link TimingSession TimingSessions} that may roll out of the window as the
+ * job is running.
*/
@VisibleForTesting
long getTimeUntilQuotaConsumedLocked(final int userId, @NonNull final String packageName) {
@@ -3073,45 +3075,45 @@
DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW;
/**
- * The maximum number of {@link TimingSession}s an app can run within this particular
- * standby bucket's window size.
+ * The maximum number of {@link TimingSession TimingSessions} an app can run within this
+ * particular standby bucket's window size.
*/
public int MAX_SESSION_COUNT_ACTIVE = DEFAULT_MAX_SESSION_COUNT_ACTIVE;
/**
- * The maximum number of {@link TimingSession}s an app can run within this particular
- * standby bucket's window size.
+ * The maximum number of {@link TimingSession TimingSessions} an app can run within this
+ * particular standby bucket's window size.
*/
public int MAX_SESSION_COUNT_WORKING = DEFAULT_MAX_SESSION_COUNT_WORKING;
/**
- * The maximum number of {@link TimingSession}s an app can run within this particular
- * standby bucket's window size.
+ * The maximum number of {@link TimingSession TimingSessions} an app can run within this
+ * particular standby bucket's window size.
*/
public int MAX_SESSION_COUNT_FREQUENT = DEFAULT_MAX_SESSION_COUNT_FREQUENT;
/**
- * The maximum number of {@link TimingSession}s an app can run within this particular
- * standby bucket's window size.
+ * The maximum number of {@link TimingSession TimingSessions} an app can run within this
+ * particular standby bucket's window size.
*/
public int MAX_SESSION_COUNT_RARE = DEFAULT_MAX_SESSION_COUNT_RARE;
/**
- * The maximum number of {@link TimingSession}s an app can run within this particular
- * standby bucket's window size.
+ * The maximum number of {@link TimingSession TimingSessions} an app can run within this
+ * particular standby bucket's window size.
*/
public int MAX_SESSION_COUNT_RESTRICTED = DEFAULT_MAX_SESSION_COUNT_RESTRICTED;
/**
- * The maximum number of {@link TimingSession}s that can run within the past
+ * The maximum number of {@link TimingSession TimingSessions} that can run within the past
* {@link #ALLOWED_TIME_PER_PERIOD_MS}.
*/
public int MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW =
DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW;
/**
- * Treat two distinct {@link TimingSession}s as the same if they start and end within this
- * amount of time of each other.
+ * Treat two distinct {@link TimingSession TimingSessions} as the same if they start and
+ * end within this amount of time of each other.
*/
public long TIMING_SESSION_COALESCING_DURATION_MS =
DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS;
@@ -3125,8 +3127,8 @@
private static final int MIN_BUCKET_JOB_COUNT = 10;
/**
- * The minimum number of {@link TimingSession}s that any bucket will be allowed to run
- * within its window.
+ * The minimum number of {@link TimingSession TimingSessions} that any bucket will be
+ * allowed to run within its window.
*/
private static final int MIN_BUCKET_SESSION_COUNT = 1;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/restrictions/JobRestriction.java b/apex/jobscheduler/service/java/com/android/server/job/restrictions/JobRestriction.java
index 3387b1d..4067541 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/restrictions/JobRestriction.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/restrictions/JobRestriction.java
@@ -54,7 +54,8 @@
/**
* Called by {@link JobSchedulerService} to check if it may proceed with scheduling the job (in
- * case all constraints are satisfied and all other {@link JobRestriction}s are fine with it)
+ * case all constraints are satisfied and all other {@link JobRestriction JobRestrictions} are
+ * fine with it).
*
* @param job to be checked
* @return false if the {@link JobSchedulerService} should not schedule this job at the moment,
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
index c5f0f32..005c447 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
@@ -85,7 +85,7 @@
mCurrentOngoingEvents = new SparseArrayMap<>();
/**
- * Set of {@link ActionAffordabilityNote}s keyed by userId-pkgName.
+ * Set of {@link ActionAffordabilityNote ActionAffordabilityNotes} keyed by userId-pkgName.
*
* Note: it would be nice/better to sort by base price since that doesn't change and simply
* look at the change in the "insertion" of what would be affordable, but since CTP
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java b/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
index 630f1e7..0fa0c47 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
@@ -74,7 +74,7 @@
}
/**
- * A collection of {@link AnticipatedAction}s that will be performed together.
+ * A collection of {@link AnticipatedAction AnticipatedActions} that will be performed together.
*/
final class ActionBill {
private static final Comparator<AnticipatedAction>
diff --git a/config/generate-preloaded-classes.sh b/config/generate-preloaded-classes.sh
deleted file mode 100755
index b17a366..0000000
--- a/config/generate-preloaded-classes.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-if [ "$#" -lt 2 ]; then
- echo "Usage $0 <input classes file> <denylist file> [extra classes files]"
- exit 1
-fi
-
-# Write file headers first
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-cat "$DIR/copyright-header"
-echo "# Preloaded-classes filter file for phones.
-#
-# Classes in this file will be allocated into the boot image, and forcibly initialized in
-# the zygote during initialization. This is a trade-off, using virtual address space to share
-# common heap between apps.
-#
-# This file has been derived for mainline phone (and tablet) usage.
-#"
-
-input=$1
-denylist=$2
-shift 2
-extra_classes_files=("$@")
-
-# Disable locale to enable lexicographical sorting
-LC_ALL=C sort "$input" "${extra_classes_files[@]}" | uniq | grep -f "$denylist" -v -F -x | grep -v "\$NoPreloadHolder"
diff --git a/config/preloaded-classes-extra b/config/preloaded-classes-extra
deleted file mode 100644
index 09f393a..0000000
--- a/config/preloaded-classes-extra
+++ /dev/null
@@ -1,14 +0,0 @@
-android.icu.impl.coll.CollationRoot
-android.icu.impl.IDNA2003
-android.icu.impl.number.Parse
-android.icu.util.TimeZone
-android.media.ImageReader
-android.media.MediaCodecList
-android.media.MediaPlayer
-android.media.SoundPool
-android.text.format.Formatter
-android.text.Html$HtmlParser
-android.util.Log$PreloadHolder
-com.android.org.conscrypt.TrustedCertificateStore
-org.ccil.cowan.tagsoup.HTMLScanner
-sun.security.jca.Providers
diff --git a/core/api/Android.bp b/core/api/Android.bp
index 170febb..114a957 100644
--- a/core/api/Android.bp
+++ b/core/api/Android.bp
@@ -51,11 +51,17 @@
filegroup {
name: "non-updatable-module-lib-current.txt",
srcs: ["module-lib-current.txt"],
- visibility: ["//frameworks/base/api"],
+ visibility: [
+ "//frameworks/base/api",
+ "//cts/tests/signature/api",
+ ],
}
filegroup {
name: "non-updatable-module-lib-removed.txt",
srcs: ["module-lib-removed.txt"],
- visibility: ["//frameworks/base/api"],
+ visibility: [
+ "//frameworks/base/api",
+ "//cts/tests/signature/api",
+ ],
}
diff --git a/core/api/current.txt b/core/api/current.txt
index 5656c31..f699bbe 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -1409,6 +1409,7 @@
field public static final int summaryColumn = 16843426; // 0x10102a2
field public static final int summaryOff = 16843248; // 0x10101f0
field public static final int summaryOn = 16843247; // 0x10101ef
+ field public static final int supportedTypes;
field public static final int supportsAssist = 16844016; // 0x10104f0
field public static final int supportsInlineSuggestions = 16844301; // 0x101060d
field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
@@ -20732,7 +20733,9 @@
field public static final int GET_DEVICES_ALL = 3; // 0x3
field public static final int GET_DEVICES_INPUTS = 1; // 0x1
field public static final int GET_DEVICES_OUTPUTS = 2; // 0x2
+ field public static final int MODE_CALL_REDIRECT = 5; // 0x5
field public static final int MODE_CALL_SCREENING = 4; // 0x4
+ field public static final int MODE_COMMUNICATION_REDIRECT = 6; // 0x6
field public static final int MODE_CURRENT = -1; // 0xffffffff
field public static final int MODE_INVALID = -2; // 0xfffffffe
field public static final int MODE_IN_CALL = 2; // 0x2
@@ -26304,6 +26307,13 @@
public final class TvIAppManager {
}
+ public abstract class TvIAppService extends android.app.Service {
+ ctor public TvIAppService();
+ method public final android.os.IBinder onBind(android.content.Intent);
+ field public static final String SERVICE_INTERFACE = "android.media.tv.interactive.TvIAppService";
+ field public static final String SERVICE_META_DATA = "android.media.tv.interactive.app";
+ }
+
}
package android.mtp {
@@ -31656,9 +31666,9 @@
method public byte[] marshall();
method @NonNull public static android.os.Parcel obtain();
method @NonNull public static android.os.Parcel obtain(@NonNull android.os.IBinder);
- method @Nullable public Object[] readArray(@Nullable ClassLoader);
+ method @Deprecated @Nullable public Object[] readArray(@Nullable ClassLoader);
method @Nullable public <T> T[] readArray(@Nullable ClassLoader, @NonNull Class<T>);
- method @Nullable public java.util.ArrayList readArrayList(@Nullable ClassLoader);
+ method @Deprecated @Nullable public java.util.ArrayList readArrayList(@Nullable ClassLoader);
method @Nullable public <T> java.util.ArrayList<T> readArrayList(@Nullable ClassLoader, @NonNull Class<? extends T>);
method public void readBinderArray(@NonNull android.os.IBinder[]);
method public void readBinderList(@NonNull java.util.List<android.os.IBinder>);
@@ -31676,32 +31686,32 @@
method public android.os.ParcelFileDescriptor readFileDescriptor();
method public float readFloat();
method public void readFloatArray(@NonNull float[]);
- method @Nullable public java.util.HashMap readHashMap(@Nullable ClassLoader);
+ method @Deprecated @Nullable public java.util.HashMap readHashMap(@Nullable ClassLoader);
method @Nullable public <K, V> java.util.HashMap<K,V> readHashMap(@Nullable ClassLoader, @NonNull Class<? extends K>, @NonNull Class<? extends V>);
method public int readInt();
method public void readIntArray(@NonNull int[]);
method public <T extends android.os.IInterface> void readInterfaceArray(@NonNull T[], @NonNull java.util.function.Function<android.os.IBinder,T>);
method public <T extends android.os.IInterface> void readInterfaceList(@NonNull java.util.List<T>, @NonNull java.util.function.Function<android.os.IBinder,T>);
- method public void readList(@NonNull java.util.List, @Nullable ClassLoader);
+ method @Deprecated public void readList(@NonNull java.util.List, @Nullable ClassLoader);
method public <T> void readList(@NonNull java.util.List<? super T>, @Nullable ClassLoader, @NonNull Class<T>);
method public long readLong();
method public void readLongArray(@NonNull long[]);
- method public void readMap(@NonNull java.util.Map, @Nullable ClassLoader);
+ method @Deprecated public void readMap(@NonNull java.util.Map, @Nullable ClassLoader);
method public <K, V> void readMap(@NonNull java.util.Map<? super K,? super V>, @Nullable ClassLoader, @NonNull Class<K>, @NonNull Class<V>);
- method @Nullable public <T extends android.os.Parcelable> T readParcelable(@Nullable ClassLoader);
+ method @Deprecated @Nullable public <T extends android.os.Parcelable> T readParcelable(@Nullable ClassLoader);
method @Nullable public <T extends android.os.Parcelable> T readParcelable(@Nullable ClassLoader, @NonNull Class<T>);
method @Nullable public android.os.Parcelable[] readParcelableArray(@Nullable ClassLoader);
method @Nullable public <T> T[] readParcelableArray(@Nullable ClassLoader, @NonNull Class<T>);
- method @Nullable public android.os.Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader);
+ method @Deprecated @Nullable public android.os.Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader);
method @Nullable public <T> android.os.Parcelable.Creator<T> readParcelableCreator(@Nullable ClassLoader, @NonNull Class<T>);
method @NonNull public <T extends android.os.Parcelable> java.util.List<T> readParcelableList(@NonNull java.util.List<T>, @Nullable ClassLoader);
method @Nullable public android.os.PersistableBundle readPersistableBundle();
method @Nullable public android.os.PersistableBundle readPersistableBundle(@Nullable ClassLoader);
- method @Nullable public java.io.Serializable readSerializable();
+ method @Deprecated @Nullable public java.io.Serializable readSerializable();
method @Nullable public <T extends java.io.Serializable> T readSerializable(@Nullable ClassLoader, @NonNull Class<T>);
method @NonNull public android.util.Size readSize();
method @NonNull public android.util.SizeF readSizeF();
- method @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader);
+ method @Deprecated @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader);
method @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader, @NonNull Class<? extends T>);
method @Nullable public android.util.SparseBooleanArray readSparseBooleanArray();
method @Nullable public String readString();
@@ -31957,8 +31967,10 @@
method public static final long getElapsedCpuTime();
method public static final int[] getExclusiveCores();
method public static final int getGidForName(String);
- method public static final long getStartElapsedRealtime();
- method public static final long getStartUptimeMillis();
+ method public static long getStartElapsedRealtime();
+ method public static long getStartRequestedElapsedRealtime();
+ method public static long getStartRequestedUptimeMillis();
+ method public static long getStartUptimeMillis();
method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
method public static final int getUidForName(String);
method public static final boolean is64Bit();
@@ -31966,6 +31978,7 @@
method public static final boolean isIsolated();
method public static final void killProcess(int);
method public static final int myPid();
+ method @NonNull public static String myProcessName();
method public static final int myTid();
method public static final int myUid();
method public static android.os.UserHandle myUserHandle();
@@ -42697,6 +42710,7 @@
method @Deprecated public int getMnc();
method @Nullable public String getMncString();
method public String getNumber();
+ method public int getPortIndex();
method public int getSimSlotIndex();
method public int getSubscriptionId();
method public int getSubscriptionType();
@@ -42729,6 +42743,8 @@
method @NonNull public java.util.List<android.net.Uri> getDeviceToDeviceStatusSharingContacts(int);
method public int getDeviceToDeviceStatusSharingPreference(int);
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telephony.SubscriptionInfo> getOpportunisticSubscriptions();
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_NUMBERS, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public String getPhoneNumber(int, int);
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_NUMBERS, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public String getPhoneNumber(int);
method public static int getSlotIndex(int);
method @Nullable public int[] getSubscriptionIds(int);
method @NonNull public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
@@ -42740,6 +42756,7 @@
method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void removeSubscriptionsFromGroup(@NonNull java.util.List<java.lang.Integer>, @NonNull android.os.ParcelUuid);
+ method public void setCarrierPhoneNumber(int, @NonNull String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDeviceToDeviceStatusSharingContacts(int, @NonNull java.util.List<android.net.Uri>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDeviceToDeviceStatusSharingPreference(int, int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunistic(boolean, int);
@@ -42766,6 +42783,9 @@
field public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX";
field public static final int INVALID_SIM_SLOT_INDEX = -1; // 0xffffffff
field public static final int INVALID_SUBSCRIPTION_ID = -1; // 0xffffffff
+ field public static final int PHONE_NUMBER_SOURCE_CARRIER = 2; // 0x2
+ field public static final int PHONE_NUMBER_SOURCE_IMS = 3; // 0x3
+ field public static final int PHONE_NUMBER_SOURCE_UICC = 1; // 0x1
field public static final int SUBSCRIPTION_TYPE_LOCAL_SIM = 0; // 0x0
field public static final int SUBSCRIPTION_TYPE_REMOTE_SIM = 1; // 0x1
}
@@ -43240,14 +43260,28 @@
method public int describeContents();
method public int getCardId();
method @Nullable public String getEid();
- method @Nullable public String getIccId();
- method public int getSlotIndex();
+ method @Deprecated @Nullable public String getIccId();
+ method public int getPhysicalSlotIndex();
+ method @NonNull public java.util.Collection<android.telephony.UiccPortInfo> getPorts();
+ method @Deprecated public int getSlotIndex();
method public boolean isEuicc();
+ method public boolean isMultipleEnabledProfilesSupported();
method public boolean isRemovable();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccCardInfo> CREATOR;
}
+ public final class UiccPortInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public String getIccId();
+ method @IntRange(from=0) public int getLogicalSlotIndex();
+ method @IntRange(from=0) public int getPortIndex();
+ method public boolean isActive();
+ method public void writeToParcel(@Nullable android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccPortInfo> CREATOR;
+ field public static final String ICCID_REDACTED = "FFFFFFFFFFFFFFFFFFFF";
+ }
+
public abstract class VisualVoicemailService extends android.app.Service {
ctor public VisualVoicemailService();
method public android.os.IBinder onBind(android.content.Intent);
@@ -43548,6 +43582,7 @@
method @Nullable public String getEid();
method @Nullable public android.telephony.euicc.EuiccInfo getEuiccInfo();
method public boolean isEnabled();
+ method public boolean isSimPortAvailable(int);
method public void startResolutionActivity(android.app.Activity, int, android.content.Intent, android.app.PendingIntent) throws android.content.IntentSender.SendIntentException;
method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, android.app.PendingIntent);
method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void updateSubscriptionNickname(int, @Nullable String, @NonNull android.app.PendingIntent);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 2d762f0..4d6c1c8 100755
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -7530,7 +7530,7 @@
method @NonNull public static android.media.tv.tuner.frontend.IsdbtFrontendSettings.IsdbtLayerSettings.Builder builder();
method public int getCodeRate();
method public int getModulation();
- method @IntRange(from=0, to=255) public int getNumOfSegment();
+ method @IntRange(from=0, to=255) public int getNumberOfSegment();
method public int getTimeInterleaveMode();
}
@@ -7538,7 +7538,7 @@
method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.IsdbtLayerSettings build();
method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.IsdbtLayerSettings.Builder setCodeRate(int);
method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.IsdbtLayerSettings.Builder setModulation(int);
- method @IntRange(from=0, to=255) @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.IsdbtLayerSettings.Builder setNumOfSegment(int);
+ method @IntRange(from=0, to=255) @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.IsdbtLayerSettings.Builder setNumberOfSegment(int);
method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.IsdbtLayerSettings.Builder setTimeInterleaveMode(int);
}
@@ -8955,6 +8955,7 @@
field public static final int SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED = 4; // 0x4
field public static final int SWITCHABILITY_STATUS_USER_IN_CALL = 1; // 0x1
field public static final int SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED = 2; // 0x2
+ field public static final String USER_TYPE_FULL_GUEST = "android.os.usertype.full.GUEST";
field public static final String USER_TYPE_FULL_SECONDARY = "android.os.usertype.full.SECONDARY";
field public static final String USER_TYPE_FULL_SYSTEM = "android.os.usertype.full.SYSTEM";
field public static final String USER_TYPE_PROFILE_CLONE = "android.os.usertype.profile.CLONE";
@@ -12358,6 +12359,7 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimSlotMapping(@NonNull java.util.Collection<android.telephony.UiccSlotMapping>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>);
method @Deprecated public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
@@ -12369,7 +12371,7 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPuk(String, String);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
method public void updateServiceLocation();
@@ -12539,10 +12541,11 @@
method public int describeContents();
method public String getCardId();
method public int getCardStateInfo();
- method public boolean getIsActive();
+ method @Deprecated public boolean getIsActive();
method public boolean getIsEuicc();
method public boolean getIsExtendedApduSupported();
- method public int getLogicalSlotIdx();
+ method @Deprecated public int getLogicalSlotIdx();
+ method @NonNull public java.util.Collection<android.telephony.UiccPortInfo> getPorts();
method public boolean isRemovable();
method public void writeToParcel(android.os.Parcel, int);
field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1
@@ -12552,6 +12555,15 @@
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccSlotInfo> CREATOR;
}
+ public final class UiccSlotMapping implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public int getLogicalSlotIndex();
+ method @IntRange(from=0) public int getPhysicalSlotIndex();
+ method @IntRange(from=0) public int getPortIndex();
+ method public void writeToParcel(@Nullable android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccSlotMapping> CREATOR;
+ }
+
public abstract class VisualVoicemailService extends android.app.Service {
method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, String, short, String, android.app.PendingIntent);
method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings);
@@ -12843,7 +12855,8 @@
method public void authenticateServer(String, String, byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
method public void cancelSession(String, byte[], @android.telephony.euicc.EuiccCardManager.CancelReason int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
method public void deleteProfile(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
- method public void disableProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+ method @Deprecated public void disableProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+ method public void disableProfile(@Nullable String, @Nullable String, int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
method public void listNotifications(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>);
method public void loadBoundProfilePackage(String, byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
method public void prepareDownload(String, @Nullable byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
@@ -12861,7 +12874,8 @@
method public void retrieveNotificationList(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>);
method public void setDefaultSmdpAddress(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
method public void setNickname(String, String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
- method public void switchToProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>);
+ method @Deprecated public void switchToProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>);
+ method public void switchToProfile(@Nullable String, @Nullable String, int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>);
field public static final int CANCEL_REASON_END_USER_REJECTED = 0; // 0x0
field public static final int CANCEL_REASON_POSTPONED = 1; // 0x1
field public static final int CANCEL_REASON_PPR_NOT_ALLOWED = 3; // 0x3
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 19223f9..ffa7cf1 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -37,8 +37,10 @@
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UptimeMillisLong;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.app.backup.BackupAgent;
@@ -888,6 +890,9 @@
SharedMemory mSerializedSystemFontMap;
+ long startRequestedElapsedTime;
+ long startRequestedUptime;
+
@Override
public String toString() {
return "AppBindData{appInfo=" + appInfo + "}";
@@ -1099,7 +1104,8 @@
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial, AutofillOptions autofillOptions,
ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges,
- SharedMemory serializedSystemFontMap) {
+ SharedMemory serializedSystemFontMap,
+ long startRequestedElapsedTime, long startRequestedUptime) {
if (services != null) {
if (false) {
// Test code to make sure the app could see the passed-in services.
@@ -1149,6 +1155,8 @@
data.contentCaptureOptions = contentCaptureOptions;
data.disabledCompatChanges = disabledCompatChanges;
data.mSerializedSystemFontMap = serializedSystemFontMap;
+ data.startRequestedElapsedTime = startRequestedElapsedTime;
+ data.startRequestedUptime = startRequestedUptime;
sendMessage(H.BIND_APPLICATION, data);
}
@@ -6407,7 +6415,8 @@
DdmVmInternal.setRecentAllocationsTrackingEnabled(true);
}
// Note when this process has started.
- Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
+ Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis(),
+ data.startRequestedElapsedTime, data.startRequestedUptime);
AppCompatCallbacks.install(data.disabledCompatChanges);
// Let libcore handle any compat changes after installing the list of compat changes.
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index d6ff6d3..0e42a79 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -80,7 +80,8 @@
in CompatibilityInfo compatInfo, in Map services,
in Bundle coreSettings, in String buildSerial, in AutofillOptions autofillOptions,
in ContentCaptureOptions contentCaptureOptions, in long[] disabledCompatChanges,
- in SharedMemory serializedSystemFontMap);
+ in SharedMemory serializedSystemFontMap,
+ long startRequestedElapsedTime, long startRequestedUptime);
void runIsolatedEntryPoint(in String entryPoint, in String[] entryPointArgs);
void scheduleExit();
void scheduleServiceArgs(IBinder token, in ParceledListSlice args);
diff --git a/core/java/android/hardware/devicestate/DeviceStateManager.java b/core/java/android/hardware/devicestate/DeviceStateManager.java
index 95892aa..b06d076 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManager.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManager.java
@@ -96,7 +96,7 @@
public void requestState(@NonNull DeviceStateRequest request,
@Nullable @CallbackExecutor Executor executor,
@Nullable DeviceStateRequest.Callback callback) {
- mGlobal.requestState(request, callback, executor);
+ mGlobal.requestState(request, executor, callback);
}
/**
diff --git a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
index 904a54b..85e70b0 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
@@ -117,7 +117,7 @@
* @see DeviceStateRequest
*/
public void requestState(@NonNull DeviceStateRequest request,
- @Nullable DeviceStateRequest.Callback callback, @Nullable Executor executor) {
+ @Nullable Executor executor, @Nullable DeviceStateRequest.Callback callback) {
if (callback == null && executor != null) {
throw new IllegalArgumentException("Callback must be supplied with executor.");
} else if (executor == null && callback != null) {
@@ -149,7 +149,7 @@
/**
* Cancels a {@link DeviceStateRequest request} previously submitted with a call to
- * {@link #requestState(DeviceStateRequest, DeviceStateRequest.Callback, Executor)}.
+ * {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
*
* @see DeviceStateManager#cancelRequest(DeviceStateRequest)
*/
@@ -408,7 +408,7 @@
return;
}
- mExecutor.execute(() -> mCallback.onRequestSuspended(mRequest));
+ mExecutor.execute(() -> mCallback.onRequestCanceled(mRequest));
}
}
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 689c806..a4a76a8 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -58,6 +58,7 @@
import java.lang.annotation.RetentionPolicy;
import java.text.DecimalFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Formatter;
@@ -859,11 +860,13 @@
/**
* Returns cpu times of an uid at a particular process state.
*/
- public abstract long[] getCpuFreqTimes(int which, int procState);
+ public abstract boolean getCpuFreqTimes(@NonNull long[] timesInFreqMs, int procState);
+
/**
* Returns cpu times of an uid while the screen if off at a particular process state.
*/
- public abstract long[] getScreenOffCpuFreqTimes(int which, int procState);
+ public abstract boolean getScreenOffCpuFreqTimes(@NonNull long[] timesInFreqMs,
+ int procState);
// Note: the following times are disjoint. They can be added together to find the
// total time a uid has had any processes running at all.
@@ -1575,6 +1578,11 @@
public abstract long getNextMaxDailyDeadline();
+ /**
+ * Returns the total number of frequencies across all CPU clusters.
+ */
+ public abstract int getCpuFreqCount();
+
public abstract long[] getCpuFreqs();
public final static class HistoryTag {
@@ -4626,27 +4634,26 @@
cpuFreqTimeMs.length, sb.toString());
}
+ final long[] timesInFreqMs = new long[getCpuFreqCount()];
for (int procState = 0; procState < Uid.NUM_PROCESS_STATE; ++procState) {
- final long[] timesMs = u.getCpuFreqTimes(which, procState);
- if (timesMs != null && timesMs.length == cpuFreqs.length) {
+ if (u.getCpuFreqTimes(timesInFreqMs, procState)) {
sb.setLength(0);
- for (int i = 0; i < timesMs.length; ++i) {
+ for (int i = 0; i < timesInFreqMs.length; ++i) {
if (i != 0) sb.append(',');
- sb.append(timesMs[i]);
+ sb.append(timesInFreqMs[i]);
}
- final long[] screenOffTimesMs = u.getScreenOffCpuFreqTimes(
- which, procState);
- if (screenOffTimesMs != null) {
- for (int i = 0; i < screenOffTimesMs.length; ++i) {
- sb.append(',').append(screenOffTimesMs[i]);
+ if (u.getScreenOffCpuFreqTimes(timesInFreqMs, procState)) {
+ for (int i = 0; i < timesInFreqMs.length; ++i) {
+ sb.append(',').append(timesInFreqMs[i]);
}
} else {
- for (int i = 0; i < timesMs.length; ++i) {
+ for (int i = 0; i < timesInFreqMs.length; ++i) {
sb.append(",0");
}
}
dumpLine(pw, uid, category, CPU_TIMES_AT_FREQ_DATA,
- Uid.UID_PROCESS_TYPES[procState], timesMs.length, sb.toString());
+ Uid.UID_PROCESS_TYPES[procState], timesInFreqMs.length,
+ sb.toString());
}
}
}
@@ -6243,25 +6250,24 @@
pw.println(sb.toString());
}
+ final long[] timesInFreqMs = new long[getCpuFreqCount()];
for (int procState = 0; procState < Uid.NUM_PROCESS_STATE; ++procState) {
- final long[] cpuTimes = u.getCpuFreqTimes(which, procState);
- if (cpuTimes != null) {
+ if (u.getCpuFreqTimes(timesInFreqMs, procState)) {
sb.setLength(0);
sb.append(" Cpu times per freq at state ")
.append(Uid.PROCESS_STATE_NAMES[procState]).append(':');
- for (int i = 0; i < cpuTimes.length; ++i) {
- sb.append(" " + cpuTimes[i]);
+ for (int i = 0; i < timesInFreqMs.length; ++i) {
+ sb.append(" ").append(timesInFreqMs[i]);
}
pw.println(sb.toString());
}
- final long[] screenOffCpuTimes = u.getScreenOffCpuFreqTimes(which, procState);
- if (screenOffCpuTimes != null) {
+ if (u.getScreenOffCpuFreqTimes(timesInFreqMs, procState)) {
sb.setLength(0);
sb.append(" Screen-off cpu times per freq at state ")
.append(Uid.PROCESS_STATE_NAMES[procState]).append(':');
- for (int i = 0; i < screenOffCpuTimes.length; ++i) {
- sb.append(" " + screenOffCpuTimes[i]);
+ for (int i = 0; i < timesInFreqMs.length; ++i) {
+ sb.append(" ").append(timesInFreqMs[i]);
}
pw.println(sb.toString());
}
@@ -7627,22 +7633,22 @@
}
}
+ final long[] timesInFreqMs = new long[getCpuFreqCount()];
+ final long[] timesInFreqScreenOffMs = new long[getCpuFreqCount()];
for (int procState = 0; procState < Uid.NUM_PROCESS_STATE; ++procState) {
- final long[] timesMs = u.getCpuFreqTimes(which, procState);
- if (timesMs != null && timesMs.length == cpuFreqs.length) {
- long[] screenOffTimesMs = u.getScreenOffCpuFreqTimes(which, procState);
- if (screenOffTimesMs == null) {
- screenOffTimesMs = new long[timesMs.length];
+ if (u.getCpuFreqTimes(timesInFreqMs, procState)) {
+ if (!u.getScreenOffCpuFreqTimes(timesInFreqScreenOffMs, procState)) {
+ Arrays.fill(timesInFreqScreenOffMs, 0);
}
final long procToken = proto.start(UidProto.Cpu.BY_PROCESS_STATE);
proto.write(UidProto.Cpu.ByProcessState.PROCESS_STATE, procState);
- for (int ic = 0; ic < timesMs.length; ++ic) {
+ for (int ic = 0; ic < timesInFreqMs.length; ++ic) {
long cToken = proto.start(UidProto.Cpu.ByProcessState.BY_FREQUENCY);
proto.write(UidProto.Cpu.ByFrequency.FREQUENCY_INDEX, ic + 1);
proto.write(UidProto.Cpu.ByFrequency.TOTAL_DURATION_MS,
- timesMs[ic]);
+ timesInFreqMs[ic]);
proto.write(UidProto.Cpu.ByFrequency.SCREEN_OFF_DURATION_MS,
- screenOffTimesMs[ic]);
+ timesInFreqScreenOffMs[ic]);
proto.end(cToken);
}
proto.end(procToken);
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 09e5a8f..7bdb6b9 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -2990,7 +2990,12 @@
* Please use {@link #readBundle(ClassLoader)} instead (whose data must have
* been written with {@link #writeBundle}. Read into an existing Map object
* from the parcel at the current dataPosition().
+ *
+ * @deprecated Consider using {@link #readBundle(ClassLoader)} as stated above, in case this
+ * method is still preferred use the type-safer version {@link #readMap(Map, ClassLoader,
+ * Class, Class)} starting from Android {@link Build.VERSION_CODES#TIRAMISU}.
*/
+ @Deprecated
public final void readMap(@NonNull Map outVal, @Nullable ClassLoader loader) {
int n = readInt();
readMapInternal(outVal, n, loader, /* clazzKey */ null, /* clazzValue */ null);
@@ -3016,7 +3021,14 @@
* Read into an existing List object from the parcel at the current
* dataPosition(), using the given class loader to load any enclosed
* Parcelables. If it is null, the default class loader is used.
+ *
+ * @deprecated Use the type-safer version {@link #readList(List, ClassLoader, Class)} starting
+ * from Android {@link Build.VERSION_CODES#TIRAMISU}. Also consider changing the format to
+ * use {@link #readTypedList(List, Parcelable.Creator)} if possible (eg. if the items'
+ * class is final) since this is also more performant. Note that changing to the latter
+ * also requires changing the writes.
*/
+ @Deprecated
public final void readList(@NonNull List outVal, @Nullable ClassLoader loader) {
int N = readInt();
readListInternal(outVal, N, loader, /* clazz */ null);
@@ -3043,10 +3055,14 @@
* object from the parcel at the current dataPosition(), using the given
* class loader to load any enclosed Parcelables. Returns null if
* the previously written map object was null.
+ *
+ * @deprecated Consider using {@link #readBundle(ClassLoader)} as stated above, in case this
+ * method is still preferred use the type-safer version {@link #readHashMap(ClassLoader,
+ * Class, Class)} starting from Android {@link Build.VERSION_CODES#TIRAMISU}.
*/
+ @Deprecated
@Nullable
- public final HashMap readHashMap(@Nullable ClassLoader loader)
- {
+ public HashMap readHashMap(@Nullable ClassLoader loader) {
int n = readInt();
if (n < 0) {
return null;
@@ -3247,7 +3263,14 @@
* dataPosition(). Returns null if the previously written list object was
* null. The given class loader will be used to load any enclosed
* Parcelables.
+ *
+ * @deprecated Use the type-safer version {@link #readArrayList(ClassLoader, Class)} starting
+ * from Android {@link Build.VERSION_CODES#TIRAMISU}. Also consider changing the format to
+ * use {@link #createTypedArrayList(Parcelable.Creator)} if possible (eg. if the items'
+ * class is final) since this is also more performant. Note that changing to the latter
+ * also requires changing the writes.
*/
+ @Deprecated
@Nullable
public ArrayList readArrayList(@Nullable ClassLoader loader) {
return readArrayListInternal(loader, /* clazz */ null);
@@ -3274,7 +3297,14 @@
* dataPosition(). Returns null if the previously written array was
* null. The given class loader will be used to load any enclosed
* Parcelables.
+ *
+ * @deprecated Use the type-safer version {@link #readArray(ClassLoader, Class)} starting from
+ * Android {@link Build.VERSION_CODES#TIRAMISU}. Also consider changing the format to use
+ * {@link #createTypedArray(Parcelable.Creator)} if possible (eg. if the items' class is
+ * final) since this is also more performant. Note that changing to the latter also
+ * requires changing the writes.
*/
+ @Deprecated
@Nullable
public Object[] readArray(@Nullable ClassLoader loader) {
return readArrayInternal(loader, /* clazz */ null);
@@ -3300,7 +3330,14 @@
* dataPosition(). Returns null if the previously written list object was
* null. The given class loader will be used to load any enclosed
* Parcelables.
+ *
+ * @deprecated Use the type-safer version {@link #readSparseArray(ClassLoader, Class)} starting
+ * from Android {@link Build.VERSION_CODES#TIRAMISU}. Also consider changing the format to
+ * use {@link #createTypedSparseArray(Parcelable.Creator)} if possible (eg. if the items'
+ * class is final) since this is also more performant. Note that changing to the latter
+ * also requires changing the writes.
*/
+ @Deprecated
@Nullable
public <T> SparseArray<T> readSparseArray(@Nullable ClassLoader loader) {
return readSparseArrayInternal(loader, /* clazz */ null);
@@ -4107,7 +4144,13 @@
* object has been written.
* @throws BadParcelableException Throws BadParcelableException if there
* was an error trying to instantiate the Parcelable.
+ *
+ * @deprecated Use the type-safer version {@link #readParcelable(ClassLoader, Class)} starting
+ * from Android {@link Build.VERSION_CODES#TIRAMISU}. Also consider changing the format to
+ * use {@link Parcelable.Creator#createFromParcel(Parcel)} if possible since this is also
+ * more performant. Note that changing to the latter also requires changing the writes.
*/
+ @Deprecated
@Nullable
public final <T extends Parcelable> T readParcelable(@Nullable ClassLoader loader) {
return readParcelableInternal(loader, /* clazz */ null);
@@ -4176,7 +4219,11 @@
* read the {@link Parcelable.Creator}.
*
* @see #writeParcelableCreator
+ *
+ * @deprecated Use the type-safer version {@link #readParcelableCreator(ClassLoader, Class)}
+ * starting from Android {@link Build.VERSION_CODES#TIRAMISU}.
*/
+ @Deprecated
@Nullable
public final Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader loader) {
return readParcelableCreatorInternal(loader, /* clazz */ null);
@@ -4337,7 +4384,11 @@
* Read and return a new Serializable object from the parcel.
* @return the Serializable object, or null if the Serializable name
* wasn't found in the parcel.
+ *
+ * @deprecated Use the type-safer version {@link #readSerializable(ClassLoader, Class)} starting
+ * from Android {@link Build.VERSION_CODES#TIRAMISU}.
*/
+ @Deprecated
@Nullable
public Serializable readSerializable() {
return readSerializableInternal(/* loader */ null, /* clazz */ null);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 9f37c48..c9670ff 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -18,11 +18,14 @@
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.annotation.UptimeMillisLong;
import android.compat.annotation.UnsupportedAppUsage;
+import android.os.Build.VERSION_CODES;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
@@ -553,9 +556,26 @@
public static final int SIGNAL_KILL = 9;
public static final int SIGNAL_USR1 = 10;
+ /**
+ * When the process started and ActivityThread.handleBindApplication() was executed.
+ */
private static long sStartElapsedRealtime;
+
+ /**
+ * When the process started and ActivityThread.handleBindApplication() was executed.
+ */
private static long sStartUptimeMillis;
+ /**
+ * When the activity manager was about to ask zygote to fork.
+ */
+ private static long sStartRequestedElapsedRealtime;
+
+ /**
+ * When the activity manager was about to ask zygote to fork.
+ */
+ private static long sStartRequestedUptimeMillis;
+
private static final int PIDFD_UNKNOWN = 0;
private static final int PIDFD_SUPPORTED = 1;
private static final int PIDFD_UNSUPPORTED = 2;
@@ -605,6 +625,12 @@
*/
public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess();
+
+ /**
+ * The process name set via {@link #setArgV0(String)}.
+ */
+ private static String sArgV0;
+
/**
* Start a new process.
*
@@ -718,21 +744,44 @@
/**
* Return the {@link SystemClock#elapsedRealtime()} at which this process was started.
*/
- public static final long getStartElapsedRealtime() {
+ @ElapsedRealtimeLong
+ public static long getStartElapsedRealtime() {
return sStartElapsedRealtime;
}
/**
* Return the {@link SystemClock#uptimeMillis()} at which this process was started.
*/
- public static final long getStartUptimeMillis() {
+ @UptimeMillisLong
+ public static long getStartUptimeMillis() {
return sStartUptimeMillis;
}
+ /**
+ * Return the {@link SystemClock#elapsedRealtime()} at which the system decides to start
+ * this process.
+ */
+ @ElapsedRealtimeLong
+ public static long getStartRequestedElapsedRealtime() {
+ return sStartRequestedElapsedRealtime;
+ }
+
+ /**
+ * Return the {@link SystemClock#uptimeMillis()} at which the system decides to start
+ * this process.
+ */
+ @UptimeMillisLong
+ public static long getStartRequestedUptimeMillis() {
+ return sStartRequestedUptimeMillis;
+ }
+
/** @hide */
- public static final void setStartTimes(long elapsedRealtime, long uptimeMillis) {
+ public static final void setStartTimes(long elapsedRealtime, long uptimeMillis,
+ long startRequestedElapsedRealtime, long startRequestedUptime) {
sStartElapsedRealtime = elapsedRealtime;
sStartUptimeMillis = uptimeMillis;
+ sStartRequestedElapsedRealtime = startRequestedElapsedRealtime;
+ sStartRequestedUptimeMillis = startRequestedUptime;
}
/**
@@ -1135,8 +1184,26 @@
*
* {@hide}
*/
- @UnsupportedAppUsage
- public static final native void setArgV0(String text);
+ @UnsupportedAppUsage(maxTargetSdk = VERSION_CODES.S, publicAlternatives = "Do not try to "
+ + "change the process name. (If you must, you could use {@code pthread_setname_np(3)}, "
+ + "but this could confuse the system)")
+ public static void setArgV0(@NonNull String text) {
+ sArgV0 = text;
+ setArgV0Native(text);
+ }
+
+ private static native void setArgV0Native(String text);
+
+ /**
+ * Return the name of this process.
+ */
+ @NonNull
+ public static String myProcessName() {
+ // Note this could be different from the actual process name if someone changes the
+ // process name using native code (using pthread_setname_np()). But sArgV0
+ // is the name that the system thinks this process has.
+ return sArgV0;
+ }
/**
* Kill the process with the given PID.
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index 4e8418b..ba5ed43 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -298,6 +298,17 @@
}
/**
+ * Register callback for service registration notifications.
+ *
+ * @throws RemoteException for underlying error.
+ * @hide
+ */
+ public static void registerForNotifications(
+ @NonNull String name, @NonNull IServiceCallback callback) throws RemoteException {
+ getIServiceManager().registerForNotifications(name, callback);
+ }
+
+ /**
* Return a list of all currently running services.
* @return an array of all currently running services, or <code>null</code> in
* case of an exception
diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java
index 3739040..2dcf674 100644
--- a/core/java/android/os/ServiceManagerNative.java
+++ b/core/java/android/os/ServiceManagerNative.java
@@ -78,7 +78,7 @@
public void registerForNotifications(String name, IServiceCallback cb)
throws RemoteException {
- throw new RemoteException();
+ mServiceManager.registerForNotifications(name, cb);
}
public void unregisterForNotifications(String name, IServiceCallback cb)
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 14d7e82..447102b 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -118,6 +118,7 @@
* User type representing a guest user that may be transient.
* @hide
*/
+ @SystemApi
public static final String USER_TYPE_FULL_GUEST = "android.os.usertype.full.GUEST";
/**
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index fbac954..bff5c62 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -90,9 +90,9 @@
*/
int changeEncryptionPassword(int type, in String password) = 28;
/**
- * Returns list of all mountable volumes.
+ * Returns list of all mountable volumes for the specified userId
*/
- StorageVolume[] getVolumeList(int uid, in String packageName, int flags) = 29;
+ StorageVolume[] getVolumeList(int userId, in String callingPackage, int flags) = 29;
/**
* Determines the encryption state of the volume.
* @return a numerical value. See {@code ENCRYPTION_STATE_*} for possible
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 77c794c..627e09e 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1391,13 +1391,7 @@
}
packageName = packageNames[0];
}
- final int uid = ActivityThread.getPackageManager().getPackageUid(packageName,
- PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
- if (uid <= 0) {
- Log.w(TAG, "Missing UID; no storage volumes available");
- return new StorageVolume[0];
- }
- return storageManager.getVolumeList(uid, packageName, flags);
+ return storageManager.getVolumeList(userId, packageName, flags);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 17272d3..3d7c026 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -15080,22 +15080,6 @@
"max_sound_trigger_detection_service_ops_per_day";
/**
- * Setting indicating the name of the Wear OS app package containing the device's sysui.
- *
- * @hide
- */
- public static final String CLOCKWORK_SYSUI_PACKAGE_NAME =
- "clockwork_sysui_package_name";
-
- /**
- * Setting indicating the name of the main activity of the Wear OS sysui.
- *
- * @hide
- */
- public static final String CLOCKWORK_SYSUI_MAIN_ACTIVITY_NAME =
- "clockwork_sysui_main_activity_name";
-
- /**
* Setting to determine if the Clockwork Home application is ready.
*
* <p>
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 89b95c0..f807da8 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -10424,7 +10424,7 @@
@Override
public boolean applyTransactionOnDraw(@NonNull SurfaceControl.Transaction t) {
- if (mRemoved) {
+ if (mRemoved || !isHardwareEnabled()) {
t.apply();
} else {
registerRtFrameCallback(frame -> mergeWithNextTransaction(t, frame));
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index dc01990..91ef8a5 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -20,6 +20,7 @@
import static android.view.accessibility.AccessibilityNodeInfo.FOCUS_ACCESSIBILITY;
import android.os.Build;
+import android.os.SystemClock;
import android.util.ArraySet;
import android.util.Log;
import android.util.LongArray;
@@ -71,6 +72,11 @@
private long mAccessibilityFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
private long mInputFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+ /**
+ * The event time of the {@link AccessibilityEvent} which presents the populated windows cache
+ * before it is stale.
+ */
+ private long mValidWindowCacheTimeStamp = 0;
private int mAccessibilityFocusedWindow = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
private int mInputFocusWindow = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
@@ -97,13 +103,20 @@
* The key of SparseArray is display ID.
*
* @param windowsOnAllDisplays The accessibility windows of all displays.
+ * @param populationTimeStamp The timestamp from {@link SystemClock#uptimeMillis()} when the
+ * client requests the data.
*/
public void setWindowsOnAllDisplays(
- SparseArray<List<AccessibilityWindowInfo>> windowsOnAllDisplays) {
+ SparseArray<List<AccessibilityWindowInfo>> windowsOnAllDisplays,
+ long populationTimeStamp) {
synchronized (mLock) {
if (DEBUG) {
Log.i(LOG_TAG, "Set windows");
}
+ if (mValidWindowCacheTimeStamp > populationTimeStamp) {
+ // Discard the windows because it might be stale.
+ return;
+ }
clearWindowCacheLocked();
if (windowsOnAllDisplays == null) {
return;
@@ -224,6 +237,7 @@
} break;
case AccessibilityEvent.TYPE_WINDOWS_CHANGED:
+ mValidWindowCacheTimeStamp = event.getEventTime();
if (event.getWindowChanges()
== AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED) {
// Don't need to clear all cache. Unless the changes are related to
@@ -232,6 +246,7 @@
break;
}
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
+ mValidWindowCacheTimeStamp = event.getEventTime();
clear();
} break;
}
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 6975bb2..bc21488 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -435,8 +435,10 @@
}
}
+ long populationTimeStamp;
final long identityToken = Binder.clearCallingIdentity();
try {
+ populationTimeStamp = SystemClock.uptimeMillis();
windows = connection.getWindows();
} finally {
Binder.restoreCallingIdentity(identityToken);
@@ -446,7 +448,7 @@
}
if (windows != null) {
if (sAccessibilityCache != null) {
- sAccessibilityCache.setWindowsOnAllDisplays(windows);
+ sAccessibilityCache.setWindowsOnAllDisplays(windows, populationTimeStamp);
}
return windows;
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 9140bb8..06d68e0 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -468,6 +468,7 @@
mPendingUids.clear();
}
final long timestampMs = mClock.elapsedRealtime();
+ LongArrayMultiStateCounter.LongArrayContainer deltaContainer = null;
for (int i = uidStates.size() - 1; i >= 0; --i) {
final int uid = uidStates.keyAt(i);
final int procState = uidStates.valueAt(i);
@@ -493,6 +494,9 @@
isolatedUids[j] = u.mChildUids.keyAt(j);
isolatedUidTimeInFreqCounters[j] =
u.mChildUids.valueAt(j).cpuTimeInFreqCounter;
+ if (deltaContainer == null && isolatedUidTimeInFreqCounters[j] != null) {
+ deltaContainer = getCpuTimeInFreqContainer();
+ }
}
}
}
@@ -509,8 +513,6 @@
mKernelSingleUidTimeReader.addDelta(uid, onBatteryScreenOffCounter, timestampMs);
if (isolatedUids != null) {
- LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
- new LongArrayMultiStateCounter.LongArrayContainer(getCpuFreqCount());
for (int j = isolatedUids.length - 1; j >= 0; --j) {
if (isolatedUidTimeInFreqCounters[j] != null) {
mKernelSingleUidTimeReader.addDelta(isolatedUids[j],
@@ -612,13 +614,13 @@
}
if (u.mChildUids != null) {
- final LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
- new LongArrayMultiStateCounter.LongArrayContainer(getCpuFreqCount());
for (int j = u.mChildUids.size() - 1; j >= 0; --j) {
final LongArrayMultiStateCounter counter =
u.mChildUids.valueAt(j).cpuTimeInFreqCounter;
if (counter != null) {
final int isolatedUid = u.mChildUids.keyAt(j);
+ final LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
+ getCpuTimeInFreqContainer();
mKernelSingleUidTimeReader.addDelta(isolatedUid,
counter, timestampMs, deltaContainer);
onBatteryCounter.addCounts(deltaContainer);
@@ -1186,7 +1188,9 @@
private long mBatteryTimeToFullSeconds = -1;
+ private boolean mCpuFreqsInitialized;
private long[] mCpuFreqs;
+ private LongArrayMultiStateCounter.LongArrayContainer mTmpCpuTimeInFreq;
/**
* Times spent by the system server threads handling incoming binder requests.
@@ -1931,23 +1935,22 @@
}
/**
- * Returns accumulated counts for the specified state, or null if all counts are zero.
+ * Returns accumulated counts for the specified state, or false if all counts are zero.
*/
- @Nullable
- public long[] getCountsLocked(int which, int procState) {
- LongArrayMultiStateCounter.LongArrayContainer longArrayContainer =
- new LongArrayMultiStateCounter.LongArrayContainer(mCounter.getArrayLength());
- mCounter.getCounts(longArrayContainer, procState);
- final long[] counts = new long[mCounter.getArrayLength()];
- longArrayContainer.getValues(counts);
+ public boolean getCountsLocked(long[] counts, int procState) {
+ if (counts.length != mCounter.getArrayLength()) {
+ return false;
+ }
+
+ mCounter.getCounts(counts, procState);
// Return counts only if at least one of the elements is non-zero.
for (int i = counts.length - 1; i >= 0; --i) {
if (counts[i] != 0) {
- return counts;
+ return true;
}
}
- return null;
+ return false;
}
public void logState(Printer pw, String prefix) {
@@ -8346,35 +8349,34 @@
@GuardedBy("mBsi")
@Override
- public long[] getCpuFreqTimes(int which, int procState) {
+ public boolean getCpuFreqTimes(long[] timesInFreqMs, int procState) {
if (procState < 0 || procState >= NUM_PROCESS_STATE) {
- return null;
+ return false;
}
if (mProcStateTimeMs == null) {
- return null;
+ return false;
}
if (!mBsi.mPerProcStateCpuTimesAvailable) {
mProcStateTimeMs = null;
- return null;
+ return false;
}
-
- return mProcStateTimeMs.getCountsLocked(which, procState);
+ return mProcStateTimeMs.getCountsLocked(timesInFreqMs, procState);
}
@GuardedBy("mBsi")
@Override
- public long[] getScreenOffCpuFreqTimes(int which, int procState) {
+ public boolean getScreenOffCpuFreqTimes(long[] timesInFreqMs, int procState) {
if (procState < 0 || procState >= NUM_PROCESS_STATE) {
- return null;
+ return false;
}
if (mProcStateScreenOffTimeMs == null) {
- return null;
+ return false;
}
if (!mBsi.mPerProcStateCpuTimesAvailable) {
mProcStateScreenOffTimeMs = null;
- return null;
+ return false;
}
- return mProcStateScreenOffTimeMs.getCountsLocked(which, procState);
+ return mProcStateScreenOffTimeMs.getCountsLocked(timesInFreqMs, procState);
}
public long getBinderCallCount() {
@@ -11577,18 +11579,30 @@
}
}
+ @GuardedBy("this")
+ @Override
public long[] getCpuFreqs() {
+ if (!mCpuFreqsInitialized) {
+ mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
+ mCpuFreqsInitialized = true;
+ }
return mCpuFreqs;
}
- /**
- * Returns the total number of frequencies across all CPU clusters.
- */
- private int getCpuFreqCount() {
- if (mCpuFreqs == null) {
- mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
+ @GuardedBy("this")
+ @Override
+ public int getCpuFreqCount() {
+ final long[] cpuFreqs = getCpuFreqs();
+ return cpuFreqs != null ? cpuFreqs.length : 0;
+ }
+
+ @GuardedBy("this")
+ private LongArrayMultiStateCounter.LongArrayContainer getCpuTimeInFreqContainer() {
+ if (mTmpCpuTimeInFreq == null) {
+ mTmpCpuTimeInFreq =
+ new LongArrayMultiStateCounter.LongArrayContainer(getCpuFreqCount());
}
- return mCpuFreqs != null ? mCpuFreqs.length : 0;
+ return mTmpCpuTimeInFreq;
}
public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index 4ab4fae..175f28f 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -56,6 +56,7 @@
public long durationFgMs;
public String packageWithHighestDrain;
public double[] perProcStatePowerMah;
+ public long[] cpuFreqTimes;
}
public CpuPowerCalculator(PowerProfile profile) {
@@ -98,6 +99,9 @@
BatteryConsumer.Key[] keys = UNINITIALIZED_KEYS;
Result result = new Result();
+ if (query.isProcessStateDataNeeded()) {
+ result.cpuFreqTimes = new long[batteryStats.getCpuFreqCount()];
+ }
final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
builder.getUidBatteryConsumerBuilders();
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
@@ -187,11 +191,10 @@
// TODO(b/191921016): use per-state CPU cluster times
final long[] cpuClusterTimes = null;
- final long[] cpuFreqTimes = u.getCpuFreqTimes(BatteryStats.STATS_SINCE_CHARGED,
- uidProcState);
- if (cpuClusterTimes != null || cpuFreqTimes != null) {
+ boolean hasCpuFreqTimes = u.getCpuFreqTimes(result.cpuFreqTimes, uidProcState);
+ if (cpuClusterTimes != null || hasCpuFreqTimes) {
result.perProcStatePowerMah[procState] += calculateUidModeledPowerMah(u,
- 0, cpuClusterTimes, cpuFreqTimes);
+ 0, cpuClusterTimes, result.cpuFreqTimes);
}
}
diff --git a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
index d98b73f..50dcca64 100644
--- a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
+++ b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
@@ -27,6 +27,7 @@
import libcore.util.NativeAllocationRegistry;
import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicReference;
/**
* Performs per-state counting of multi-element values over time. The class' behavior is illustrated
@@ -120,6 +121,8 @@
private static final NativeAllocationRegistry sRegistry =
NativeAllocationRegistry.createMalloced(
LongArrayMultiStateCounter.class.getClassLoader(), native_getReleaseFunc());
+ private static final AtomicReference<LongArrayContainer> sTmpArrayContainer =
+ new AtomicReference<>();
private final int mStateCount;
private final int mLength;
@@ -204,6 +207,19 @@
}
/**
+ * Populates the array with the accumulated counts for the specified state.
+ */
+ public void getCounts(long[] counts, int state) {
+ LongArrayContainer container = sTmpArrayContainer.getAndSet(null);
+ if (container == null || container.mLength != counts.length) {
+ container = new LongArrayContainer(counts.length);
+ }
+ getCounts(container, state);
+ container.getValues(counts);
+ sTmpArrayContainer.set(container);
+ }
+
+ /**
* Populates longArrayContainer with the accumulated counts for the specified state.
*/
public void getCounts(LongArrayContainer longArrayContainer, int state) {
diff --git a/core/java/com/android/internal/view/OWNERS b/core/java/com/android/internal/view/OWNERS
index eb2478f..7a590d0 100644
--- a/core/java/com/android/internal/view/OWNERS
+++ b/core/java/com/android/internal/view/OWNERS
@@ -15,7 +15,7 @@
# WindowManager
per-file AppearanceRegion = file:/services/core/java/com/android/server/wm/OWNERS
-per-file BaseIWIndow.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file BaseIWindow.java = file:/services/core/java/com/android/server/wm/OWNERS
per-file RotationPolicy.java = file:/services/core/java/com/android/server/wm/OWNERS
per-file WindowManagerPolicyThread.java = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 5c9b6df..18e85b6 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -750,8 +750,9 @@
}
const bool checkJni = GetBoolProperty("dalvik.vm.checkjni", false);
- ALOGV("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
if (checkJni) {
+ ALOGD("CheckJNI is ON");
+
/* extended JNI checking */
addOption("-Xcheck:jni");
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 4d8d4db..7c67cbc 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -1346,7 +1346,7 @@
{"createProcessGroup", "(II)I", (void*)android_os_Process_createProcessGroup},
{"getExclusiveCores", "()[I", (void*)android_os_Process_getExclusiveCores},
{"setSwappiness", "(IZ)Z", (void*)android_os_Process_setSwappiness},
- {"setArgV0", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
+ {"setArgV0Native", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
{"setUid", "(I)I", (void*)android_os_Process_setUid},
{"setGid", "(I)I", (void*)android_os_Process_setGid},
{"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
diff --git a/core/res/res/layout-watch/alert_dialog_material.xml b/core/res/res/layout-watch/alert_dialog_material.xml
index 960b927..1d56845 100644
--- a/core/res/res/layout-watch/alert_dialog_material.xml
+++ b/core/res/res/layout-watch/alert_dialog_material.xml
@@ -51,7 +51,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal|top"
- android:textAppearance="@style/TextAppearance.Material.Subhead"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Body1"
android:paddingStart="?dialogPreferredPadding"
android:paddingEnd="?dialogPreferredPadding"
android:paddingTop="8dip"
diff --git a/core/res/res/layout-watch/progress_dialog_material.xml b/core/res/res/layout-watch/progress_dialog_material.xml
index 96bda1d..a7df948 100644
--- a/core/res/res/layout-watch/progress_dialog_material.xml
+++ b/core/res/res/layout-watch/progress_dialog_material.xml
@@ -40,7 +40,7 @@
<TextView
android:id="@+id/message"
- android:textAppearance="?attr/textAppearanceListItem"
+ android:textAppearance="@style/TextAppearance.DeviceDefault.Subhead"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" />
diff --git a/core/res/res/values-w208dp/dimens_material.xml b/core/res/res/values-w208dp/dimens_material.xml
new file mode 100644
index 0000000..069eeb0
--- /dev/null
+++ b/core/res/res/values-w208dp/dimens_material.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <dimen name="screen_percentage_05">10.4dp</dimen>
+ <dimen name="screen_percentage_10">20.8dp</dimen>
+ <dimen name="screen_percentage_15">31.2dp</dimen>
+</resources>
diff --git a/core/res/res/values-w227dp/dimens_material.xml b/core/res/res/values-w227dp/dimens_material.xml
new file mode 100644
index 0000000..eb4df8a2
--- /dev/null
+++ b/core/res/res/values-w227dp/dimens_material.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <dimen name="screen_percentage_05">11.35dp</dimen>
+ <dimen name="screen_percentage_10">22.7dp</dimen>
+ <dimen name="screen_percentage_15">34.05dp</dimen>
+</resources>
diff --git a/core/res/res/values-watch/styles_device_default.xml b/core/res/res/values-watch/styles_device_default.xml
new file mode 100644
index 0000000..e2261af
--- /dev/null
+++ b/core/res/res/values-watch/styles_device_default.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <style name="DialogWindowTitle.DeviceDefault" parent="DialogWindowTitle.Material">
+ <item name="maxLines">2</item>
+ <item name="shadowRadius">0</item>
+ <item name="ellipsize">end</item>
+ <item name="textAppearance">@style/TextAppearance.DeviceDefault.Title</item>
+ </style>
+ <style name="TextAppearance.DeviceDefault.Body1" parent="TextAppearance.Material.Body1">
+ <item name="android:textSize">15sp</item>
+ <item name="android:fontFamily">sans-serif</item>
+ </style>
+ <style name="TextAppearance.DeviceDefault.Title" parent="TextAppearance.Material.Title">
+ <item name="android:textSize">16sp</item>
+ <item name="android:fontFamily">google-sans</item>
+ <item name="android:textStyle">bold</item>
+ </style>
+ <style name="TextAppearance.DeviceDefault.Subhead" parent="TextAppearance.Material.Subhead">
+ <item name="android:textSize">16sp</item>
+ <item name="android:fontFamily">google-sans-medium</item>
+ </style>
+</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 819857f..1380165 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -9316,6 +9316,18 @@
<attr name="canPauseRecording" format="boolean" />
</declare-styleable>
+ <!-- Use <code>tv-iapp</code> as the root tag of the XML resource that describes a
+ {@link android.media.tv.interactive.TvIAppService}, which is referenced from its
+ {@link android.media.tv.interactive.TvIAppService#SERVICE_META_DATA} meta-data entry.
+ Described here are the attributes that can be included in that tag. -->
+ <declare-styleable name="TvIAppService">
+ <!-- The interactive app types that the TV interactive app service supports.
+ Reference to a string array resource that describes the supported types,
+ e.g. HbbTv, Ginga. -->
+ <attr name="supportedTypes" format="reference" />
+ </declare-styleable>
+
+
<!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the
XML resource that describes TV content rating of a {@link android.media.tv.TvInputService},
which is referenced from its
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 53ed0ec..2c60fbd8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1419,6 +1419,12 @@
<integer name="config_screenBrightnessDim">10</integer>
<item name="config_screenBrightnessDimFloat" format="float" type="dimen">0.05</item>
+ <!-- If the screen brightness is already set at or below config_screenBrightnessDim, and the
+ user activity timeout expires, we still want to dim the screen slightly to indicate that
+ the device is about to go to sleep. The screen will dim by this amount in that case.
+ -->
+ <item name="config_screenBrightnessMinimumDimAmountFloat" format="float" type="dimen">0.04</item>
+
<!-- Minimum allowable screen brightness to use in a very dark room.
This value sets the floor for the darkest possible auto-brightness
adjustment. It is expected to be somewhat less than the first entry in
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 2820f86..a2dadb9 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3304,6 +3304,7 @@
<public name="requiredSplitTypes" />
<public name="splitTypes" />
<public name="canDisplayOnRemoteDevices" />
+ <public name="supportedTypes" />
</staging-public-group>
<staging-public-group type="id" first-id="0x01de0000">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b0e4b1ff..12b1842 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2049,6 +2049,7 @@
<java-symbol type="dimen" name="config_screenBrightnessSettingDefaultFloat" />
<java-symbol type="dimen" name="config_screenBrightnessDozeFloat" />
<java-symbol type="dimen" name="config_screenBrightnessDimFloat" />
+ <java-symbol type="dimen" name="config_screenBrightnessMinimumDimAmountFloat" />
<java-symbol type="integer" name="config_screenBrightnessDark" />
<java-symbol type="integer" name="config_screenBrightnessDim" />
<java-symbol type="integer" name="config_screenBrightnessDoze" />
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 1f27063..5db6a3e 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -309,18 +309,22 @@
final int numOfConfig = activity.mNumOfConfigChanges;
final Configuration processConfigLandscape = new Configuration();
+ processConfigLandscape.orientation = ORIENTATION_LANDSCAPE;
processConfigLandscape.windowConfiguration.setBounds(new Rect(0, 0, 100, 60));
processConfigLandscape.seq = BASE_SEQ + 1;
final Configuration activityConfigLandscape = new Configuration();
+ activityConfigLandscape.orientation = ORIENTATION_LANDSCAPE;
activityConfigLandscape.windowConfiguration.setBounds(new Rect(0, 0, 100, 50));
activityConfigLandscape.seq = BASE_SEQ + 2;
final Configuration processConfigPortrait = new Configuration();
+ processConfigPortrait.orientation = ORIENTATION_PORTRAIT;
processConfigPortrait.windowConfiguration.setBounds(new Rect(0, 0, 60, 100));
processConfigPortrait.seq = BASE_SEQ + 3;
final Configuration activityConfigPortrait = new Configuration();
+ activityConfigPortrait.orientation = ORIENTATION_PORTRAIT;
activityConfigPortrait.windowConfiguration.setBounds(new Rect(0, 0, 50, 100));
activityConfigPortrait.seq = BASE_SEQ + 4;
@@ -348,7 +352,8 @@
assertEquals(activityConfigPortrait.windowConfiguration.getBounds(), bounds);
// Ensure that Activity#onConfigurationChanged() not be called because the changes in
- // WindowConfiguration shouldn't be reported.
+ // WindowConfiguration shouldn't be reported, and we only apply the latest Configuration
+ // update in transaction.
assertEquals(numOfConfig, activity.mNumOfConfigChanges);
}
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index df0c64c..207671e 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -453,7 +453,8 @@
boolean b2, boolean b3, Configuration configuration,
CompatibilityInfo compatibilityInfo, Map map, Bundle bundle1, String s1,
AutofillOptions ao, ContentCaptureOptions co, long[] disableCompatChanges,
- SharedMemory serializedSystemFontMap)
+ SharedMemory serializedSystemFontMap,
+ long startRequestedElapsedTime, long startRequestedUptime)
throws RemoteException {
}
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
index 0e78f87..33c6a4b 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
@@ -35,6 +35,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.os.SystemClock;
import android.util.SparseArray;
import android.view.Display;
import android.view.View;
@@ -299,7 +300,8 @@
SparseArray<List<AccessibilityWindowInfo>> allWindows = new SparseArray<>();
allWindows.put(Display.DEFAULT_DISPLAY, windowsIn1);
allWindows.put(SECONDARY_DISPLAY_ID, windowsIn2);
- mAccessibilityCache.setWindowsOnAllDisplays(allWindows);
+ final long populationTimeStamp = SystemClock.uptimeMillis();
+ mAccessibilityCache.setWindowsOnAllDisplays(allWindows, populationTimeStamp);
// Gets windows at default display.
windowsOut1 = getWindowsByDisplay(Display.DEFAULT_DISPLAY);
window1Out = mAccessibilityCache.getWindow(WINDOW_ID_1);
@@ -339,6 +341,46 @@
}
@Test
+ public void setInvalidWindowsAfterWindowsChangedEvent_notInCache() {
+ final AccessibilityEvent event = new AccessibilityEvent(
+ AccessibilityEvent.TYPE_WINDOWS_CHANGED);
+ final long eventTime = 1000L;
+ event.setEventTime(eventTime);
+ mAccessibilityCache.onAccessibilityEvent(event);
+
+ final AccessibilityWindowInfo windowInfo1 = obtainAccessibilityWindowInfo(WINDOW_ID_1,
+ SPECIFIC_WINDOW_LAYER);
+ List<AccessibilityWindowInfo> windowsIn = Arrays.asList(windowInfo1);
+ setWindowsByDisplay(Display.DEFAULT_DISPLAY, windowsIn, eventTime - 10);
+
+ try {
+ assertNull(getWindowsByDisplay(Display.DEFAULT_DISPLAY));
+ } finally {
+ windowInfo1.recycle();
+ }
+ }
+
+ @Test
+ public void setInvalidWindowsAfterStateChangedEvent_notInCache() {
+ final AccessibilityEvent event = new AccessibilityEvent(
+ AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ final long eventTime = 1000L;
+ event.setEventTime(eventTime);
+ mAccessibilityCache.onAccessibilityEvent(event);
+
+ final AccessibilityWindowInfo windowInfo1 = obtainAccessibilityWindowInfo(WINDOW_ID_1,
+ SPECIFIC_WINDOW_LAYER);
+ List<AccessibilityWindowInfo> windowsIn = Arrays.asList(windowInfo1);
+ setWindowsByDisplay(Display.DEFAULT_DISPLAY, windowsIn, eventTime - 10);
+
+ try {
+ assertNull(getWindowsByDisplay(Display.DEFAULT_DISPLAY));
+ } finally {
+ windowInfo1.recycle();
+ }
+ }
+
+ @Test
public void addWindowThenStateChangedEvent_noLongerInCache() {
putWindowWithWindowIdAndDisplayIdInCache(WINDOW_ID_1, Display.DEFAULT_DISPLAY,
DEFAULT_WINDOW_LAYER);
@@ -1063,9 +1105,14 @@
}
private void setWindowsByDisplay(int displayId, List<AccessibilityWindowInfo> windows) {
+ setWindowsByDisplay(displayId, windows, SystemClock.uptimeMillis());
+ }
+
+ private void setWindowsByDisplay(int displayId, List<AccessibilityWindowInfo> windows,
+ long populationTimeStamp) {
SparseArray<List<AccessibilityWindowInfo>> allWindows = new SparseArray<>();
allWindows.put(displayId, windows);
- mAccessibilityCache.setWindowsOnAllDisplays(allWindows);
+ mAccessibilityCache.setWindowsOnAllDisplays(allWindows, populationTimeStamp);
}
private List<AccessibilityWindowInfo> getWindowsByDisplay(int displayId) {
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
index 8b060ff..8ec33bf 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
@@ -16,7 +16,6 @@
package com.android.internal.os;
-import static android.os.BatteryStats.STATS_SINCE_CHARGED;
import static android.os.BatteryStats.Uid.NUM_PROCESS_STATE;
import static android.os.BatteryStats.Uid.PROCESS_STATE_BACKGROUND;
import static android.os.BatteryStats.Uid.PROCESS_STATE_CACHED;
@@ -25,8 +24,10 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
@@ -115,14 +116,17 @@
{989834, 384098, 98483, 23809, 4984},
{4859048, 348903, 4578967, 5973894, 298549}
};
+
+ final long[] timeInFreqs = new long[NUM_CPU_FREQS];
+
for (int i = 0; i < testUids.length; ++i) {
mockKernelSingleUidTimeReader(testUids[i], cpuTimes[i]);
// Verify there are no cpu times initially.
final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUids[i]);
for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
- assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
- assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
+ assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
}
}
addPendingUids(testUids, testProcStates);
@@ -134,13 +138,13 @@
for (int i = 0; i < testUids.length; ++i) {
final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
+ final boolean hasTimeInFreq = u.getCpuFreqTimes(timeInFreqs, procState);
if (procState == testProcStates[i]) {
- assertArrayEquals("Uid=" + testUids[i], cpuTimes[i],
- u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertArrayEquals("Uid=" + testUids[i], cpuTimes[i], timeInFreqs);
} else {
- assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertFalse(hasTimeInFreq);
}
- assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
}
}
@@ -172,12 +176,12 @@
for (int j = 0; j < expectedCpuTimes.length; ++j) {
expectedCpuTimes[j] += delta1[i][j];
}
- assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes,
- u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
+ assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, timeInFreqs);
} else {
- assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
}
- assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
}
}
@@ -214,13 +218,13 @@
for (int j = 0; j < expectedCpuTimes.length; ++j) {
expectedCpuTimes[j] += delta1[i][j] + delta2[i][j];
}
- assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes,
- u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
- assertArrayEquals("Uid=" + testUids[i], delta2[i],
- u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
+ assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, timeInFreqs);
+ assertTrue(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
+ assertArrayEquals("Uid=" + testUids[i], delta2[i], timeInFreqs);
} else {
- assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
- assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
+ assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
}
}
}
@@ -262,18 +266,18 @@
expectedCpuTimes[j] += delta1[i][j] + delta2[i][j] + delta3[i][j]
+ (testUids[i] == parentUid ? isolatedUidCpuTimes[j] : 0);
}
- assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes,
- u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
+ assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, timeInFreqs);
long[] expectedScreenOffTimes = delta2[i].clone();
for (int j = 0; j < expectedScreenOffTimes.length; ++j) {
expectedScreenOffTimes[j] += delta3[i][j]
+ (testUids[i] == parentUid ? isolatedUidCpuTimes[j] : 0);
}
- assertArrayEquals("Uid=" + testUids[i], expectedScreenOffTimes,
- u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertTrue(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
+ assertArrayEquals("Uid=" + testUids[i], expectedScreenOffTimes, timeInFreqs);
} else {
- assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
- assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
+ assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
}
}
}
@@ -329,16 +333,19 @@
mBatteryStatsImpl.copyFromAllUidsCpuTimes(true, false);
verifyNoPendingUids();
+
+ final long[] timeInFreqs = new long[NUM_CPU_FREQS];
+
for (int i = 0; i < testUids.length; ++i) {
final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
if (procState == testProcStates[i]) {
- assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes[i],
- u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
+ assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes[i], timeInFreqs);
} else {
- assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
}
- assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+ assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
}
}
}
diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
index 055fc71..db63e6e 100644
--- a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
+++ b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
@@ -160,6 +160,34 @@
verify(callback).onStateChanged(eq(mService.getBaseState()));
}
+ @Test
+ public void verifyDeviceStateRequestCallbacksCalled() {
+ DeviceStateRequest.Callback callback = mock(TestDeviceStateRequestCallback.class);
+
+ DeviceStateRequest request = DeviceStateRequest.newBuilder(OTHER_DEVICE_STATE).build();
+ mDeviceStateManagerGlobal.requestState(request,
+ ConcurrentUtils.DIRECT_EXECUTOR /* executor */,
+ callback /* callback */);
+
+ verify(callback).onRequestActivated(eq(request));
+ Mockito.reset(callback);
+
+ mDeviceStateManagerGlobal.cancelRequest(request);
+
+ verify(callback).onRequestCanceled(eq(request));
+ }
+
+ public static class TestDeviceStateRequestCallback implements DeviceStateRequest.Callback {
+ @Override
+ public void onRequestActivated(DeviceStateRequest request) { }
+
+ @Override
+ public void onRequestCanceled(DeviceStateRequest request) { }
+
+ @Override
+ public void onRequestSuspended(DeviceStateRequest request) { }
+ }
+
private static final class TestDeviceStateManagerService extends IDeviceStateManager.Stub {
public static final class Request {
public final IBinder token;
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index be1e2b2..88228f2 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-
// Sysconfig files
package {
@@ -119,6 +118,13 @@
}
prebuilt_etc {
+ name: "privapp_whitelist_com.android.intentresolver",
+ sub_dir: "permissions",
+ src: "com.android.intentresolver.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
name: "privapp_whitelist_com.android.launcher3",
system_ext_specific: true,
sub_dir: "permissions",
diff --git a/packages/SystemUI/res/drawable/assist_orb_navbar_scrim.xml b/data/etc/com.android.intentresolver.xml
similarity index 66%
rename from packages/SystemUI/res/drawable/assist_orb_navbar_scrim.xml
rename to data/etc/com.android.intentresolver.xml
index 52ed76d..0f1c467 100644
--- a/packages/SystemUI/res/drawable/assist_orb_navbar_scrim.xml
+++ b/data/etc/com.android.intentresolver.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-
<!--
- ~ Copyright (C) 2014 The Android Open Source Project
+ ~ 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.
@@ -15,11 +14,9 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <gradient
- android:type="linear"
- android:angle="90"
- android:startColor="#33000000"
- android:endColor="#00000000" />
-</shape>
\ No newline at end of file
+<permissions>
+ <privapp-permissions package="com.android.intentresolver">
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ </privapp-permissions>
+</permissions>
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java
index 194b633..89d7a40 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java
@@ -39,6 +39,8 @@
final Transformation mTransformation = new Transformation();
final float[] mMatrix = new float[9];
+ final float[] mVecs = new float[4];
+ final Rect mRect = new Rect();
private boolean mIsFirstFrame = true;
TaskFragmentAnimationAdapter(@NonNull Animation animation,
@@ -76,6 +78,22 @@
mTarget.localBounds.left, mTarget.localBounds.top);
t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix);
t.setAlpha(mLeash, mTransformation.getAlpha());
+
+ // Open/close animation may scale up the surface. Apply an inverse scale to the window crop
+ // so that it will not be covering other windows.
+ mVecs[1] = mVecs[2] = 0;
+ mVecs[0] = mVecs[3] = 1;
+ mTransformation.getMatrix().mapVectors(mVecs);
+ mVecs[0] = 1.f / mVecs[0];
+ mVecs[3] = 1.f / mVecs[3];
+ final Rect clipRect = mTarget.localBounds;
+ mRect.left = (int) (clipRect.left * mVecs[0] + 0.5f);
+ mRect.right = (int) (clipRect.right * mVecs[0] + 0.5f);
+ mRect.top = (int) (clipRect.top * mVecs[3] + 0.5f);
+ mRect.bottom = (int) (clipRect.bottom * mVecs[3] + 0.5f);
+ mRect.offsetTo(Math.round(mTarget.localBounds.width() * (1 - mVecs[0]) / 2.f),
+ Math.round(mTarget.localBounds.height() * (1 - mVecs[3]) / 2.f));
+ t.setWindowCrop(mLeash, mRect);
}
/** Called after animation finished. */
@@ -157,8 +175,6 @@
* Should be used for the animation of the {@link RemoteAnimationTarget} that has size change.
*/
static class BoundsChangeAdapter extends TaskFragmentAnimationAdapter {
- private final float[] mVecs = new float[4];
- private final Rect mRect = new Rect();
BoundsChangeAdapter(@NonNull Animation animation, @NonNull RemoteAnimationTarget target) {
super(animation, target);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
index 32d447e..fe9ce97 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
@@ -18,9 +18,12 @@
import static android.view.Display.DEFAULT_DISPLAY;
+import static androidx.window.common.DisplayFeature.COMMON_STATE_FLAT;
+import static androidx.window.common.DisplayFeature.COMMON_STATE_HALF_OPENED;
import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation;
import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect;
+import android.annotation.Nullable;
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
@@ -119,22 +122,45 @@
return !mWindowLayoutChangeListeners.isEmpty();
}
- private int getFeatureState(DisplayFeature feature) {
+ /**
+ * Calculate the {@link DisplayFeature.State} from the feature or the device posture producer.
+ * If the given {@link DisplayFeature.State} is not valid then {@code null} will be returned.
+ * The {@link FoldingFeature} should be ignored in the case of an invalid
+ * {@link DisplayFeature.State}.
+ *
+ * @param feature a {@link DisplayFeature} to provide the feature state if present.
+ * @return {@link DisplayFeature.State} of the hinge if present or the state from the posture
+ * produce if present.
+ */
+ @Nullable
+ private Integer getFeatureState(DisplayFeature feature) {
Integer featureState = feature.getState();
Optional<Integer> posture = mDevicePostureProducer.getData();
- int fallbackPosture = posture.orElse(DisplayFeature.COMMON_STATE_FLAT);
- int displayFeatureState = featureState == null ? fallbackPosture : featureState;
- return convertToExtensionState(displayFeatureState);
+ Integer state = featureState == null ? posture.orElse(null) : featureState;
+ return convertToExtensionState(state);
}
- private int convertToExtensionState(int state) {
- switch (state) {
- case DisplayFeature.COMMON_STATE_FLAT:
- return FoldingFeature.STATE_FLAT;
- case DisplayFeature.COMMON_STATE_HALF_OPENED:
- return FoldingFeature.STATE_HALF_OPENED;
+ /**
+ * A convenience method to translate from the common feature state to the extensions feature
+ * state. More specifically, translates from {@link DisplayFeature.State} to
+ * {@link FoldingFeature.STATE_FLAT} or {@link FoldingFeature.STATE_HALF_OPENED}. If it is not
+ * possible to translate, then we will return a {@code null} value.
+ *
+ * @param state if it matches a value in {@link DisplayFeature.State}, {@code null} otherwise.
+ * @return a {@link FoldingFeature.STATE_FLAT} or {@link FoldingFeature.STATE_HALF_OPENED} if
+ * the given state matches a value in {@link DisplayFeature.State} and {@code null} otherwise.
+ */
+ @Nullable
+ private Integer convertToExtensionState(@Nullable Integer state) {
+ if (state == null) { // The null check avoids a NullPointerException.
+ return null;
+ } else if (state == COMMON_STATE_FLAT) {
+ return FoldingFeature.STATE_FLAT;
+ } else if (state == COMMON_STATE_HALF_OPENED) {
+ return FoldingFeature.STATE_HALF_OPENED;
+ } else {
+ return null;
}
- return FoldingFeature.STATE_FLAT;
}
private void onDisplayFeaturesChanged() {
@@ -151,6 +177,25 @@
return new WindowLayoutInfo(displayFeatures);
}
+ /**
+ * Translate from the {@link DisplayFeature} to
+ * {@link androidx.window.extensions.layout.DisplayFeature} for a given {@link Activity}. If a
+ * {@link DisplayFeature} is not valid then it will be omitted.
+ *
+ * For a {@link FoldingFeature} the bounds are localized into the {@link Activity} window
+ * coordinate space and the state is calculated either from {@link DisplayFeature#getState()} or
+ * {@link #mDisplayFeatureProducer}. The state from {@link #mDisplayFeatureProducer} may not be
+ * valid since {@link #mDisplayFeatureProducer} is a general state controller. If the state is
+ * not valid, the {@link FoldingFeature} is omitted from the {@link List} of
+ * {@link androidx.window.extensions.layout.DisplayFeature}. If the bounds are not valid,
+ * constructing a {@link FoldingFeature} will throw an {@link IllegalArgumentException} since
+ * this can cause negative UI effects down stream.
+ *
+ * @param activity a proxy for the {@link android.view.Window} that contains the
+ * {@link androidx.window.extensions.layout.DisplayFeature}.
+ * @return a {@link List} of valid {@link androidx.window.extensions.layout.DisplayFeature} that
+ * are within the {@link android.view.Window} of the {@link Activity}
+ */
private List<androidx.window.extensions.layout.DisplayFeature> getDisplayFeatures(
@NonNull Activity activity) {
List<androidx.window.extensions.layout.DisplayFeature> features = new ArrayList<>();
@@ -170,6 +215,10 @@
if (storedFeatures.isPresent()) {
for (DisplayFeature baseFeature : storedFeatures.get()) {
+ Integer state = getFeatureState(baseFeature);
+ if (state == null) {
+ continue;
+ }
Rect featureRect = baseFeature.getRect();
rotateRectToDisplayRotation(displayId, featureRect);
transformToWindowSpaceRect(activity, featureRect);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
index f567877..c3ce362 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
@@ -74,7 +74,7 @@
Optional<PipTouchHandler> pipTouchHandlerOptional,
FullscreenTaskListener fullscreenTaskListener,
Optional<FullscreenUnfoldController> fullscreenUnfoldTransitionController,
- Optional<Optional<FreeformTaskListener>> freeformTaskListenerOptional,
+ Optional<FreeformTaskListener> freeformTaskListenerOptional,
Optional<RecentTasksController> recentTasks,
Transitions transitions,
StartingWindowController startingWindow,
@@ -90,7 +90,7 @@
mFullscreenTaskListener = fullscreenTaskListener;
mPipTouchHandlerOptional = pipTouchHandlerOptional;
mFullscreenUnfoldController = fullscreenUnfoldTransitionController;
- mFreeformTaskListenerOptional = freeformTaskListenerOptional.flatMap(f -> f);
+ mFreeformTaskListenerOptional = freeformTaskListenerOptional;
mRecentTasks = recentTasks;
mTransitions = transitions;
mMainExecutor = mainExecutor;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/DynamicOverride.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/DynamicOverride.java
new file mode 100644
index 0000000..806f795
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/DynamicOverride.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.dagger;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.inject.Qualifier;
+
+/**
+ * This is a qualifier that Shell uses to workaround an issue with providing nullable optionals
+ * which are by default unbound.
+ *
+ * For example, ideally we would have this scenario:
+ * BaseModule:
+ * @BindsOptionalOf
+ * abstract Optional<Interface> optionalInterface();
+ *
+ * SpecializedModule:
+ * @Provides
+ * static Interface providesInterface() {
+ * return new InterfaceImpl();
+ * }
+ *
+ * However, if the interface is supposed to be provided dynamically, then Dagger is not able to bind
+ * the optional interface to a null instance, and @BindsOptionalOf does not support @Nullable
+ * instances of the interface provided by the specialized module.
+ *
+ * For example, this does not work:
+ * BaseModule:
+ * @BindsOptionalOf
+ * abstract Optional<Interface> optionalInterface();
+ *
+ * SpecializedModule:
+ * @Provides
+ * static Interface providesInterface() {
+ * if (systemSupportsInterfaceFeature) {
+ * return new InterfaceImpl();
+ * } else {
+ * return null;
+ * }
+ * }
+ *
+ * To workaround this, we can instead upstream the check (assuming it can be upstreamed into the
+ * base module), and then always provide a non-null instance in the specialized module.
+ *
+ * For example:
+ * BaseModule:
+ * @BindsOptionalOf
+ * @DynamicOverride
+ * abstract Interface dynamicInterface();
+ *
+ * @Provides
+ * static Optional<Interface> providesOptionalInterface(
+ * @DynamicOverride Optional<Interface> interface) {
+ * if (systemSupportsInterfaceFeature) {
+ * return interface;
+ * }
+ * return Optional.empty();
+ * }
+ *
+ * SpecializedModule:
+ * @Provides
+ * @DynamicOverride
+ * static Interface providesInterface() {
+ * return new InterfaceImpl();
+ * }
+ *
+ * This is also useful in cases where there needs to be a default implementation in the base module
+ * which is also overridable in the specialized module. This isn't generally recommended, but
+ * due to the nature of Shell modules being referenced from a number of various projects, this
+ * can be useful for *required* components that
+ * 1) clearly identifies which are intended for overriding in the base module, and
+ * 2) allows us to declare a default implementation in the base module, without having to force
+ * every SysUI impl to explicitly provide it (if a large number of them share the default impl)
+ *
+ * For example, this uses the same setup as above, but the interface provided (if bound) is used
+ * otherwise the default is created:
+ * @BindsOptionalOf
+ * @DynamicOverride
+ * abstract Interface dynamicInterface();
+ *
+ * @Provides
+ * static Optional<Interface> providesOptionalInterface(
+ * @DynamicOverride Optional<Interface> overrideInterfaceImpl) {
+ * if (overrideInterfaceImpl.isPresent()) {
+ * return overrideInterfaceImpl.get();
+ * }
+ * return new DefaultImpl();
+ * }
+ *
+ * SpecializedModule:
+ * @Provides
+ * @DynamicOverride
+ * static Interface providesInterface() {
+ * return new SuperSpecialImpl();
+ * }
+ */
+@Documented
+@Inherited
+@Qualifier
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DynamicOverride {}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
index 6997d60..15bfeb2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
@@ -16,25 +16,16 @@
package com.android.wm.shell.dagger;
-import android.animation.AnimationHandler;
-import android.content.Context;
import android.view.IWindowManager;
-import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.common.SystemWindows;
-import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.TransactionPool;
-import com.android.wm.shell.common.annotations.ChoreographerSfVsync;
import com.android.wm.shell.common.annotations.ShellMainThread;
-import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm;
import com.android.wm.shell.startingsurface.tv.TvStartingWindowTypeAlgorithm;
-import com.android.wm.shell.transition.Transitions;
import dagger.Module;
import dagger.Provides;
@@ -51,42 +42,12 @@
public class TvWMShellModule {
//
- // Internal common - Components used internally by multiple shell features
- //
-
- @WMSingleton
- @Provides
- static DisplayImeController provideDisplayImeController(IWindowManager wmService,
- DisplayController displayController, DisplayInsetsController displayInsetsController,
- @ShellMainThread ShellExecutor mainExecutor, TransactionPool transactionPool) {
- return new DisplayImeController(wmService, displayController, displayInsetsController,
- mainExecutor, transactionPool);
- }
-
- //
- // Split/multiwindow
- //
-
- @WMSingleton
- @Provides
- static LegacySplitScreenController provideSplitScreen(Context context,
- DisplayController displayController, SystemWindows systemWindows,
- DisplayImeController displayImeController, TransactionPool transactionPool,
- ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
- TaskStackListenerImpl taskStackListener, Transitions transitions,
- @ShellMainThread ShellExecutor mainExecutor,
- @ChoreographerSfVsync AnimationHandler sfVsyncAnimationHandler) {
- return new LegacySplitScreenController(context, displayController, systemWindows,
- displayImeController, transactionPool, shellTaskOrganizer, syncQueue,
- taskStackListener, transitions, mainExecutor, sfVsyncAnimationHandler);
- }
-
- //
// Starting Windows (Splash Screen)
//
@WMSingleton
@Provides
+ @DynamicOverride
static StartingWindowTypeAlgorithm provideStartingWindowTypeAlgorithm() {
return new TvStartingWindowTypeAlgorithm();
};
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index ac2e448..3f5b70b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -16,16 +16,16 @@
package com.android.wm.shell.dagger;
+import static com.android.wm.shell.onehanded.OneHandedController.SUPPORT_ONE_HANDED_MODE;
+
import android.app.ActivityTaskManager;
import android.content.Context;
-import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.os.Handler;
+import android.os.SystemProperties;
import android.view.IWindowManager;
-import android.view.WindowManager;
import com.android.internal.logging.UiEventLogger;
-import com.android.internal.statusbar.IStatusBarService;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.RootDisplayAreaOrganizer;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
@@ -77,23 +77,19 @@
import com.android.wm.shell.sizecompatui.SizeCompatUIController;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreenController;
-import com.android.wm.shell.splitscreen.StageTaskUnfoldController;
import com.android.wm.shell.startingsurface.StartingSurface;
import com.android.wm.shell.startingsurface.StartingWindowController;
import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm;
+import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm;
import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper;
import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelperController;
import com.android.wm.shell.transition.ShellTransitions;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
-import com.android.wm.shell.unfold.UnfoldBackgroundController;
import java.util.Optional;
-import javax.inject.Provider;
-
import dagger.BindsOptionalOf;
-import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
@@ -128,6 +124,28 @@
return new DisplayInsetsController(wmService, displayController, mainExecutor);
}
+ // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
+ @BindsOptionalOf
+ @DynamicOverride
+ abstract DisplayImeController optionalDisplayImeController();
+
+ @WMSingleton
+ @Provides
+ static DisplayImeController provideDisplayImeController(
+ @DynamicOverride Optional<DisplayImeController> overrideDisplayImeController,
+ IWindowManager wmService,
+ DisplayController displayController,
+ DisplayInsetsController displayInsetsController,
+ @ShellMainThread ShellExecutor mainExecutor,
+ TransactionPool transactionPool
+ ) {
+ if (overrideDisplayImeController.isPresent()) {
+ return overrideDisplayImeController.get();
+ }
+ return new DisplayImeController(wmService, displayController, displayInsetsController,
+ mainExecutor, transactionPool);
+ }
+
@WMSingleton
@Provides
static DisplayLayout provideDisplayLayout() {
@@ -202,7 +220,7 @@
}
//
- // Bubbles
+ // Bubbles (optional feature)
//
@WMSingleton
@@ -211,27 +229,8 @@
return bubbleController.map((controller) -> controller.asBubbles());
}
- // Note: Handler needed for LauncherApps.register
- @WMSingleton
- @Provides
- static Optional<BubbleController> provideBubbleController(Context context,
- FloatingContentCoordinator floatingContentCoordinator,
- IStatusBarService statusBarService,
- WindowManager windowManager,
- WindowManagerShellWrapper windowManagerShellWrapper,
- LauncherApps launcherApps,
- TaskStackListenerImpl taskStackListener,
- UiEventLogger uiEventLogger,
- ShellTaskOrganizer organizer,
- DisplayController displayController,
- @ShellMainThread ShellExecutor mainExecutor,
- @ShellMainThread Handler mainHandler,
- SyncTransactionQueue syncQueue) {
- return Optional.of(BubbleController.create(context, null /* synchronizer */,
- floatingContentCoordinator, statusBarService, windowManager,
- windowManagerShellWrapper, launcherApps, taskStackListener,
- uiEventLogger, organizer, displayController, mainExecutor, mainHandler, syncQueue));
- }
+ @BindsOptionalOf
+ abstract BubbleController optionalBubblesController();
//
// Fullscreen
@@ -252,59 +251,45 @@
// Unfold transition
//
+ @BindsOptionalOf
+ abstract ShellUnfoldProgressProvider optionalShellUnfoldProgressProvider();
+
+ // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
+ @BindsOptionalOf
+ @DynamicOverride
+ abstract FullscreenUnfoldController optionalFullscreenUnfoldController();
+
@WMSingleton
@Provides
static Optional<FullscreenUnfoldController> provideFullscreenUnfoldController(
- Context context,
- Optional<ShellUnfoldProgressProvider> progressProvider,
- Lazy<UnfoldBackgroundController> unfoldBackgroundController,
- DisplayInsetsController displayInsetsController,
- @ShellMainThread ShellExecutor mainExecutor
- ) {
- return progressProvider.map(shellUnfoldTransitionProgressProvider ->
- new FullscreenUnfoldController(context, mainExecutor,
- unfoldBackgroundController.get(), shellUnfoldTransitionProgressProvider,
- displayInsetsController));
- }
-
- @Provides
- static Optional<StageTaskUnfoldController> provideStageTaskUnfoldController(
- Optional<ShellUnfoldProgressProvider> progressProvider,
- Context context,
- TransactionPool transactionPool,
- Lazy<UnfoldBackgroundController> unfoldBackgroundController,
- DisplayInsetsController displayInsetsController,
- @ShellMainThread ShellExecutor mainExecutor
- ) {
- return progressProvider.map(shellUnfoldTransitionProgressProvider ->
- new StageTaskUnfoldController(
- context,
- transactionPool,
- shellUnfoldTransitionProgressProvider,
- displayInsetsController,
- unfoldBackgroundController.get(),
- mainExecutor
- ));
- }
-
- @WMSingleton
- @Provides
- static UnfoldBackgroundController provideUnfoldBackgroundController(
- RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
- Context context
- ) {
- return new UnfoldBackgroundController(
- context,
- rootTaskDisplayAreaOrganizer
- );
+ @DynamicOverride Optional<FullscreenUnfoldController> fullscreenUnfoldController,
+ Optional<ShellUnfoldProgressProvider> progressProvider) {
+ if (progressProvider.isPresent()
+ && progressProvider.get() != ShellUnfoldProgressProvider.NO_PROVIDER) {
+ return fullscreenUnfoldController;
+ }
+ return Optional.empty();
}
//
// Freeform (optional feature)
//
+ // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
@BindsOptionalOf
- abstract Optional<FreeformTaskListener> optionalFreeformTaskListener();
+ @DynamicOverride
+ abstract FreeformTaskListener optionalFreeformTaskListener();
+
+ @WMSingleton
+ @Provides
+ static Optional<FreeformTaskListener> provideFreeformTaskListener(
+ @DynamicOverride Optional<FreeformTaskListener> freeformTaskListener,
+ Context context) {
+ if (FreeformTaskListener.isFreeformEnabled(context)) {
+ return freeformTaskListener;
+ }
+ return Optional.empty();
+ }
//
// Hide display cutout
@@ -335,20 +320,22 @@
return oneHandedController.map((controller) -> controller.asOneHanded());
}
- // Needs the shell main handler for ContentObserver callbacks
+ // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
+ @BindsOptionalOf
+ @DynamicOverride
+ abstract OneHandedController optionalOneHandedController();
+
@WMSingleton
@Provides
- static Optional<OneHandedController> provideOneHandedController(Context context,
- WindowManager windowManager, DisplayController displayController,
- DisplayLayout displayLayout, TaskStackListenerImpl taskStackListener,
- UiEventLogger uiEventLogger,
- @ShellMainThread ShellExecutor mainExecutor,
- @ShellMainThread Handler mainHandler) {
- return Optional.ofNullable(OneHandedController.create(context, windowManager,
- displayController, displayLayout, taskStackListener, uiEventLogger, mainExecutor,
- mainHandler));
+ static Optional<OneHandedController> providesOneHandedController(
+ @DynamicOverride Optional<OneHandedController> oneHandedController) {
+ if (!SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
+ return oneHandedController;
+ }
+ return Optional.empty();
}
+
//
// Task to Surface communication
//
@@ -366,15 +353,6 @@
return Optional.ofNullable(new TaskSurfaceHelperController(taskOrganizer, mainExecutor));
}
- @WMSingleton
- @Provides
- static Optional<DisplayAreaHelper> provideDisplayAreaHelper(
- @ShellMainThread ShellExecutor mainExecutor,
- RootDisplayAreaOrganizer rootDisplayAreaOrganizer) {
- return Optional.ofNullable(new DisplayAreaHelperController(mainExecutor,
- rootDisplayAreaOrganizer));
- }
-
//
// Pip (optional feature)
//
@@ -460,7 +438,7 @@
}
//
- // Split/multiwindow
+ // Display areas
//
@WMSingleton
@@ -479,31 +457,38 @@
@WMSingleton
@Provides
+ static Optional<DisplayAreaHelper> provideDisplayAreaHelper(
+ @ShellMainThread ShellExecutor mainExecutor,
+ RootDisplayAreaOrganizer rootDisplayAreaOrganizer) {
+ return Optional.of(new DisplayAreaHelperController(mainExecutor,
+ rootDisplayAreaOrganizer));
+ }
+
+ //
+ // Splitscreen (optional feature)
+ //
+
+ @WMSingleton
+ @Provides
static Optional<SplitScreen> provideSplitScreen(
Optional<SplitScreenController> splitScreenController) {
return splitScreenController.map((controller) -> controller.asSplitScreen());
}
+ // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
+ @BindsOptionalOf
+ @DynamicOverride
+ abstract SplitScreenController optionalSplitScreenController();
+
@WMSingleton
@Provides
- static Optional<SplitScreenController> provideSplitScreenController(
- ShellTaskOrganizer shellTaskOrganizer,
- SyncTransactionQueue syncQueue, Context context,
- RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
- @ShellMainThread ShellExecutor mainExecutor,
- DisplayImeController displayImeController,
- DisplayInsetsController displayInsetsController, Transitions transitions,
- TransactionPool transactionPool, IconProvider iconProvider,
- Optional<RecentTasksController> recentTasks,
- Provider<Optional<StageTaskUnfoldController>> stageTaskUnfoldControllerProvider) {
+ static Optional<SplitScreenController> providesSplitScreenController(
+ @DynamicOverride Optional<SplitScreenController> splitscreenController,
+ Context context) {
if (ActivityTaskManager.supportsSplitScreenMultiWindow(context)) {
- return Optional.of(new SplitScreenController(shellTaskOrganizer, syncQueue, context,
- rootTaskDisplayAreaOrganizer, mainExecutor, displayImeController,
- displayInsetsController, transitions, transactionPool, iconProvider,
- recentTasks, stageTaskUnfoldControllerProvider));
- } else {
- return Optional.empty();
+ return splitscreenController;
}
+ return Optional.empty();
}
// Legacy split (optional feature)
@@ -529,7 +514,9 @@
@BindsOptionalOf
abstract AppPairsController optionalAppPairs();
+ //
// Starting window
+ //
@WMSingleton
@Provides
@@ -548,6 +535,23 @@
startingWindowTypeAlgorithm, iconProvider, pool);
}
+ // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
+ @BindsOptionalOf
+ @DynamicOverride
+ abstract StartingWindowTypeAlgorithm optionalStartingWindowTypeAlgorithm();
+
+ @WMSingleton
+ @Provides
+ static StartingWindowTypeAlgorithm provideStartingWindowTypeAlgorithm(
+ @DynamicOverride Optional<StartingWindowTypeAlgorithm> startingWindowTypeAlgorithm
+ ) {
+ if (startingWindowTypeAlgorithm.isPresent()) {
+ return startingWindowTypeAlgorithm.get();
+ }
+ // Default to phone starting window type
+ return new PhoneStartingWindowTypeAlgorithm();
+ }
+
//
// Task view factory
//
@@ -591,7 +595,7 @@
Optional<PipTouchHandler> pipTouchHandlerOptional,
FullscreenTaskListener fullscreenTaskListener,
Optional<FullscreenUnfoldController> appUnfoldTransitionController,
- Optional<Optional<FreeformTaskListener>> freeformTaskListener,
+ Optional<FreeformTaskListener> freeformTaskListener,
Optional<RecentTasksController> recentTasksOptional,
Transitions transitions,
StartingWindowController startingWindow,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index ec70147..46c7b50 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -18,15 +18,22 @@
import android.animation.AnimationHandler;
import android.content.Context;
+import android.content.pm.LauncherApps;
import android.os.Handler;
-import android.view.IWindowManager;
+import android.view.WindowManager;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.launcher3.icons.IconProvider;
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.apppairs.AppPairsController;
+import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
@@ -36,6 +43,7 @@
import com.android.wm.shell.common.annotations.ChoreographerSfVsync;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.freeform.FreeformTaskListener;
+import com.android.wm.shell.fullscreen.FullscreenUnfoldController;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.Pip;
@@ -55,13 +63,18 @@
import com.android.wm.shell.pip.phone.PipController;
import com.android.wm.shell.pip.phone.PipMotionHelper;
import com.android.wm.shell.pip.phone.PipTouchHandler;
+import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.splitscreen.SplitScreenController;
-import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm;
-import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm;
+import com.android.wm.shell.splitscreen.StageTaskUnfoldController;
import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
+import com.android.wm.shell.unfold.UnfoldBackgroundController;
import java.util.Optional;
+import javax.inject.Provider;
+
+import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
@@ -77,17 +90,29 @@
public class WMShellModule {
//
- // Internal common - Components used internally by multiple shell features
+ // Bubbles
//
+ // Note: Handler needed for LauncherApps.register
@WMSingleton
@Provides
- static DisplayImeController provideDisplayImeController(IWindowManager wmService,
- DisplayController displayController, DisplayInsetsController displayInsetsController,
+ static BubbleController provideBubbleController(Context context,
+ FloatingContentCoordinator floatingContentCoordinator,
+ IStatusBarService statusBarService,
+ WindowManager windowManager,
+ WindowManagerShellWrapper windowManagerShellWrapper,
+ LauncherApps launcherApps,
+ TaskStackListenerImpl taskStackListener,
+ UiEventLogger uiEventLogger,
+ ShellTaskOrganizer organizer,
+ DisplayController displayController,
@ShellMainThread ShellExecutor mainExecutor,
- TransactionPool transactionPool) {
- return new DisplayImeController(wmService, displayController, displayInsetsController,
- mainExecutor, transactionPool);
+ @ShellMainThread Handler mainHandler,
+ SyncTransactionQueue syncQueue) {
+ return BubbleController.create(context, null /* synchronizer */,
+ floatingContentCoordinator, statusBarService, windowManager,
+ windowManagerShellWrapper, launcherApps, taskStackListener,
+ uiEventLogger, organizer, displayController, mainExecutor, mainHandler, syncQueue);
}
//
@@ -96,16 +121,55 @@
@WMSingleton
@Provides
- static Optional<FreeformTaskListener> provideFreeformTaskListener(
- Context context,
+ @DynamicOverride
+ static FreeformTaskListener provideFreeformTaskListener(
SyncTransactionQueue syncQueue) {
- return Optional.ofNullable(FreeformTaskListener.create(context, syncQueue));
+ return new FreeformTaskListener(syncQueue);
}
//
- // Split/multiwindow
+ // One handed mode
//
+
+ // Needs the shell main handler for ContentObserver callbacks
+ @WMSingleton
+ @Provides
+ @DynamicOverride
+ static OneHandedController provideOneHandedController(Context context,
+ WindowManager windowManager, DisplayController displayController,
+ DisplayLayout displayLayout, TaskStackListenerImpl taskStackListener,
+ UiEventLogger uiEventLogger,
+ @ShellMainThread ShellExecutor mainExecutor,
+ @ShellMainThread Handler mainHandler) {
+ return OneHandedController.create(context, windowManager,
+ displayController, displayLayout, taskStackListener, uiEventLogger, mainExecutor,
+ mainHandler);
+ }
+
+ //
+ // Splitscreen
+ //
+
+ @WMSingleton
+ @Provides
+ @DynamicOverride
+ static SplitScreenController provideSplitScreenController(
+ ShellTaskOrganizer shellTaskOrganizer,
+ SyncTransactionQueue syncQueue, Context context,
+ RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
+ @ShellMainThread ShellExecutor mainExecutor,
+ DisplayImeController displayImeController,
+ DisplayInsetsController displayInsetsController, Transitions transitions,
+ TransactionPool transactionPool, IconProvider iconProvider,
+ Optional<RecentTasksController> recentTasks,
+ Provider<Optional<StageTaskUnfoldController>> stageTaskUnfoldControllerProvider) {
+ return new SplitScreenController(shellTaskOrganizer, syncQueue, context,
+ rootTaskDisplayAreaOrganizer, mainExecutor, displayImeController,
+ displayInsetsController, transitions, transactionPool, iconProvider,
+ recentTasks, stageTaskUnfoldControllerProvider);
+ }
+
@WMSingleton
@Provides
static LegacySplitScreenController provideLegacySplitScreen(Context context,
@@ -258,12 +322,53 @@
}
//
- // Starting Windows (Splash Screen)
+ // Unfold transition
//
@WMSingleton
@Provides
- static StartingWindowTypeAlgorithm provideStartingWindowTypeAlgorithm() {
- return new PhoneStartingWindowTypeAlgorithm();
+ @DynamicOverride
+ static FullscreenUnfoldController provideFullscreenUnfoldController(
+ Context context,
+ Optional<ShellUnfoldProgressProvider> progressProvider,
+ Lazy<UnfoldBackgroundController> unfoldBackgroundController,
+ DisplayInsetsController displayInsetsController,
+ @ShellMainThread ShellExecutor mainExecutor
+ ) {
+ return new FullscreenUnfoldController(context, mainExecutor,
+ unfoldBackgroundController.get(), progressProvider.get(),
+ displayInsetsController);
+ }
+
+ @Provides
+ static Optional<StageTaskUnfoldController> provideStageTaskUnfoldController(
+ Optional<ShellUnfoldProgressProvider> progressProvider,
+ Context context,
+ TransactionPool transactionPool,
+ Lazy<UnfoldBackgroundController> unfoldBackgroundController,
+ DisplayInsetsController displayInsetsController,
+ @ShellMainThread ShellExecutor mainExecutor
+ ) {
+ return progressProvider.map(shellUnfoldTransitionProgressProvider ->
+ new StageTaskUnfoldController(
+ context,
+ transactionPool,
+ shellUnfoldTransitionProgressProvider,
+ displayInsetsController,
+ unfoldBackgroundController.get(),
+ mainExecutor
+ ));
+ }
+
+ @WMSingleton
+ @Provides
+ static UnfoldBackgroundController provideUnfoldBackgroundController(
+ RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
+ Context context
+ ) {
+ return new UnfoldBackgroundController(
+ context,
+ rootTaskDisplayAreaOrganizer
+ );
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index 0c12d6c..d2b4711 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -19,6 +19,7 @@
import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY;
import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT;
import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.DragEvent.ACTION_DRAG_ENDED;
import static android.view.DragEvent.ACTION_DRAG_ENTERED;
import static android.view.DragEvent.ACTION_DRAG_EXITED;
@@ -34,13 +35,13 @@
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.Display;
import android.view.DragEvent;
import android.view.LayoutInflater;
import android.view.SurfaceControl;
@@ -55,7 +56,6 @@
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
-import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreenController;
import java.util.Optional;
@@ -91,6 +91,11 @@
@Override
public void onDisplayAdded(int displayId) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Display added: %d", displayId);
+ if (displayId != DEFAULT_DISPLAY) {
+ // Ignore non-default displays for now
+ return;
+ }
+
final Context context = mDisplayController.getDisplayContext(displayId)
.createWindowContext(TYPE_APPLICATION_OVERLAY, null);
final WindowManager wm = context.getSystemService(WindowManager.class);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index 8a8d7c6..5c8e7d0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -141,16 +141,4 @@
|| Settings.Global.getInt(context.getContentResolver(),
DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
}
-
- /**
- * Creates {@link FreeformTaskListener} if freeform is enabled.
- */
- public static FreeformTaskListener create(Context context,
- SyncTransactionQueue syncQueue) {
- if (!isFreeformEnabled(context)) {
- return null;
- }
-
- return new FreeformTaskListener(syncQueue);
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
index 80ab166..67e487d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
@@ -172,6 +172,14 @@
};
mWindowManager = new DividerWindowManager(mSystemWindows);
+
+ // No need to listen to display window container or create root tasks if the device is not
+ // using legacy split screen.
+ if (!context.getResources().getBoolean(com.android.internal.R.bool.config_useLegacySplit)) {
+ return;
+ }
+
+
mDisplayController.addDisplayWindowListener(this);
// Don't initialize the divider or anything until we get the default display.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index 90074371..e068614 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -46,7 +46,6 @@
import android.window.WindowContainerTransaction;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.UiEventLogger;
@@ -76,7 +75,7 @@
private static final int OVERLAY_ENABLED_DELAY_MS = 250;
private static final int DISPLAY_AREA_READY_RETRY_MS = 10;
- static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
+ public static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
private volatile boolean mIsOneHandedEnabled;
private volatile boolean mIsSwipeToNotificationEnabled;
@@ -198,16 +197,10 @@
/**
* Creates {@link OneHandedController}, returns {@code null} if the feature is not supported.
*/
- @Nullable
public static OneHandedController create(
Context context, WindowManager windowManager, DisplayController displayController,
DisplayLayout displayLayout, TaskStackListenerImpl taskStackListener,
UiEventLogger uiEventLogger, ShellExecutor mainExecutor, Handler mainHandler) {
- if (!SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
- Slog.w(TAG, "Device doesn't support OneHanded feature");
- return null;
- }
-
OneHandedSettingsUtil settingsUtil = new OneHandedSettingsUtil();
OneHandedAccessibilityUtil accessibilityUtil = new OneHandedAccessibilityUtil(context);
OneHandedTimeoutHandler timeoutHandler = new OneHandedTimeoutHandler(mainExecutor);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 7457be2..8af72a8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -130,19 +130,6 @@
private StageCoordinator mStageCoordinator;
- // TODO(b/205019015): Remove after we clean up downstream modules
- public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer,
- SyncTransactionQueue syncQueue, Context context,
- RootTaskDisplayAreaOrganizer rootTDAOrganizer,
- ShellExecutor mainExecutor, DisplayImeController displayImeController,
- DisplayInsetsController displayInsetsController,
- Transitions transitions, TransactionPool transactionPool, IconProvider iconProvider,
- Provider<Optional<StageTaskUnfoldController>> unfoldControllerProvider) {
- this(shellTaskOrganizer, syncQueue, context, rootTDAOrganizer, mainExecutor,
- displayImeController, displayInsetsController, transitions, transactionPool,
- iconProvider, Optional.empty(), unfoldControllerProvider);
- }
-
public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer,
SyncTransactionQueue syncQueue, Context context,
RootTaskDisplayAreaOrganizer rootTDAOrganizer,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 050d255..d494191 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -78,7 +78,6 @@
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
-import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.InstanceId;
import com.android.internal.protolog.common.ProtoLog;
@@ -157,10 +156,6 @@
private boolean mExitSplitScreenOnHide;
private boolean mKeyguardOccluded;
- // TODO(b/187041611): remove this flag after totally deprecated legacy split
- /** Whether the device is supporting legacy split or not. */
- private boolean mUseLegacySplit;
-
@SplitScreen.StageType
private int mDismissTop = NO_DISMISS;
@@ -735,17 +730,9 @@
private void onStageRootTaskAppeared(StageListenerImpl stageListener) {
if (mMainStageListener.mHasRootTask && mSideStageListener.mHasRootTask) {
- mUseLegacySplit = mContext.getResources().getBoolean(R.bool.config_useLegacySplit);
final WindowContainerTransaction wct = new WindowContainerTransaction();
// Make the stages adjacent to each other so they occlude what's behind them.
wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token);
-
- // Only sets side stage as launch-adjacent-flag-root when the device is not using legacy
- // split to prevent new split behavior confusing users.
- if (!mUseLegacySplit) {
- wct.setLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token);
- }
-
mTaskOrganizer.applyTransaction(wct);
}
}
@@ -755,11 +742,6 @@
final WindowContainerTransaction wct = new WindowContainerTransaction();
// Deactivate the main stage if it no longer has a root task.
mMainStage.deactivate(wct);
-
- if (!mUseLegacySplit) {
- wct.clearLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token);
- }
-
mTaskOrganizer.applyTransaction(wct);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 190006e..62b8638 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -37,6 +37,7 @@
import androidx.annotation.NonNull;
+import com.android.internal.R;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.SurfaceUtils;
@@ -102,7 +103,12 @@
mSurfaceSession = surfaceSession;
mIconProvider = iconProvider;
mStageTaskUnfoldController = stageTaskUnfoldController;
- taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this);
+
+ // No need to create root task if the device is using legacy split screen.
+ // TODO(b/199236198): Remove this check after totally deprecated legacy split.
+ if (!context.getResources().getBoolean(R.bool.config_useLegacySplit)) {
+ taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this);
+ }
}
int getChildCount() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 7abda99..a0d9d03 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -52,9 +52,12 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
+import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityThread;
import android.content.Context;
+import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
@@ -66,6 +69,7 @@
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.WindowManager;
+import android.view.WindowManager.TransitionType;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Transformation;
@@ -78,6 +82,7 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.AttributeCache;
+import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.policy.TransitionAnimation;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.DisplayController;
@@ -292,9 +297,12 @@
finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */);
};
+ boolean requireBackgroundForTransition = false;
+
final int wallpaperTransit = getWallpaperTransitType(info);
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
+ final boolean isTask = change.getTaskInfo() != null;
if (change.getMode() == TRANSIT_CHANGE && (change.getFlags() & FLAG_IS_DISPLAY) != 0) {
int rotateDelta = change.getEndRotation() - change.getStartRotation();
@@ -342,7 +350,7 @@
startTransaction.setPosition(change.getLeash(),
change.getEndAbsBounds().left - change.getEndRelOffset().x,
change.getEndAbsBounds().top - change.getEndRelOffset().y);
- if (change.getTaskInfo() != null) {
+ if (isTask) {
// Skip non-tasks since those usually have null bounds.
startTransaction.setWindowCrop(change.getLeash(),
change.getEndAbsBounds().width(), change.getEndAbsBounds().height());
@@ -354,14 +362,34 @@
Animation a = loadAnimation(info, change, wallpaperTransit);
if (a != null) {
+ if (changeRequiresBackground(info, change)) {
+ requireBackgroundForTransition = true;
+ }
+
+ float cornerRadius = 0;
+ if (a.hasRoundedCorners() && isTask) {
+ // hasRoundedCorners is currently only enabled for tasks
+ final Context displayContext =
+ mDisplayController.getDisplayContext(change.getTaskInfo().displayId);
+ cornerRadius =
+ ScreenDecorationsUtils.getWindowCornerRadius(displayContext);
+ }
+
startSurfaceAnimation(animations, a, change.getLeash(), onAnimFinish,
- mTransactionPool, mMainExecutor, mAnimExecutor, null /* position */);
+ mTransactionPool, mMainExecutor, mAnimExecutor, null /* position */,
+ cornerRadius, change.getEndAbsBounds());
if (info.getAnimationOptions() != null) {
- attachThumbnail(animations, onAnimFinish, change, info.getAnimationOptions());
+ attachThumbnail(animations, onAnimFinish, change, info.getAnimationOptions(),
+ cornerRadius);
}
}
}
+
+ if (requireBackgroundForTransition) {
+ addBackgroundToTransition(info.getRootLeash(), startTransaction, finishTransaction);
+ }
+
startTransaction.apply();
TransitionMetrics.getInstance().reportAnimationStart(transition);
// run finish now in-case there are no animations
@@ -369,6 +397,40 @@
return true;
}
+ private boolean changeRequiresBackground(TransitionInfo info,
+ TransitionInfo.Change change) {
+ final boolean isTask = change.getTaskInfo() != null;
+ final @TransitionType int type = info.getType();
+ final boolean isOpenOrCloseTransition = type == TRANSIT_OPEN || type == TRANSIT_CLOSE
+ || type == TRANSIT_TO_FRONT || type == TRANSIT_TO_BACK;
+ return isTask && isOpenOrCloseTransition;
+ }
+
+ private void addBackgroundToTransition(
+ @NonNull SurfaceControl rootLeash,
+ @NonNull SurfaceControl.Transaction startTransaction,
+ @NonNull SurfaceControl.Transaction finishTransaction
+ ) {
+ final Context uiContext = ActivityThread.currentActivityThread().getSystemUiContext();
+ final @ColorInt int overviewBackgroundColor =
+ uiContext.getColor(R.color.overview_background);
+ final Color bgColor = Color.valueOf(overviewBackgroundColor);
+ final float[] colorArray = new float[] { bgColor.red(), bgColor.green(), bgColor.blue() };
+
+ final SurfaceControl animationBackgroundSurface = new SurfaceControl.Builder()
+ .setName("Animation Background")
+ .setParent(rootLeash)
+ .setColorLayer()
+ .setOpaque(true)
+ .build();
+
+ startTransaction
+ .setLayer(animationBackgroundSurface, Integer.MIN_VALUE)
+ .setColor(animationBackgroundSurface, colorArray)
+ .show(animationBackgroundSurface);
+ finishTransaction.remove(animationBackgroundSurface);
+ }
+
@Nullable
@Override
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
@@ -508,7 +570,7 @@
@NonNull Animation anim, @NonNull SurfaceControl leash,
@NonNull Runnable finishCallback, @NonNull TransactionPool pool,
@NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor,
- @Nullable Point position) {
+ @Nullable Point position, float cornerRadius, @Nullable Rect clipRect) {
final SurfaceControl.Transaction transaction = pool.acquire();
final ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
final Transformation transformation = new Transformation();
@@ -520,12 +582,12 @@
final long currentPlayTime = Math.min(va.getDuration(), va.getCurrentPlayTime());
applyTransformation(currentPlayTime, transaction, leash, anim, transformation, matrix,
- position);
+ position, cornerRadius, clipRect);
});
final Runnable finisher = () -> {
applyTransformation(va.getDuration(), transaction, leash, anim, transformation, matrix,
- position);
+ position, cornerRadius, clipRect);
pool.release(transaction);
mainExecutor.execute(() -> {
@@ -550,23 +612,24 @@
private void attachThumbnail(@NonNull ArrayList<Animator> animations,
@NonNull Runnable finishCallback, TransitionInfo.Change change,
- TransitionInfo.AnimationOptions options) {
+ TransitionInfo.AnimationOptions options, float cornerRadius) {
final boolean isTask = change.getTaskInfo() != null;
final boolean isOpen = Transitions.isOpeningType(change.getMode());
final boolean isClose = Transitions.isClosingType(change.getMode());
if (isOpen) {
if (options.getType() == ANIM_OPEN_CROSS_PROFILE_APPS && isTask) {
- attachCrossProfileThunmbnailAnimation(animations, finishCallback, change);
+ attachCrossProfileThunmbnailAnimation(animations, finishCallback, change,
+ cornerRadius);
} else if (options.getType() == ANIM_THUMBNAIL_SCALE_UP) {
- attachThumbnailAnimation(animations, finishCallback, change, options);
+ attachThumbnailAnimation(animations, finishCallback, change, options, cornerRadius);
}
} else if (isClose && options.getType() == ANIM_THUMBNAIL_SCALE_DOWN) {
- attachThumbnailAnimation(animations, finishCallback, change, options);
+ attachThumbnailAnimation(animations, finishCallback, change, options, cornerRadius);
}
}
private void attachCrossProfileThunmbnailAnimation(@NonNull ArrayList<Animator> animations,
- @NonNull Runnable finishCallback, TransitionInfo.Change change) {
+ @NonNull Runnable finishCallback, TransitionInfo.Change change, float cornerRadius) {
final int thumbnailDrawableRes = change.getTaskInfo().userId == mCurrentUserId
? R.drawable.ic_account_circle : R.drawable.ic_corp_badge;
final Rect bounds = change.getEndAbsBounds();
@@ -594,12 +657,13 @@
a.restrictDuration(MAX_ANIMATION_DURATION);
a.scaleCurrentDuration(mTransitionAnimationScaleSetting);
startSurfaceAnimation(animations, a, wt.getSurface(), finisher, mTransactionPool,
- mMainExecutor, mAnimExecutor, new Point(bounds.left, bounds.top));
+ mMainExecutor, mAnimExecutor, new Point(bounds.left, bounds.top),
+ cornerRadius, change.getEndAbsBounds());
}
private void attachThumbnailAnimation(@NonNull ArrayList<Animator> animations,
@NonNull Runnable finishCallback, TransitionInfo.Change change,
- TransitionInfo.AnimationOptions options) {
+ TransitionInfo.AnimationOptions options, float cornerRadius) {
final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
final WindowThumbnail wt = WindowThumbnail.createAndAttach(mSurfaceSession,
change.getLeash(), options.getThumbnail(), transaction);
@@ -618,7 +682,8 @@
a.restrictDuration(MAX_ANIMATION_DURATION);
a.scaleCurrentDuration(mTransitionAnimationScaleSetting);
startSurfaceAnimation(animations, a, wt.getSurface(), finisher, mTransactionPool,
- mMainExecutor, mAnimExecutor, null /* position */);
+ mMainExecutor, mAnimExecutor, null /* position */,
+ cornerRadius, change.getEndAbsBounds());
}
private static int getWallpaperTransitType(TransitionInfo info) {
@@ -650,13 +715,19 @@
private static void applyTransformation(long time, SurfaceControl.Transaction t,
SurfaceControl leash, Animation anim, Transformation transformation, float[] matrix,
- Point position) {
+ Point position, float cornerRadius, @Nullable Rect clipRect) {
anim.getTransformation(time, transformation);
if (position != null) {
transformation.getMatrix().postTranslate(position.x, position.y);
}
t.setMatrix(leash, transformation.getMatrix(), matrix);
t.setAlpha(leash, transformation.getAlpha());
+ if (anim.hasRoundedCorners() && cornerRadius > 0 && clipRect != null) {
+ // We can only apply rounded corner if a crop is set
+ t.setWindowCrop(leash, clipRect);
+ t.setCornerRadius(leash, cornerRadius);
+ }
+
t.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId());
t.apply();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
index 13c670a..45d8be1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
@@ -292,14 +292,16 @@
@NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor,
@NonNull ShellExecutor animExecutor) {
startSurfaceAnimation(animations, mRotateEnterAnimation, mSurfaceControl, finishCallback,
- mTransactionPool, mainExecutor, animExecutor, null /* position */);
+ mTransactionPool, mainExecutor, animExecutor, null /* position */,
+ 0 /* cornerRadius */, null /* clipRect */);
}
private void startScreenshotRotationAnimation(@NonNull ArrayList<Animator> animations,
@NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor,
@NonNull ShellExecutor animExecutor) {
startSurfaceAnimation(animations, mRotateExitAnimation, mAnimLeash, finishCallback,
- mTransactionPool, mainExecutor, animExecutor, null /* position */);
+ mTransactionPool, mainExecutor, animExecutor, null /* position */,
+ 0 /* cornerRadius */, null /* clipRect */);
}
private void startColorAnimation(float animationScale, @NonNull ShellExecutor animExecutor) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/ShellUnfoldProgressProvider.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/ShellUnfoldProgressProvider.java
index 74e4812..367676f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/ShellUnfoldProgressProvider.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/ShellUnfoldProgressProvider.java
@@ -26,10 +26,16 @@
*/
public interface ShellUnfoldProgressProvider {
+ // This is a temporary workaround until we move the progress providers into the Shell or
+ // refactor the dependencies. TLDR, the base module depends on this provider to determine if the
+ // FullscreenUnfoldController is available, but this check can't rely on an optional component.
+ public static final ShellUnfoldProgressProvider NO_PROVIDER =
+ new ShellUnfoldProgressProvider() {};
+
/**
* Adds a transition listener
*/
- void addListener(Executor executor, UnfoldListener listener);
+ default void addListener(Executor executor, UnfoldListener listener) {}
/**
* Listener for receiving unfold updates
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
index ad4ccc0..574a9f4 100644
--- a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
@@ -16,10 +16,6 @@
<!-- restart launcher to activate TAPL -->
<option name="run-command" value="setprop ro.test_harness 1 ; am force-stop com.google.android.apps.nexuslauncher" />
</target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.DeviceCleaner">
- <!-- reboot the device to teardown any crashed tests -->
- <option name="cleanup-action" value="REBOOT" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true"/>
<option name="test-file-name" value="WMShellFlickerTests.apk"/>
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
index ecc2d31..1d463d5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
@@ -24,11 +24,13 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.wm.shell.flicker.appPairsDividerIsInvisibleAtEnd
import com.android.wm.shell.flicker.helpers.AppPairsHelper
import com.android.wm.shell.flicker.helpers.MultiWindowHelper.Companion.resetMultiWindowConfig
import com.android.wm.shell.flicker.helpers.MultiWindowHelper.Companion.setSupportsNonResizableMultiWindow
import org.junit.After
+import org.junit.Assume.assumeFalse
import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
@@ -82,7 +84,11 @@
@FlakyTest
@Test
- override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
index 04c82e5..10cf0b7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
@@ -24,10 +24,12 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.wm.shell.flicker.APP_PAIR_SPLIT_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appPairsDividerIsVisibleAtEnd
import com.android.wm.shell.flicker.helpers.AppPairsHelper
import com.android.wm.shell.flicker.helpers.AppPairsHelper.Companion.waitAppsShown
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -67,7 +69,11 @@
@FlakyTest
@Test
- override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestSupportPairNonResizeableApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestSupportPairNonResizeableApps.kt
index b7d3ba6..722ec34 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestSupportPairNonResizeableApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestSupportPairNonResizeableApps.kt
@@ -24,11 +24,13 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.wm.shell.flicker.appPairsDividerIsVisibleAtEnd
import com.android.wm.shell.flicker.helpers.AppPairsHelper
import com.android.wm.shell.flicker.helpers.MultiWindowHelper.Companion.resetMultiWindowConfig
import com.android.wm.shell.flicker.helpers.MultiWindowHelper.Companion.setSupportsNonResizableMultiWindow
import org.junit.After
+import org.junit.Assume.assumeFalse
import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
@@ -86,7 +88,11 @@
@FlakyTest
@Test
- override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
index f6ce3d4..38c008c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
@@ -25,10 +25,12 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.wm.shell.flicker.APP_PAIR_SPLIT_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appPairsDividerIsInvisibleAtEnd
import com.android.wm.shell.flicker.helpers.AppPairsHelper
import com.android.wm.shell.flicker.helpers.AppPairsHelper.Companion.waitAppsShown
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -71,7 +73,11 @@
@FlakyTest
@Test
- override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
index 5fe13e0..a787f2b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
@@ -27,6 +27,7 @@
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.entireScreenCovered
import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.launchSplitScreen
import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview
import com.android.server.wm.flicker.helpers.setRotation
@@ -40,6 +41,7 @@
import com.android.server.wm.traces.common.FlickerComponentName
import com.android.wm.shell.flicker.dockedStackDividerBecomesInvisible
import com.android.wm.shell.flicker.helpers.SimpleAppHelper
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -110,7 +112,11 @@
@Presubmit
@Test
- fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
index a238bc2..6041e23 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
@@ -30,6 +30,7 @@
import com.android.server.wm.flicker.entireScreenCovered
import com.android.server.wm.flicker.helpers.ImeAppHelper
import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.launchSplitScreen
import com.android.server.wm.flicker.helpers.resizeSplitScreen
import com.android.server.wm.flicker.helpers.setRotation
@@ -44,6 +45,7 @@
import com.android.wm.shell.flicker.DOCKED_STACK_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.helpers.SimpleAppHelper
import com.android.wm.shell.flicker.testapp.Components
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -134,7 +136,11 @@
fun navBarLayerRotatesAndScales() = testSpec.navBarLayerRotatesAndScales()
@Test
- fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
@Test
fun topAppLayerIsAlwaysVisible() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
index 50cd548..e44d7d6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
@@ -25,6 +25,7 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group2
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.launchSplitScreen
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
@@ -34,6 +35,7 @@
import com.android.wm.shell.flicker.dockedStackDividerIsVisibleAtEnd
import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -77,7 +79,11 @@
@Presubmit
@Test
- fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
index 8d52225..d33d92b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
@@ -25,6 +25,7 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group2
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.launchSplitScreen
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
@@ -34,6 +35,7 @@
import com.android.wm.shell.flicker.dockedStackDividerIsVisibleAtEnd
import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -76,7 +78,11 @@
@Presubmit
@Test
- fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
index 070f636..ece68df 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
@@ -24,6 +24,7 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group2
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.launchSplitScreen
import com.android.server.wm.flicker.helpers.reopenAppFromOverview
import com.android.server.wm.flicker.helpers.setRotation
@@ -35,6 +36,7 @@
import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -85,7 +87,11 @@
@Presubmit
@Test
- fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
index fabbd26..127301f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
@@ -25,6 +25,7 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group2
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.launchSplitScreen
import com.android.server.wm.flicker.helpers.reopenAppFromOverview
import com.android.server.wm.flicker.helpers.setRotation
@@ -36,6 +37,7 @@
import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -91,7 +93,11 @@
@Presubmit
@Test
- fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
@FlakyTest
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
index 33626d0..c439922 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -26,6 +26,8 @@
import com.android.server.wm.flicker.LAUNCHER_COMPONENT
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -65,6 +67,15 @@
}
}
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
+
/**
* Checks [pipApp] window remains visible throughout the animation
*/
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
index 791505b..f923a23 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -27,6 +27,7 @@
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.entireScreenCovered
import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.traces.common.FlickerComponentName
@@ -35,6 +36,7 @@
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_PORTRAIT
import com.android.wm.shell.flicker.testapp.Components.PipActivity.ACTION_ENTER_PIP
import com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -119,7 +121,11 @@
*/
@Presubmit
@Test
- override fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
/**
* Checks that all parts of the screen are covered at the start and end of the transition
@@ -204,6 +210,7 @@
@Presubmit
@Test
fun testAppPlusPipLayerCoversFullScreenOnEnd() {
+ // This test doesn't work in shell transitions because of b/206669574
testSpec.assertLayersEnd {
val pipRegion = visibleRegion(pipApp.component).region
visibleRegion(testApp.component)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
index 8267442..3e7e2f5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
@@ -18,7 +18,9 @@
import android.platform.test.annotations.Presubmit
import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.wm.shell.flicker.helpers.FixedAppHelper
+import org.junit.Assume.assumeFalse
import org.junit.Test
/**
@@ -27,6 +29,15 @@
abstract class ExitPipToAppTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
protected val testApp = FixedAppHelper(instrumentation)
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
+
/**
* Checks that the pip app window remains inside the display bounds throughout the whole
* animation
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
index 5f29dbc..4d63d14 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.flicker.pip
+import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -23,7 +24,10 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
+import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
@@ -75,6 +79,15 @@
}
}
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
+
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
index 00ccf26..030e040 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.flicker.pip
+import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -23,7 +24,10 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
+import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
@@ -72,6 +76,15 @@
}
}
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
+
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
index b0b11e9..2def979 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.flicker.pip
+import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -23,7 +24,11 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume.assumeFalse
+import org.junit.Before
import org.junit.FixMethodOrder
+import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
@@ -60,6 +65,21 @@
}
}
+ @Before
+ fun onBefore() {
+ // This CUJ don't work in shell transitions because of b/204570898 b/204562589
+ assumeFalse(isShellTransitionsEnabled)
+ }
+
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
+
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
index f4eb701..9191d0e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
@@ -25,7 +25,9 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -96,7 +98,11 @@
@Presubmit
@Test
- override fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
index f196764..3511cc2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
@@ -26,6 +26,9 @@
import com.android.server.wm.flicker.LAUNCHER_COMPONENT
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume.assumeFalse
+import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -62,6 +65,12 @@
}
}
+ @Before
+ fun onBefore() {
+ // This CUJ don't work in shell transitions because of b/204570898 b/204562589
+ assumeFalse(isShellTransitionsEnabled)
+ }
+
/**
* Checks that the pip app window remains inside the display bounds throughout the whole
* animation
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt
index d9685f3..10a542f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.flicker.pip
+import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -23,8 +24,11 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.traces.RegionSubject
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
+import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
@@ -78,6 +82,15 @@
current.isHigherOrEqual(previous.region)
}
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
+
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt
index c6b42ea..cb6ba0e6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.flicker.pip
+import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -23,8 +24,11 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.traces.RegionSubject
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
+import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
@@ -78,6 +82,15 @@
current.isLowerOrEqual(previous.region)
}
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
+
companion object {
/**
* Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
index 45cbdc8..81ac10f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
@@ -25,9 +25,11 @@
import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.traces.common.FlickerComponentName
import com.android.wm.shell.flicker.helpers.ImeAppHelper
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -70,6 +72,15 @@
}
}
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
+
/**
* Ensure the pip window remains visible throughout any keyboard interactions
*/
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
index 3e3ea16..70075dd 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
@@ -89,6 +89,15 @@
}
}
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(com.android.server.wm.flicker.helpers.isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
+
@FlakyTest(bugId = 161435597)
@Test
fun pipWindowInsideDisplayBounds() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
index af984b3..16fc048 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
@@ -27,10 +27,13 @@
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.entireScreenCovered
import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.wm.shell.flicker.helpers.FixedAppHelper
+import org.junit.Assume.assumeFalse
+import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -81,6 +84,12 @@
}
}
+ @Before
+ fun onBefore() {
+ // This CUJ don't work in shell transitions because of b/204570898 b/204562589 b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ }
+
/**
* Checks that all parts of the screen are covered at the start and end of the transition
*/
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
index f8e2d38..9c26105 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
@@ -25,10 +25,12 @@
import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
import com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION
import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP
import org.junit.Assert.assertEquals
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -102,7 +104,11 @@
@FlakyTest
@Test
- override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
@FlakyTest
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
index 31e9167..9c3b0fa 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
@@ -27,7 +27,7 @@
import com.android.wm.shell.flicker.pip.PipTestBase
import org.junit.After
import org.junit.Assert.assertFalse
-import org.junit.Assume
+import org.junit.Assume.assumeTrue
import org.junit.Before
abstract class TvPipTestBase : PipTestBase(rotationToString(ROTATION_0), ROTATION_0) {
@@ -37,7 +37,7 @@
@Before
final override fun televisionSetUp() {
// Should run only on TVs.
- Assume.assumeTrue(isTelevision)
+ assumeTrue(isTelevision)
systemUiProcessObserver.start()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
new file mode 100644
index 0000000..bfa2c92
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.draganddrop;
+
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.view.Display;
+import android.view.DragEvent;
+import android.view.View;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.UiEventLogger;
+import com.android.wm.shell.common.DisplayController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for the drag and drop controller.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DragAndDropControllerTest {
+
+ @Mock
+ private Context mContext;
+
+ @Mock
+ private DisplayController mDisplayController;
+
+ @Mock
+ private UiEventLogger mUiEventLogger;
+
+ private DragAndDropController mController;
+
+ @Before
+ public void setUp() throws RemoteException {
+ MockitoAnnotations.initMocks(this);
+
+ mController = new DragAndDropController(mContext, mDisplayController, mUiEventLogger);
+ }
+
+ @Test
+ public void testIgnoreNonDefaultDisplays() {
+ final int nonDefaultDisplayId = 12345;
+ final View dragLayout = mock(View.class);
+ final Display display = mock(Display.class);
+ doReturn(nonDefaultDisplayId).when(display).getDisplayId();
+ doReturn(display).when(dragLayout).getDisplay();
+
+ // Expect no per-display layout to be added
+ mController.onDisplayAdded(nonDefaultDisplayId);
+ assertFalse(mController.onDrag(dragLayout, mock(DragEvent.class)));
+ }
+}
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 8f04cfb..6ea303c 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -17,24 +17,29 @@
#define LOG_TAG "PointerController"
//#define LOG_NDEBUG 0
-// Log debug messages about pointer updates
-#define DEBUG_POINTER_UPDATES 0
-
#include "PointerController.h"
-#include "MouseCursorController.h"
#include "PointerControllerContext.h"
-#include "TouchSpotController.h"
-#include <log/log.h>
-
-#include <SkBitmap.h>
#include <SkBlendMode.h>
#include <SkCanvas.h>
#include <SkColor.h>
-#include <SkPaint.h>
namespace android {
+namespace {
+
+const ui::Transform kIdentityTransform;
+
+} // namespace
+
+// --- PointerController::DisplayInfoListener ---
+
+void PointerController::DisplayInfoListener::onWindowInfosChanged(
+ const std::vector<android::gui::WindowInfo>&,
+ const std::vector<android::gui::DisplayInfo>& displayInfo) {
+ mPointerController.onDisplayInfosChanged(displayInfo);
+}
+
// --- PointerController ---
std::shared_ptr<PointerController> PointerController::create(
@@ -63,9 +68,12 @@
PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
const sp<Looper>& looper,
const sp<SpriteController>& spriteController)
- : mContext(policy, looper, spriteController, *this), mCursorController(mContext) {
+ : mContext(policy, looper, spriteController, *this),
+ mCursorController(mContext),
+ mDisplayInfoListener(new DisplayInfoListener(*this)) {
std::scoped_lock lock(mLock);
mLocked.presentation = Presentation::SPOT;
+ SurfaceComposerClient::getDefault()->addWindowInfosListener(mDisplayInfoListener);
}
bool PointerController::getBounds(float* outMinX, float* outMinY, float* outMaxX,
@@ -74,7 +82,14 @@
}
void PointerController::move(float deltaX, float deltaY) {
- mCursorController.move(deltaX, deltaY);
+ const int32_t displayId = mCursorController.getDisplayId();
+ vec2 transformed;
+ {
+ std::scoped_lock lock(mLock);
+ const auto& transform = getTransformForDisplayLocked(displayId);
+ transformed = transformWithoutTranslation(transform, {deltaX, deltaY});
+ }
+ mCursorController.move(transformed.x, transformed.y);
}
void PointerController::setButtonState(int32_t buttonState) {
@@ -86,12 +101,26 @@
}
void PointerController::setPosition(float x, float y) {
- std::scoped_lock lock(mLock);
- mCursorController.setPosition(x, y);
+ const int32_t displayId = mCursorController.getDisplayId();
+ vec2 transformed;
+ {
+ std::scoped_lock lock(mLock);
+ const auto& transform = getTransformForDisplayLocked(displayId);
+ transformed = transform.transform(x, y);
+ }
+ mCursorController.setPosition(transformed.x, transformed.y);
}
void PointerController::getPosition(float* outX, float* outY) const {
+ const int32_t displayId = mCursorController.getDisplayId();
mCursorController.getPosition(outX, outY);
+ {
+ std::scoped_lock lock(mLock);
+ const auto& transform = getTransformForDisplayLocked(displayId);
+ const auto xy = transform.inverse().transform(*outX, *outY);
+ *outX = xy.x;
+ *outY = xy.y;
+ }
}
int32_t PointerController::getDisplayId() const {
@@ -130,11 +159,25 @@
void PointerController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
BitSet32 spotIdBits, int32_t displayId) {
std::scoped_lock lock(mLock);
+ std::array<PointerCoords, MAX_POINTERS> outSpotCoords{};
+ const ui::Transform& transform = getTransformForDisplayLocked(displayId);
+
+ for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) {
+ const uint32_t index = spotIdToIndex[idBits.clearFirstMarkedBit()];
+
+ const vec2 xy = transform.transform(spotCoords[index].getXYValue());
+ outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_X, xy.x);
+ outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y);
+
+ float pressure = spotCoords[index].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
+ outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
+ }
+
auto it = mLocked.spotControllers.find(displayId);
if (it == mLocked.spotControllers.end()) {
mLocked.spotControllers.try_emplace(displayId, displayId, mContext);
}
- mLocked.spotControllers.at(displayId).setSpots(spotCoords, spotIdToIndex, spotIdBits);
+ mLocked.spotControllers.at(displayId).setSpots(outSpotCoords.data(), spotIdToIndex, spotIdBits);
}
void PointerController::clearSpots() {
@@ -194,7 +237,7 @@
void PointerController::onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports) {
std::unordered_set<int32_t> displayIdSet;
- for (DisplayViewport viewport : viewports) {
+ for (const DisplayViewport& viewport : viewports) {
displayIdSet.insert(viewport.displayId);
}
@@ -214,4 +257,17 @@
}
}
+void PointerController::onDisplayInfosChanged(const std::vector<gui::DisplayInfo>& displayInfo) {
+ std::scoped_lock lock(mLock);
+ mLocked.mDisplayInfos = displayInfo;
+}
+
+const ui::Transform& PointerController::getTransformForDisplayLocked(int displayId) const {
+ const auto& di = mLocked.mDisplayInfos;
+ auto it = std::find_if(di.begin(), di.end(), [displayId](const gui::DisplayInfo& info) {
+ return info.displayId == displayId;
+ });
+ return it != di.end() ? it->transform : kIdentityTransform;
+}
+
} // namespace android
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 97567ba..58bb014 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -72,6 +72,8 @@
void reloadPointerResources();
void onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports);
+ void onDisplayInfosChanged(const std::vector<gui::DisplayInfo>& displayInfos);
+
private:
friend PointerControllerContext::LooperCallback;
friend PointerControllerContext::MessageHandler;
@@ -85,9 +87,23 @@
struct Locked {
Presentation presentation;
+ std::vector<gui::DisplayInfo> mDisplayInfos;
std::unordered_map<int32_t /* displayId */, TouchSpotController> spotControllers;
} mLocked GUARDED_BY(mLock);
+ class DisplayInfoListener : public gui::WindowInfosListener {
+ public:
+ explicit DisplayInfoListener(PointerController& pc) : mPointerController(pc){};
+ void onWindowInfosChanged(const std::vector<android::gui::WindowInfo>&,
+ const std::vector<android::gui::DisplayInfo>&) override;
+
+ private:
+ PointerController& mPointerController;
+ };
+ sp<DisplayInfoListener> mDisplayInfoListener;
+
+ const ui::Transform& getTransformForDisplayLocked(int displayId) const REQUIRES(mLock);
+
PointerController(const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
const sp<SpriteController>& spriteController);
void clearSpotsLocked();
diff --git a/media/aidl/android/media/audio/common/AudioMode.aidl b/media/aidl/android/media/audio/common/AudioMode.aidl
index cc03813..701bcb6 100644
--- a/media/aidl/android/media/audio/common/AudioMode.aidl
+++ b/media/aidl/android/media/audio/common/AudioMode.aidl
@@ -45,4 +45,8 @@
IN_COMMUNICATION = 3,
/** Call screening in progress. */
CALL_SCREEN = 4,
+ /** PSTN Call redirection in progress. */
+ SYS_RESERVED_CALL_REDIRECT = 5,
+ /** VoIP Call redirection in progress. */
+ SYS_RESERVED_COMMUNICATION_REDIRECT = 6,
}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioMode.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioMode.aidl
index 8ae1c10..8256c1c 100644
--- a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioMode.aidl
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioMode.aidl
@@ -42,4 +42,6 @@
IN_CALL = 2,
IN_COMMUNICATION = 3,
CALL_SCREEN = 4,
+ SYS_RESERVED_CALL_REDIRECT = 5,
+ SYS_RESERVED_COMMUNICATION_REDIRECT = 6,
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index e3ed703..c662223 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -30,8 +30,11 @@
import android.annotation.TestApi;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.app.compat.CompatChanges;
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothDevice;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -2840,6 +2843,14 @@
}
/**
+ * This change id controls use of audio modes for call audio redirection.
+ * @hide
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ public static final long CALL_REDIRECTION_AUDIO_MODES = 189472651L; // buganizer id
+
+ /**
* Returns the current audio mode.
*
* @return the current audio mode.
@@ -2858,6 +2869,12 @@
}
if (mode == MODE_CALL_SCREENING && sdk <= Build.VERSION_CODES.Q) {
mode = MODE_IN_CALL;
+ } else if (mode == MODE_CALL_REDIRECT
+ && !CompatChanges.isChangeEnabled(CALL_REDIRECTION_AUDIO_MODES)) {
+ mode = MODE_IN_CALL;
+ } else if (mode == MODE_COMMUNICATION_REDIRECT
+ && !CompatChanges.isChangeEnabled(CALL_REDIRECTION_AUDIO_MODES)) {
+ mode = MODE_IN_COMMUNICATION;
}
return mode;
} catch (RemoteException e) {
@@ -3075,13 +3092,26 @@
*/
public static final int MODE_CALL_SCREENING = AudioSystem.MODE_CALL_SCREENING;
+ /**
+ * A telephony call is established and its audio is being redirected to another device.
+ */
+ public static final int MODE_CALL_REDIRECT = AudioSystem.MODE_CALL_REDIRECT;
+
+ /**
+ * n audio/video chat or VoIP call is established and its audio is being redirected to another
+ * device.
+ */
+ public static final int MODE_COMMUNICATION_REDIRECT = AudioSystem.MODE_COMMUNICATION_REDIRECT;
+
/** @hide */
@IntDef(flag = false, prefix = "MODE_", value = {
MODE_NORMAL,
MODE_RINGTONE,
MODE_IN_CALL,
MODE_IN_COMMUNICATION,
- MODE_CALL_SCREENING }
+ MODE_CALL_SCREENING,
+ MODE_CALL_REDIRECT,
+ MODE_COMMUNICATION_REDIRECT}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioMode {}
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 60c9e1c..16cb5f4 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -199,7 +199,11 @@
/** @hide */
public static final int MODE_CALL_SCREENING = 4;
/** @hide */
- public static final int NUM_MODES = 5;
+ public static final int MODE_CALL_REDIRECT = 5;
+ /** @hide */
+ public static final int MODE_COMMUNICATION_REDIRECT = 6;
+ /** @hide */
+ public static final int NUM_MODES = 7;
/** @hide */
public static String modeToString(int mode) {
@@ -211,6 +215,8 @@
case MODE_NORMAL: return "MODE_NORMAL";
case MODE_RINGTONE: return "MODE_RINGTONE";
case MODE_CALL_SCREENING: return "MODE_CALL_SCREENING";
+ case MODE_CALL_REDIRECT: return "MODE_CALL_REDIRECT";
+ case MODE_COMMUNICATION_REDIRECT: return "MODE_COMMUNICATION_REDIRECT";
default: return "unknown mode (" + mode + ")";
}
}
diff --git a/media/java/android/media/tv/interactive/TvIAppInfo.java b/media/java/android/media/tv/interactive/TvIAppInfo.java
new file mode 100644
index 0000000..b3b5aee
--- /dev/null
+++ b/media/java/android/media/tv/interactive/TvIAppInfo.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.interactive;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class is used to specify meta information of a TV interactive app.
+ * @hide
+ */
+public final class TvIAppInfo implements Parcelable {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "TvIAppInfo";
+
+ private final ResolveInfo mService;
+ private final String mId;
+ private List<String> mTypes = new ArrayList<>();
+
+ private TvIAppInfo(ResolveInfo service, String id, List<String> types) {
+ mService = service;
+ mId = id;
+ mTypes = types;
+ }
+
+ protected TvIAppInfo(Parcel in) {
+ mService = ResolveInfo.CREATOR.createFromParcel(in);
+ mId = in.readString();
+ in.readStringList(mTypes);
+ }
+
+ public static final Creator<TvIAppInfo> CREATOR = new Creator<TvIAppInfo>() {
+ @Override
+ public TvIAppInfo createFromParcel(Parcel in) {
+ return new TvIAppInfo(in);
+ }
+
+ @Override
+ public TvIAppInfo[] newArray(int size) {
+ return new TvIAppInfo[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ mService.writeToParcel(dest, flags);
+ dest.writeString(mId);
+ dest.writeStringList(mTypes);
+ }
+
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * Returns the information of the service that implements this TV IApp service.
+ */
+ public ServiceInfo getServiceInfo() {
+ return mService.serviceInfo;
+ }
+
+ /**
+ * A convenience builder for creating {@link TvIAppInfo} objects.
+ */
+ public static final class Builder {
+ private static final String XML_START_TAG_NAME = "tv-iapp";
+ private final Context mContext;
+ private final ResolveInfo mResolveInfo;
+ private final List<String> mTypes = new ArrayList<>();
+
+ /**
+ * Constructs a new builder for {@link TvIAppInfo}.
+ *
+ * @param context A Context of the application package implementing this class.
+ * @param component The name of the application component to be used for the
+ * {@link TvIAppService}.
+ */
+ public Builder(Context context, ComponentName component) {
+ if (context == null) {
+ throw new IllegalArgumentException("context cannot be null.");
+ }
+ Intent intent = new Intent(TvIAppService.SERVICE_INTERFACE).setComponent(component);
+ mResolveInfo = context.getPackageManager().resolveService(intent,
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+ if (mResolveInfo == null) {
+ throw new IllegalArgumentException("Invalid component. Can't find the service.");
+ }
+ mContext = context;
+ }
+
+ /**
+ * Creates a {@link TvIAppInfo} instance with the specified fields. Most of the information
+ * is obtained by parsing the AndroidManifest and {@link TvIAppService#SERVICE_META_DATA}
+ * for the {@link TvIAppService} this TV IApp implements.
+ *
+ * @return TvIAppInfo containing information about this TV IApp service.
+ */
+ public TvIAppInfo build() {
+ ComponentName componentName = new ComponentName(mResolveInfo.serviceInfo.packageName,
+ mResolveInfo.serviceInfo.name);
+ String id;
+ id = generateIAppServiceId(componentName);
+ parseServiceMetadata();
+ return new TvIAppInfo(mResolveInfo, id, mTypes);
+ }
+
+ private static String generateIAppServiceId(ComponentName name) {
+ return name.flattenToShortString();
+ }
+
+ private void parseServiceMetadata() {
+ ServiceInfo si = mResolveInfo.serviceInfo;
+ PackageManager pm = mContext.getPackageManager();
+ try (XmlResourceParser parser =
+ si.loadXmlMetaData(pm, TvIAppService.SERVICE_META_DATA)) {
+ if (parser == null) {
+ throw new IllegalStateException("No " + TvIAppService.SERVICE_META_DATA
+ + " meta-data found for " + si.name);
+ }
+
+ Resources res = pm.getResourcesForApplication(si.applicationInfo);
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.START_TAG) {
+ // move to the START_TAG
+ }
+
+ String nodeName = parser.getName();
+ if (!XML_START_TAG_NAME.equals(nodeName)) {
+ throw new IllegalStateException("Meta-data does not start with "
+ + XML_START_TAG_NAME + " tag for " + si.name);
+ }
+
+ TypedArray sa = res.obtainAttributes(attrs,
+ com.android.internal.R.styleable.TvIAppService);
+ CharSequence[] types = sa.getTextArray(
+ com.android.internal.R.styleable.TvIAppService_supportedTypes);
+ for (CharSequence cs : types) {
+ mTypes.add(cs.toString());
+ }
+
+ sa.recycle();
+ } catch (IOException | XmlPullParserException e) {
+ throw new IllegalStateException(
+ "Failed reading meta-data for " + si.packageName, e);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new IllegalStateException("No resources found for " + si.packageName, e);
+ }
+ }
+ }
+}
diff --git a/media/java/android/media/tv/interactive/TvIAppService.java b/media/java/android/media/tv/interactive/TvIAppService.java
index b385d9c..8863729 100644
--- a/media/java/android/media/tv/interactive/TvIAppService.java
+++ b/media/java/android/media/tv/interactive/TvIAppService.java
@@ -38,22 +38,32 @@
/**
* The TvIAppService class represents a TV interactive applications RTE.
- * @hide
*/
public abstract class TvIAppService extends Service {
private static final boolean DEBUG = false;
private static final String TAG = "TvIAppService";
- private final Handler mServiceHandler = new ServiceHandler();
+ // TODO: cleanup and unhide APIs.
/**
- * This is the interface name that a service implementing an environment to run Tv IApp should
- * say that it support -- that is, this is the action it uses for its intent filter. To be
- * supported, the service must also require the BIND_TV_IAPP permission so that other
- * applications cannot abuse it.
+ * This is the interface name that a service implementing a TV IApp service should say that it
+ * supports -- that is, this is the action it uses for its intent filter. To be supported, the
+ * service must also require the android.Manifest.permission#BIND_TV_IAPP permission so
+ * that other applications cannot abuse it.
*/
- public static final String SERVICE_INTERFACE = "android.media.tv.TvIAppService";
+ public static final String SERVICE_INTERFACE = "android.media.tv.interactive.TvIAppService";
+ /**
+ * Name under which a TvIAppService component publishes information about itself. This meta-data
+ * must reference an XML resource containing an
+ * <code><{@link android.R.styleable#TvIAppService tv-iapp}></code>
+ * tag.
+ */
+ public static final String SERVICE_META_DATA = "android.media.tv.interactive.app";
+
+ private final Handler mServiceHandler = new ServiceHandler();
+
+ /** @hide */
@Override
public final IBinder onBind(Intent intent) {
ITvIAppService.Stub tvIAppServiceBinder = new ITvIAppService.Stub() {
@@ -83,12 +93,17 @@
*
* @param iAppServiceId The ID of the TV IApp associated with the session.
* @param type The type of the TV IApp associated with the session.
+ * @hide
*/
@Nullable
- public abstract Session onCreateSession(@NonNull String iAppServiceId, int type);
+ public Session onCreateSession(@NonNull String iAppServiceId, int type) {
+ // TODO: make it abstract when unhide
+ return null;
+ }
/**
* Base class for derived classes to implement to provide a TV interactive app session.
+ * @hide
*/
public abstract static class Session implements KeyEvent.Callback {
private final Object mLock = new Object();
@@ -113,6 +128,7 @@
/**
* Starts TvIAppService session.
+ * @hide
*/
public void onStartIApp() {
}
@@ -144,6 +160,7 @@
/**
* Releases TvIAppService session.
+ * @hide
*/
public void onRelease() {
}
@@ -245,6 +262,7 @@
/**
* Implements the internal ITvIAppSession interface.
+ * @hide
*/
public static class ITvIAppSessionWrapper extends ITvIAppSession.Stub {
private final Session mSessionImpl;
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
index 1090f33..403bfa7 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
@@ -581,7 +581,7 @@
* Gets Number of Segment.
*/
@IntRange(from = 0, to = 0xff)
- public int getNumOfSegment() {
+ public int getNumberOfSegment() {
return mNumOfSegment;
}
@@ -639,7 +639,7 @@
*/
@NonNull
@IntRange(from = 0, to = 0xff)
- public Builder setNumOfSegment(int numOfSegment) {
+ public Builder setNumberOfSegment(int numOfSegment) {
mNumOfSegment = numOfSegment;
return this;
}
diff --git a/media/native/midi/amidi.cpp b/media/native/midi/amidi.cpp
index 923377c..f90796e 100644
--- a/media/native/midi/amidi.cpp
+++ b/media/native/midi/amidi.cpp
@@ -325,8 +325,8 @@
}
uint8_t readBuffer[AMIDI_PACKET_SIZE];
- ssize_t readCount = read(mPort->ufd, readBuffer, sizeof(readBuffer));
- if (readCount == EINTR || readCount < 1) {
+ ssize_t readCount = TEMP_FAILURE_RETRY(read(mPort->ufd, readBuffer, sizeof(readBuffer)));
+ if (readCount < 1) {
return AMEDIA_ERROR_UNKNOWN;
}
@@ -407,7 +407,8 @@
ssize_t numTransferBytes =
AMIDI_makeSendBuffer(writeBuffer, data + numSent, blockSize, timestamp);
- ssize_t numWritten = write(((AMIDI_Port*)inputPort)->ufd, writeBuffer, numTransferBytes);
+ ssize_t numWritten = TEMP_FAILURE_RETRY(write(((AMIDI_Port*)inputPort)->ufd, writeBuffer,
+ numTransferBytes));
if (numWritten < 0) {
break; // error so bail out.
}
@@ -430,7 +431,8 @@
uint8_t opCode = AMIDI_OPCODE_FLUSH;
ssize_t numTransferBytes = 1;
- ssize_t numWritten = write(((AMIDI_Port*)inputPort)->ufd, &opCode, numTransferBytes);
+ ssize_t numWritten = TEMP_FAILURE_RETRY(write(((AMIDI_Port*)inputPort)->ufd, &opCode,
+ numTransferBytes));
if (numWritten < numTransferBytes) {
ALOGE("AMidiInputPort_flush Couldn't write MIDI flush. requested:%zd, written:%zd",
diff --git a/packages/SettingsLib/TopIntroPreference/Android.bp b/packages/SettingsLib/TopIntroPreference/Android.bp
index 9577281..cd0bdea 100644
--- a/packages/SettingsLib/TopIntroPreference/Android.bp
+++ b/packages/SettingsLib/TopIntroPreference/Android.bp
@@ -19,4 +19,8 @@
],
sdk_version: "system_current",
min_sdk_version: "21",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.cellbroadcast",
+ ],
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
index 71bf9f6..a781a62 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -175,9 +175,12 @@
public UserIconDrawable setBadgeIfManagedUser(Context context, int userId) {
Drawable badge = null;
if (userId != UserHandle.USER_NULL) {
- boolean isManaged = context.getSystemService(DevicePolicyManager.class)
- .getProfileOwnerAsUser(userId) != null;
- if (isManaged) {
+ DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+ boolean isCorp =
+ dpm.getProfileOwnerAsUser(userId) != null // has an owner
+ && dpm.getProfileOwnerOrDeviceOwnerSupervisionComponent(UserHandle.of(userId))
+ == null; // and has no supervisor
+ if (isCorp) {
badge = getDrawableForDisplayDensity(
context, com.android.internal.R.drawable.ic_corp_badge_case);
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index 6f42d59..a50d4ae1 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -40,9 +40,6 @@
public static final String[] SETTINGS_TO_BACKUP = {
Settings.Global.APPLY_RAMPING_RINGER,
Settings.Global.BUGREPORT_IN_POWER_MENU,
- Settings.Global.CLOCKWORK_SYSUI_PACKAGE_NAME,
- Settings.Global.CLOCKWORK_SYSUI_MAIN_ACTIVITY_NAME,
- Settings.Global.CLOCKWORK_HOME_READY,
Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
Settings.Global.APP_AUTO_RESTRICTION_ENABLED,
Settings.Global.AUTO_TIME,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index 2bd5bdc..bf62f1d 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -116,8 +116,6 @@
VALIDATORS.put(
Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, PERCENTAGE_INTEGER_VALIDATOR);
VALIDATORS.put(Global.BLUETOOTH_ON, BOOLEAN_VALIDATOR);
- VALIDATORS.put(Global.CLOCKWORK_SYSUI_MAIN_ACTIVITY_NAME, ANY_STRING_VALIDATOR);
- VALIDATORS.put(Global.CLOCKWORK_SYSUI_PACKAGE_NAME, ANY_STRING_VALIDATOR);
VALIDATORS.put(Global.CLOCKWORK_HOME_READY, ANY_STRING_VALIDATOR);
VALIDATORS.put(Global.ENABLE_TARE, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.ENABLE_TARE_ALARM_MANAGER, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 53df2e82..324c05e 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -591,6 +591,7 @@
Settings.Global.CACHED_APPS_FREEZER_ENABLED,
Settings.Global.APP_INTEGRITY_VERIFICATION_TIMEOUT,
Settings.Global.KEY_CHORD_POWER_VOLUME_UP,
+ Settings.Global.CLOCKWORK_HOME_READY,
Settings.Global.Wearable.BATTERY_SAVER_MODE,
Settings.Global.Wearable.COMBINED_LOCATION_ENABLED,
Settings.Global.Wearable.HAS_PAY_TOKENS,
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
index b83ea4a..d5f858c 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
@@ -34,7 +34,7 @@
String ACTION = "com.android.systemui.action.PLUGIN_QS";
- int VERSION = 11;
+ int VERSION = 12;
String TAG = "QS";
@@ -46,6 +46,8 @@
void setHeightOverride(int desiredHeight);
void setHeaderClickable(boolean qsExpansionEnabled);
boolean isCustomizing();
+ /** Close the QS customizer, if it is open. */
+ void closeCustomizer();
void setOverscrolling(boolean overscrolling);
void setExpanded(boolean qsExpanded);
void setListening(boolean listening);
diff --git a/packages/SystemUI/res/drawable/assist_orb_scrim.xml b/packages/SystemUI/res/drawable/assist_orb_scrim.xml
deleted file mode 100644
index bbb2617..0000000
--- a/packages/SystemUI/res/drawable/assist_orb_scrim.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- ~ 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
- -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <gradient
- android:type="linear"
- android:angle="90"
- android:startColor="#55000000"
- android:endColor="#00000000" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/assist_orb.xml b/packages/SystemUI/res/layout/assist_orb.xml
deleted file mode 100644
index 0036ed6..0000000
--- a/packages/SystemUI/res/layout/assist_orb.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2012, 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.
-*/
--->
-
-<!-- Extends FrameLayout -->
-<com.android.systemui.assist.AssistOrbContainer
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <com.android.systemui.statusbar.AlphaOptimizedView
- android:layout_width="match_parent"
- android:layout_height="@dimen/assist_orb_scrim_height"
- android:layout_gravity="bottom"
- android:id="@+id/assist_orb_scrim"
- android:background="@drawable/assist_orb_scrim"/>
-
- <com.android.systemui.assist.AssistOrbView
- android:id="@+id/assist_orb"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/search_logo"/>
- </com.android.systemui.assist.AssistOrbView>
-
- <com.android.systemui.statusbar.AlphaOptimizedView
- android:id="@+id/assist_orb_navbar_scrim"
- android:layout_height="@dimen/assist_orb_navbar_scrim_height"
- android:layout_width="match_parent"
- android:layout_gravity="bottom"
- android:elevation="50dp"
- android:outlineProvider="none"
- android:background="@drawable/assist_orb_navbar_scrim"/>
-
-</com.android.systemui.assist.AssistOrbContainer>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index af5d85d..c5b47d0 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -87,8 +87,6 @@
<color name="notification_section_clear_all_btn_color">@color/GM2_grey_700</color>
- <color name="assist_orb_color">#ffffff</color>
-
<color name="keyguard_user_switcher_background_gradient_color">#77000000</color>
<!-- The color of the navigation bar icons. Need to be in sync with ic_sysbar_* -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 8d0895c..059aad7 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -678,25 +678,6 @@
from Keyguard. -->
<dimen name="go_to_full_shade_appearing_translation">200dp</dimen>
- <!-- The diameter of the search panel circle. -->
- <dimen name="assist_orb_size">144dp</dimen>
-
- <!-- The margin to the edge of the screen from where the orb starts to appear -->
- <dimen name="assist_orb_base_margin">22dp</dimen>
-
- <!-- The amount the orb translates when appearing -->
- <dimen name="assist_orb_travel_distance">26dp</dimen>
-
- <!-- The elevation of the orb -->
- <dimen name="assist_orb_elevation">12dp</dimen>
-
- <!-- The height of the scrim behind the orb. -->
- <dimen name="assist_orb_scrim_height">250dp</dimen>
-
- <!-- The height of the scrim behind the search panel circle. Should be navigation_bar_height
- + 8dp. -->
- <dimen name="assist_orb_navbar_scrim_height">56dp</dimen>
-
<!-- The width/height of the keyguard bottom area icon view on keyguard. -->
<dimen name="keyguard_affordance_height">48dp</dimen>
<dimen name="keyguard_affordance_width">48dp</dimen>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
index e960e81..03f04d3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
@@ -38,10 +38,8 @@
val shouldListenForFingerprintAssistant: Boolean,
val switchingUser: Boolean,
val udfps: Boolean,
- val userDoesNotHaveTrust: Boolean,
- val userNeedsStrongAuth: Boolean
+ val userDoesNotHaveTrust: Boolean
) : KeyguardListenModel()
-
/**
* Verbose debug information associated with [KeyguardUpdateMonitor.shouldListenForFace].
*/
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index d27bc67..e24f07c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -2222,11 +2222,9 @@
!(mFingerprintLockedOut && mBouncer && mCredentialAttempted);
final boolean isEncryptedOrLockdownForUser = isEncryptedOrLockdown(user);
- final boolean userNeedsStrongAuth = userNeedsStrongAuth();
final boolean shouldListenUdfpsState = !isUdfps
|| (!userCanSkipBouncer
&& !isEncryptedOrLockdownForUser
- && !userNeedsStrongAuth
&& userDoesNotHaveTrust
&& !mFingerprintLockedOut);
@@ -2257,8 +2255,7 @@
shouldListenForFingerprintAssistant,
mSwitchingUser,
isUdfps,
- userDoesNotHaveTrust,
- userNeedsStrongAuth));
+ userDoesNotHaveTrust));
}
return shouldListen;
@@ -2362,7 +2359,15 @@
|| (DEBUG_FINGERPRINT
&& model instanceof KeyguardFingerprintListenModel
&& mFingerprintRunningState != BIOMETRIC_STATE_RUNNING);
- if (notYetRunning && model.getListening()) {
+ final boolean running =
+ (DEBUG_FACE
+ && model instanceof KeyguardFaceListenModel
+ && mFaceRunningState == BIOMETRIC_STATE_RUNNING)
+ || (DEBUG_FINGERPRINT
+ && model instanceof KeyguardFingerprintListenModel
+ && mFingerprintRunningState == BIOMETRIC_STATE_RUNNING);
+ if (notYetRunning && model.getListening()
+ || running && !model.getListening()) {
mListenModels.add(model);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index b1197e6..9d5b93c 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -7,7 +7,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.SearchManager;
import android.content.ActivityNotFoundException;
@@ -27,17 +26,16 @@
import com.android.internal.app.AssistUtils;
import com.android.internal.app.IVoiceInteractionSessionListener;
-import com.android.internal.app.IVoiceInteractionSessionShowCallback;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.assist.ui.DefaultUiController;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.model.SysUiState;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import javax.inject.Inject;
@@ -124,23 +122,8 @@
private final DeviceProvisionedController mDeviceProvisionedController;
private final CommandQueue mCommandQueue;
- private final AssistOrbController mOrbController;
protected final AssistUtils mAssistUtils;
- private IVoiceInteractionSessionShowCallback mShowCallback =
- new IVoiceInteractionSessionShowCallback.Stub() {
-
- @Override
- public void onFailed() throws RemoteException {
- mOrbController.postHide();
- }
-
- @Override
- public void onShown() throws RemoteException {
- mOrbController.postHide();
- }
- };
-
@Inject
public AssistManager(
DeviceProvisionedController controller,
@@ -149,20 +132,18 @@
CommandQueue commandQueue,
PhoneStateMonitor phoneStateMonitor,
OverviewProxyService overviewProxyService,
- ConfigurationController configurationController,
Lazy<SysUiState> sysUiState,
DefaultUiController defaultUiController,
- AssistLogger assistLogger) {
+ AssistLogger assistLogger,
+ @Main Handler uiHandler) {
mContext = context;
mDeviceProvisionedController = controller;
mCommandQueue = commandQueue;
mAssistUtils = assistUtils;
- mAssistDisclosure = new AssistDisclosure(context, new Handler());
+ mAssistDisclosure = new AssistDisclosure(context, uiHandler);
mPhoneStateMonitor = phoneStateMonitor;
mAssistLogger = assistLogger;
- mOrbController = new AssistOrbController(configurationController, context);
-
registerVoiceInteractionSessionListener();
mUiController = defaultUiController;
@@ -223,10 +204,6 @@
});
}
- protected boolean shouldShowOrb() {
- return !ActivityManager.isLowRamDeviceStatic();
- }
-
public void startAssist(Bundle args) {
final ComponentName assistComponent = getAssistInfo();
if (assistComponent == null) {
@@ -234,10 +211,6 @@
}
final boolean isService = assistComponent.equals(getVoiceInteractorComponentName());
- if (!isService || (!isVoiceSessionRunning() && shouldShowOrb())) {
- mOrbController.showOrb(assistComponent, isService);
- mOrbController.postHideDelayed(isService ? TIMEOUT_SERVICE : TIMEOUT_ACTIVITY);
- }
if (args == null) {
args = new Bundle();
@@ -329,7 +302,7 @@
private void startVoiceInteractor(Bundle args) {
mAssistUtils.showSessionForActiveService(args,
- VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, null);
+ VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, null, null);
}
public void launchVoiceAssistFromKeyguard() {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbContainer.java b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbContainer.java
deleted file mode 100644
index 95b9e81..0000000
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbContainer.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.assist;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
-
-public class AssistOrbContainer extends FrameLayout {
-
- private static final long EXIT_START_DELAY = 150;
-
- private View mScrim;
- private View mNavbarScrim;
- private AssistOrbView mOrb;
-
- private boolean mAnimatingOut;
-
- public AssistOrbContainer(Context context) {
- this(context, null);
- }
-
- public AssistOrbContainer(Context context, @Nullable AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public AssistOrbContainer(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mScrim = findViewById(R.id.assist_orb_scrim);
- mNavbarScrim = findViewById(R.id.assist_orb_navbar_scrim);
- mOrb = (AssistOrbView) findViewById(R.id.assist_orb);
- }
-
- public void show(final boolean show, boolean animate, Runnable onDone) {
- if (show) {
- if (getVisibility() != View.VISIBLE) {
- setVisibility(View.VISIBLE);
- if (animate) {
- startEnterAnimation(onDone);
- } else {
- reset();
- if (onDone != null) {
- onDone.run();
- }
- }
- }
- } else {
- if (animate) {
- startExitAnimation(new Runnable() {
- @Override
- public void run() {
- mAnimatingOut = false;
- setVisibility(View.GONE);
- if (onDone != null) {
- onDone.run();
- }
- }
- });
- } else {
- setVisibility(View.GONE);
- if (onDone != null) {
- onDone.run();
- }
- }
- }
- }
-
- private void reset() {
- mAnimatingOut = false;
- mOrb.reset();
- mScrim.setAlpha(1f);
- mNavbarScrim.setAlpha(1f);
- }
-
- private void startEnterAnimation(Runnable onDone) {
- if (mAnimatingOut) {
- return;
- }
- mOrb.startEnterAnimation();
- mScrim.setAlpha(0f);
- mNavbarScrim.setAlpha(0f);
- post(new Runnable() {
- @Override
- public void run() {
- mScrim.animate()
- .alpha(1f)
- .setDuration(300)
- .setStartDelay(0)
- .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- mNavbarScrim.animate()
- .alpha(1f)
- .setDuration(300)
- .setStartDelay(0)
- .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
- .withEndAction(onDone);
- }
- });
- }
-
- private void startExitAnimation(final Runnable endRunnable) {
- if (mAnimatingOut) {
- if (endRunnable != null) {
- endRunnable.run();
- }
- return;
- }
- mAnimatingOut = true;
- mOrb.startExitAnimation(EXIT_START_DELAY);
- mScrim.animate()
- .alpha(0f)
- .setDuration(250)
- .setStartDelay(EXIT_START_DELAY)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- mNavbarScrim.animate()
- .alpha(0f)
- .setDuration(250)
- .setStartDelay(EXIT_START_DELAY)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .withEndAction(endRunnable);
- }
-
- /**
- * Whether the panel is showing, or, if it's animating, whether it will be
- * when the animation is done.
- */
- public boolean isShowing() {
- return getVisibility() == View.VISIBLE && !mAnimatingOut;
- }
-
- public AssistOrbView getOrb() {
- return mOrb;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java
deleted file mode 100644
index 4082015..0000000
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.assist;
-
-import android.annotation.NonNull;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.PixelFormat;
-import android.os.Binder;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.ImageView;
-
-import com.android.settingslib.applications.InterestingConfigChanges;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-
-/**
- * AssistOrbController controls the showing and hiding of the assistant orb.
- */
-public class AssistOrbController {
- private static final String ASSIST_ICON_METADATA_NAME =
- "com.android.systemui.action_assist_icon";
- private static final String TAG = "AssistOrbController";
- private static final boolean VERBOSE = false;
-
- private final InterestingConfigChanges mInterestingConfigChanges;
- private AssistOrbContainer mView;
- private final Context mContext;
- private final WindowManager mWindowManager;
-
- private Runnable mHideRunnable = new Runnable() {
- @Override
- public void run() {
- mView.removeCallbacks(this);
- mView.show(false /* show */, true /* animate */, () -> {
- if (mView.isAttachedToWindow()) {
- mWindowManager.removeView(mView);
- }
- });
- }
- };
-
- private ConfigurationController.ConfigurationListener mConfigurationListener =
- new ConfigurationController.ConfigurationListener() {
- @Override
- public void onConfigChanged(Configuration newConfig) {
- if (!mInterestingConfigChanges.applyNewConfig(mContext.getResources())) {
- return;
- }
- boolean visible = false;
- if (mView != null) {
- visible = mView.isShowing();
- if (mView.isAttachedToWindow()) {
- mWindowManager.removeView(mView);
- }
- }
-
- if (visible) {
- showOrb(false);
- }
- }
- };
-
- AssistOrbController(ConfigurationController configurationController, Context context) {
- mContext = context;
- mWindowManager = mContext.getSystemService(WindowManager.class);
- mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION
- | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE
- | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
-
- configurationController.addCallback(mConfigurationListener);
- mConfigurationListener.onConfigChanged(context.getResources().getConfiguration());
- }
-
- public void postHide() {
- mView.post(mHideRunnable);
- }
-
- public void postHideDelayed(long delayMs) {
- mView.postDelayed(mHideRunnable, delayMs);
- }
-
- private void showOrb(boolean animated) {
- if (mView == null) {
- mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate(
- R.layout.assist_orb, null);
- mView.setVisibility(View.GONE);
- mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
- }
- if (!mView.isAttachedToWindow()) {
- WindowManager.LayoutParams params = getLayoutParams();
- mWindowManager.addView(mView, params);
- }
- mView.show(true, animated, null);
- }
-
- private WindowManager.LayoutParams getLayoutParams() {
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- mContext.getResources().getDimensionPixelSize(R.dimen.assist_orb_scrim_height),
- WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING,
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
- PixelFormat.TRANSLUCENT);
- lp.token = new Binder();
- lp.gravity = Gravity.BOTTOM | Gravity.START;
- lp.setTitle("AssistPreviewPanel");
- lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
- | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
- return lp;
- }
-
- public void showOrb(@NonNull ComponentName assistComponent, boolean isService) {
- showOrb(true);
- maybeSwapSearchIcon(assistComponent, isService);
- }
-
- private void maybeSwapSearchIcon(@NonNull ComponentName assistComponent, boolean isService) {
- replaceDrawable(mView.getOrb().getLogo(), assistComponent, ASSIST_ICON_METADATA_NAME,
- isService);
- }
-
- public void replaceDrawable(ImageView v, ComponentName component, String name,
- boolean isService) {
- if (component != null) {
- try {
- PackageManager packageManager = mContext.getPackageManager();
- // Look for the search icon specified in the activity meta-data
- Bundle metaData = isService
- ? packageManager.getServiceInfo(
- component, PackageManager.GET_META_DATA).metaData
- : packageManager.getActivityInfo(
- component, PackageManager.GET_META_DATA).metaData;
- if (metaData != null) {
- int iconResId = metaData.getInt(name);
- if (iconResId != 0) {
- Resources res = packageManager.getResourcesForApplication(
- component.getPackageName());
- v.setImageDrawable(res.getDrawable(iconResId));
- return;
- }
- }
- } catch (PackageManager.NameNotFoundException e) {
- if (VERBOSE) {
- Log.v(TAG, "Assistant component "
- + component.flattenToShortString() + " not found");
- }
- } catch (Resources.NotFoundException nfe) {
- Log.w(TAG, "Failed to swap drawable from "
- + component.flattenToShortString(), nfe);
- }
- }
- v.setImageDrawable(null);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java
deleted file mode 100644
index 16d9c84..0000000
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java
+++ /dev/null
@@ -1,279 +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
- */
-
-package com.android.systemui.assist;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Outline;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewOutlineProvider;
-import android.view.animation.Interpolator;
-import android.view.animation.OvershootInterpolator;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-
-import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
-
-public class AssistOrbView extends FrameLayout {
-
- private final int mCircleMinSize;
- private final int mBaseMargin;
- private final int mStaticOffset;
- private final Paint mBackgroundPaint = new Paint();
- private final Rect mCircleRect = new Rect();
- private final Rect mStaticRect = new Rect();
- private final Interpolator mOvershootInterpolator = new OvershootInterpolator();
-
- private boolean mClipToOutline;
- private final int mMaxElevation;
- private float mOutlineAlpha;
- private float mOffset;
- private float mCircleSize;
- private ImageView mLogo;
- private float mCircleAnimationEndValue;
-
- private ValueAnimator mOffsetAnimator;
- private ValueAnimator mCircleAnimator;
-
- private ValueAnimator.AnimatorUpdateListener mCircleUpdateListener
- = new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- applyCircleSize((float) animation.getAnimatedValue());
- updateElevation();
- }
- };
- private AnimatorListenerAdapter mClearAnimatorListener = new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mCircleAnimator = null;
- }
- };
- private ValueAnimator.AnimatorUpdateListener mOffsetUpdateListener
- = new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mOffset = (float) animation.getAnimatedValue();
- updateLayout();
- }
- };
-
-
- public AssistOrbView(Context context) {
- this(context, null);
- }
-
- public AssistOrbView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public AssistOrbView(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public AssistOrbView(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- if (mCircleSize > 0.0f) {
- outline.setOval(mCircleRect);
- } else {
- outline.setEmpty();
- }
- outline.setAlpha(mOutlineAlpha);
- }
- });
- setWillNotDraw(false);
- mCircleMinSize = context.getResources().getDimensionPixelSize(
- R.dimen.assist_orb_size);
- mBaseMargin = context.getResources().getDimensionPixelSize(
- R.dimen.assist_orb_base_margin);
- mStaticOffset = context.getResources().getDimensionPixelSize(
- R.dimen.assist_orb_travel_distance);
- mMaxElevation = context.getResources().getDimensionPixelSize(
- R.dimen.assist_orb_elevation);
- mBackgroundPaint.setAntiAlias(true);
- mBackgroundPaint.setColor(getResources().getColor(R.color.assist_orb_color));
- }
-
- public ImageView getLogo() {
- return mLogo;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- drawBackground(canvas);
- }
-
- private void drawBackground(Canvas canvas) {
- canvas.drawCircle(mCircleRect.centerX(), mCircleRect.centerY(), mCircleSize / 2,
- mBackgroundPaint);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mLogo = findViewById(R.id.search_logo);
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- mLogo.layout(0, 0, mLogo.getMeasuredWidth(), mLogo.getMeasuredHeight());
- if (changed) {
- updateCircleRect(mStaticRect, mStaticOffset, true);
- }
- }
-
- public void animateCircleSize(float circleSize, long duration,
- long startDelay, Interpolator interpolator) {
- if (circleSize == mCircleAnimationEndValue) {
- return;
- }
- if (mCircleAnimator != null) {
- mCircleAnimator.cancel();
- }
- mCircleAnimator = ValueAnimator.ofFloat(mCircleSize, circleSize);
- mCircleAnimator.addUpdateListener(mCircleUpdateListener);
- mCircleAnimator.addListener(mClearAnimatorListener);
- mCircleAnimator.setInterpolator(interpolator);
- mCircleAnimator.setDuration(duration);
- mCircleAnimator.setStartDelay(startDelay);
- mCircleAnimator.start();
- mCircleAnimationEndValue = circleSize;
- }
-
- private void applyCircleSize(float circleSize) {
- mCircleSize = circleSize;
- updateLayout();
- }
-
- private void updateElevation() {
- float t = (mStaticOffset - mOffset) / (float) mStaticOffset;
- t = 1.0f - Math.max(t, 0.0f);
- float offset = t * mMaxElevation;
- setElevation(offset);
- }
-
- /**
- * Animates the offset to the edge of the screen.
- *
- * @param offset The offset to apply.
- * @param startDelay The desired start delay if animated.
- *
- * @param interpolator The desired interpolator if animated. If null,
- * a default interpolator will be taken designed for appearing or
- * disappearing.
- */
- private void animateOffset(float offset, long duration, long startDelay,
- Interpolator interpolator) {
- if (mOffsetAnimator != null) {
- mOffsetAnimator.removeAllListeners();
- mOffsetAnimator.cancel();
- }
- mOffsetAnimator = ValueAnimator.ofFloat(mOffset, offset);
- mOffsetAnimator.addUpdateListener(mOffsetUpdateListener);
- mOffsetAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mOffsetAnimator = null;
- }
- });
- mOffsetAnimator.setInterpolator(interpolator);
- mOffsetAnimator.setStartDelay(startDelay);
- mOffsetAnimator.setDuration(duration);
- mOffsetAnimator.start();
- }
-
- private void updateLayout() {
- updateCircleRect();
- updateLogo();
- invalidateOutline();
- invalidate();
- updateClipping();
- }
-
- private void updateClipping() {
- boolean clip = mCircleSize < mCircleMinSize;
- if (clip != mClipToOutline) {
- setClipToOutline(clip);
- mClipToOutline = clip;
- }
- }
-
- private void updateLogo() {
- float translationX = (mCircleRect.left + mCircleRect.right) / 2.0f - mLogo.getWidth() / 2.0f;
- float translationY = (mCircleRect.top + mCircleRect.bottom) / 2.0f
- - mLogo.getHeight() / 2.0f - mCircleMinSize / 7f;
- float t = (mStaticOffset - mOffset) / (float) mStaticOffset;
- translationY += t * mStaticOffset * 0.1f;
- float alpha = 1.0f-t;
- alpha = Math.max((alpha - 0.5f) * 2.0f, 0);
- mLogo.setImageAlpha((int) (alpha * 255));
- mLogo.setTranslationX(translationX);
- mLogo.setTranslationY(translationY);
- }
-
- private void updateCircleRect() {
- updateCircleRect(mCircleRect, mOffset, false);
- }
-
- private void updateCircleRect(Rect rect, float offset, boolean useStaticSize) {
- int left, top;
- float circleSize = useStaticSize ? mCircleMinSize : mCircleSize;
- left = (int) (getWidth() - circleSize) / 2;
- top = (int) (getHeight() - circleSize / 2 - mBaseMargin - offset);
- rect.set(left, top, (int) (left + circleSize), (int) (top + circleSize));
- }
-
- public void startExitAnimation(long delay) {
- animateCircleSize(0, 200, delay, Interpolators.FAST_OUT_LINEAR_IN);
- animateOffset(0, 200, delay, Interpolators.FAST_OUT_LINEAR_IN);
- }
-
- public void startEnterAnimation() {
- applyCircleSize(0);
- post(new Runnable() {
- @Override
- public void run() {
- animateCircleSize(mCircleMinSize, 300, 0 /* delay */, mOvershootInterpolator);
- animateOffset(mStaticOffset, 400, 0 /* delay */, Interpolators.LINEAR_OUT_SLOW_IN);
- }
- });
- }
-
- public void reset() {
- mClipToOutline = false;
- mBackgroundPaint.setAlpha(255);
- mOutlineAlpha = 1.0f;
- }
-
- @Override
- public boolean hasOverlappingRendering() {
- // not really true but it's ok during an animation, as it's never permanent
- return false;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 1bad19e..d60edbf 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -47,6 +47,7 @@
import android.os.Trace;
import android.os.VibrationEffect;
import android.os.Vibrator;
+import android.provider.Settings;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -162,6 +163,7 @@
private boolean mOnFingerDown;
private boolean mAttemptedToDismissKeyguard;
private Set<Callback> mCallbacks = new HashSet<>();
+ private final VibrationEffect mLowTick;
@VisibleForTesting
public static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES =
@@ -171,6 +173,7 @@
.setUsage(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY)
.build();
+ // haptic to use for successful device entry
public static final VibrationEffect EFFECT_CLICK =
VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
@@ -276,6 +279,9 @@
return;
}
mGoodCaptureReceived = true;
+ if (mVibrator != null) {
+ mVibrator.cancel();
+ }
mView.stopIllumination();
if (mServerRequest != null) {
mServerRequest.onAcquiredGood();
@@ -434,7 +440,7 @@
if (idx == event.getActionIndex()) {
boolean actionMoveWithinSensorArea =
isWithinSensorArea(udfpsView, event.getX(idx), event.getY(idx),
- fromUdfpsView);
+ fromUdfpsView);
if ((fromUdfpsView || actionMoveWithinSensorArea)
&& shouldTryToDismissKeyguard()) {
Log.v(TAG, "onTouch | dismiss keyguard ACTION_MOVE");
@@ -508,9 +514,9 @@
private boolean shouldTryToDismissKeyguard() {
return mView.getAnimationViewController() != null
- && mView.getAnimationViewController() instanceof UdfpsKeyguardViewController
- && mKeyguardStateController.canDismissLockScreen()
- && !mAttemptedToDismissKeyguard;
+ && mView.getAnimationViewController() instanceof UdfpsKeyguardViewController
+ && mKeyguardStateController.canDismissLockScreen()
+ && !mAttemptedToDismissKeyguard;
}
@Inject
@@ -542,7 +548,6 @@
@NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
mContext = context;
mExecution = execution;
- // TODO (b/185124905): inject main handler and vibrator once done prototyping
mVibrator = vibrator;
mInflater = inflater;
// The fingerprint manager is queried for UDFPS before this class is constructed, so the
@@ -567,6 +572,7 @@
mConfigurationController = configurationController;
mSystemClock = systemClock;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
+ mLowTick = lowTick();
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
@@ -601,6 +607,27 @@
udfpsHapticsSimulator.setUdfpsController(this);
}
+ private VibrationEffect lowTick() {
+ float tickIntensity = Settings.Global.getFloat(
+ mContext.getContentResolver(), "low-tick-intensity", .5f);
+ VibrationEffect.Composition composition = VibrationEffect.startComposition();
+ composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK,
+ tickIntensity, 0);
+ int tickDelay = Settings.Global.getInt(
+ mContext.getContentResolver(), "low-tick-delay", 25);
+ int primitives = 1000 / tickDelay;
+ float[] rampUp = new float[]{.48f, .58f, .69f, .83f};
+ for (int i = 0; i < rampUp.length; i++) {
+ composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK,
+ tickIntensity * rampUp[i], tickDelay);
+ }
+ for (int i = rampUp.length; i < primitives; i++) {
+ composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK,
+ tickIntensity, tickDelay);
+ }
+ return composition.compose();
+ }
+
/**
* Play haptic to signal udfps scanning started.
*/
@@ -610,8 +637,8 @@
mVibrator.vibrate(
Process.myUid(),
mContext.getOpPackageName(),
- EFFECT_CLICK,
- "udfps-onStart",
+ mLowTick,
+ "udfps-onStart-tick",
VIBRATION_SONIFICATION_ATTRIBUTES);
}
}
@@ -998,6 +1025,7 @@
}
}
mOnFingerDown = false;
+ mVibrator.cancel();
if (mView.isIlluminationRequested()) {
mView.stopIllumination();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 3c86760..383c442 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -69,6 +69,7 @@
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
+import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -129,6 +130,7 @@
},
subcomponents = {
StatusBarComponent.class,
+ StatusBarFragmentComponent.class,
NotificationRowComponent.class,
DozeComponent.class,
ExpandableNotificationRowComponent.class,
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 765c245..d27c39a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -16,6 +16,10 @@
package com.android.systemui.doze;
+import static android.os.PowerManager.GO_TO_SLEEP_REASON_TIMEOUT;
+
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -31,11 +35,13 @@
import android.provider.Settings;
import android.util.IndentingPrintWriter;
+import com.android.internal.R;
import com.android.systemui.doze.dagger.BrightnessSensor;
import com.android.systemui.doze.dagger.DozeScope;
import com.android.systemui.doze.dagger.WrappedService;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.util.sensors.AsyncSensorManager;
@@ -57,6 +63,12 @@
"com.android.systemui.doze.AOD_BRIGHTNESS";
protected static final String BRIGHTNESS_BUCKET = "brightness_bucket";
+ /**
+ * Just before the screen times out from user inactivity, DisplayPowerController dims the screen
+ * brightness to the lower of {@link #mScreenBrightnessDim}, or the current brightness minus
+ * this amount.
+ */
+ private final float mScreenBrightnessMinimumDimAmountFloat;
private final Context mContext;
private final DozeMachine.Service mDozeService;
private final DozeHost mDozeHost;
@@ -87,6 +99,8 @@
*/
private int mDebugBrightnessBucket = -1;
+ private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+
@Inject
public DozeScreenBrightness(
Context context,
@@ -98,8 +112,8 @@
WakefulnessLifecycle wakefulnessLifecycle,
DozeParameters dozeParameters,
DevicePostureController devicePostureController,
- DozeLog dozeLog
- ) {
+ DozeLog dozeLog,
+ UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
mContext = context;
mDozeService = service;
mSensorManager = sensorManager;
@@ -111,6 +125,10 @@
mDozeHost = host;
mHandler = handler;
mDozeLog = dozeLog;
+ mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
+
+ mScreenBrightnessMinimumDimAmountFloat = context.getResources().getFloat(
+ R.dimen.config_screenBrightnessMinimumDimAmountFloat);
mDefaultDozeBrightness = alwaysOnDisplayPolicy.defaultDozeBrightness;
mScreenBrightnessDim = alwaysOnDisplayPolicy.dimBrightness;
@@ -163,14 +181,15 @@
}
}
- private void updateBrightnessAndReady(boolean force) {
+ public void updateBrightnessAndReady(boolean force) {
if (force || mRegistered || mDebugBrightnessBucket != -1) {
int sensorValue = mDebugBrightnessBucket == -1
? mLastSensorValue : mDebugBrightnessBucket;
int brightness = computeBrightness(sensorValue);
boolean brightnessReady = brightness > 0;
if (brightnessReady) {
- mDozeService.setDozeScreenBrightness(clampToUserSetting(brightness));
+ mDozeService.setDozeScreenBrightness(
+ clampToDimBrightnessForScreenOff(clampToUserSetting(brightness)));
}
int scrimOpacity = -1;
@@ -243,13 +262,24 @@
/**
* Clamp the brightness to the dim brightness value used by PowerManagerService just before the
* device times out and goes to sleep, if we are sleeping from a timeout. This ensures that we
- * don't raise the brightness back to the user setting before playing the screen off animation.
+ * don't raise the brightness back to the user setting before or during the screen off
+ * animation.
*/
private int clampToDimBrightnessForScreenOff(int brightness) {
- if (mDozeParameters.shouldControlUnlockedScreenOff()
- && mWakefulnessLifecycle.getLastSleepReason()
- == PowerManager.GO_TO_SLEEP_REASON_TIMEOUT) {
- return Math.min(mScreenBrightnessDim, brightness);
+ final boolean screenTurningOff =
+ mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()
+ || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_GOING_TO_SLEEP;
+ if (screenTurningOff
+ && mWakefulnessLifecycle.getLastSleepReason() == GO_TO_SLEEP_REASON_TIMEOUT) {
+ return Math.max(
+ PowerManager.BRIGHTNESS_OFF,
+ // Use the lower of either the dim brightness, or the current brightness reduced
+ // by the minimum dim amount. This is the same logic used in
+ // DisplayPowerController#updatePowerState to apply a minimum dim amount.
+ Math.min(
+ brightness - (int) Math.floor(
+ mScreenBrightnessMinimumDimAmountFloat * 255),
+ mScreenBrightnessDim));
} else {
return brightness;
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index 908397b..3631938 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -77,6 +77,7 @@
private final Provider<UdfpsController> mUdfpsControllerProvider;
@Nullable private UdfpsController mUdfpsController;
private final DozeLog mDozeLog;
+ private final DozeScreenBrightness mDozeScreenBrightness;
private int mPendingScreenState = Display.STATE_UNKNOWN;
private SettableWakeLock mWakeLock;
@@ -90,7 +91,8 @@
WakeLock wakeLock,
AuthController authController,
Provider<UdfpsController> udfpsControllerProvider,
- DozeLog dozeLog) {
+ DozeLog dozeLog,
+ DozeScreenBrightness dozeScreenBrightness) {
mDozeService = service;
mHandler = handler;
mParameters = parameters;
@@ -99,6 +101,7 @@
mAuthController = authController;
mUdfpsControllerProvider = udfpsControllerProvider;
mDozeLog = dozeLog;
+ mDozeScreenBrightness = dozeScreenBrightness;
updateUdfpsController();
if (mUdfpsController == null) {
@@ -209,6 +212,12 @@
if (screenState != Display.STATE_UNKNOWN) {
if (DEBUG) Log.d(TAG, "setDozeScreenState(" + screenState + ")");
mDozeService.setDozeScreenState(screenState);
+ if (screenState == Display.STATE_DOZE) {
+ // If we're entering doze, update the doze screen brightness. We might have been
+ // clamping it to the dim brightness during the screen off animation, and we should
+ // now change it to the brightness we actually want according to the sensor.
+ mDozeScreenBrightness.updateBrightnessAndReady(false /* force */);
+ }
mPendingScreenState = Display.STATE_UNKNOWN;
mWakeLock.setAcquired(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
index 5f7ad58..f8bdaf6 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
@@ -18,8 +18,6 @@
import android.content.Context;
import android.util.FeatureFlagUtils;
-import android.util.Log;
-import android.widget.Toast;
import com.android.systemui.dagger.SysUISingleton;
@@ -33,12 +31,10 @@
@SysUISingleton
public class FeatureFlags {
private final FlagReader mFlagReader;
- private final Context mContext;
@Inject
- public FeatureFlags(FlagReader flagReader, Context context) {
+ public FeatureFlags(FlagReader flagReader) {
mFlagReader = flagReader;
- mContext = context;
}
/**
@@ -49,22 +45,6 @@
return mFlagReader.isEnabled(flag);
}
- public void assertLegacyPipelineEnabled() {
- if (isNewNotifPipelineRenderingEnabled()) {
- throw new IllegalStateException("Old pipeline code running w/ new pipeline enabled");
- }
- }
-
- public boolean checkLegacyPipelineEnabled() {
- if (!isNewNotifPipelineRenderingEnabled()) {
- return true;
- }
- Log.d("NotifPipeline", "Old pipeline code running w/ new pipeline enabled",
- new Exception());
- Toast.makeText(mContext, "Old pipeline code running!", Toast.LENGTH_SHORT).show();
- return false;
- }
-
public boolean isNewNotifPipelineRenderingEnabled() {
return isEnabled(Flags.NEW_NOTIFICATION_PIPELINE_RENDERING);
}
@@ -129,8 +109,8 @@
}
/** System setting for provider model behavior */
- public boolean isProviderModelSettingEnabled() {
- return FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
+ public boolean isProviderModelSettingEnabled(Context context) {
+ return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
}
/**
@@ -146,9 +126,4 @@
public boolean useCombinedQSHeaders() {
return isEnabled(Flags.COMBINED_QS_HEADERS);
}
-
- /** static method for the system setting */
- public static boolean isProviderModelSettingEnabled(Context context) {
- return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index ee24f45..c60e098 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -92,6 +92,9 @@
/***************************************/
// 600- status bar
+ public static final BooleanFlag STATUS_BAR_PROVIDER_MODEL =
+ new BooleanFlag(600, false);
+
public static final BooleanFlag COMBINED_STATUS_BAR_SIGNAL_ICONS =
new BooleanFlag(601, false);
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index 4f5a969..7f57fcc 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -24,7 +24,7 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.qs.QSFragment;
-import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.policy.ConfigurationController;
import java.io.FileDescriptor;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java
index c8afd72..9ca0293 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java
@@ -26,8 +26,8 @@
import javax.inject.Qualifier;
/**
- * A {@link LogBuffer} for
- * {@link com.android.systemui.statusbar.phone.CollapsedStatusBarFragment}-related messages.
+ * A {@link LogBuffer} for {@link
+ * com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment}-related messages.
*/
@Qualifier
@Documented
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 02beff9..d3bd0a5 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -110,7 +110,7 @@
/**
* Provides a logging buffer for
- * {@link com.android.systemui.statusbar.phone.CollapsedStatusBarFragment}.
+ * {@link com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment}.
*/
@Provides
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index fa37c86..5afefa1 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -100,8 +100,7 @@
private static final int MAX_NUM_LOGGED_PREDICTIONS = 10;
private static final int MAX_NUM_LOGGED_GESTURES = 10;
- // Temporary log until b/201642126 is resolved
- static final boolean DEBUG_MISSING_GESTURE = true;
+ static final boolean DEBUG_MISSING_GESTURE = false;
static final String DEBUG_MISSING_GESTURE_TAG = "NoBackGesture";
private ISystemGestureExclusionListener mGestureExclusionListener =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index cdf770f..b533ac4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -1,5 +1,7 @@
package com.android.systemui.qs;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -20,6 +22,7 @@
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
+import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile;
@@ -533,6 +536,11 @@
private final ViewPager.OnPageChangeListener mOnPageChangeListener =
new ViewPager.SimpleOnPageChangeListener() {
+
+ private int mCurrentScrollState = SCROLL_STATE_IDLE;
+ // Flag to avoid redundant call InteractionJankMonitor::begin()
+ private boolean mIsScrollJankTraceBegin = false;
+
@Override
public void onPageSelected(int position) {
updateSelected();
@@ -546,6 +554,13 @@
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
+
+ if (!mIsScrollJankTraceBegin && mCurrentScrollState == SCROLL_STATE_DRAGGING) {
+ InteractionJankMonitor.getInstance().begin(PagedTileLayout.this,
+ CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE);
+ mIsScrollJankTraceBegin = true;
+ }
+
if (mPageIndicator == null) return;
mPageIndicatorPosition = position + positionOffset;
mPageIndicator.setLocation(mPageIndicatorPosition);
@@ -554,6 +569,16 @@
(isLayoutRtl() ? position == mPages.size() - 1 : position == 0));
}
}
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ if (state != mCurrentScrollState && state == SCROLL_STATE_IDLE) {
+ InteractionJankMonitor.getInstance().end(
+ CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE);
+ mIsScrollJankTraceBegin = false;
+ }
+ mCurrentScrollState = state;
+ }
};
private final PagerAdapter mAdapter = new PagerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index dd876b7..e42c47b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -15,10 +15,10 @@
package com.android.systemui.qs;
import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
-import static com.android.systemui.statusbar.DisableFlagsLogger.DisableState;
import static com.android.systemui.media.dagger.MediaModule.QS_PANEL;
import static com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL;
+import static com.android.systemui.statusbar.DisableFlagsLogger.DisableState;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -696,6 +696,11 @@
mQSPanelController.closeDetail();
}
+ @Override
+ public void closeCustomizer() {
+ mQSCustomizerController.hide();
+ }
+
public void notifyCustomizeChanged() {
// The customize state changed, so our height changed.
mContainer.updateExpansion();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt
index 17a815e..8544f61 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt
@@ -4,7 +4,6 @@
import com.android.systemui.log.LogLevel
import com.android.systemui.log.dagger.QSFragmentDisableLog
import com.android.systemui.statusbar.DisableFlagsLogger
-import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment
import javax.inject.Inject
/** A helper class for logging disable flag changes made in [QSFragment]. */
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 0196769..af191a1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -536,7 +536,7 @@
}
}
}
- if (featureFlags.isProviderModelSettingEnabled()) {
+ if (featureFlags.isProviderModelSettingEnabled(context)) {
if (!tiles.contains("internet")) {
if (tiles.contains("wifi")) {
// Replace the WiFi with Internet, and remove the Cell
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
index 8aa2d09..d2bc38e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
@@ -54,19 +54,23 @@
}
public int getValue() {
- return mSecureSettings.getIntForUser(mSettingName, mDefaultValue, mUserId);
+ return mListening ? mObservedValue : getValueFromProvider();
}
public void setValue(int value) {
mSecureSettings.putIntForUser(mSettingName, value, mUserId);
}
+ private int getValueFromProvider() {
+ return mSecureSettings.getIntForUser(mSettingName, mDefaultValue, mUserId);
+ }
+
@Override
public void setListening(boolean listening) {
if (listening == mListening) return;
mListening = listening;
if (listening) {
- mObservedValue = getValue();
+ mObservedValue = getValueFromProvider();
mSecureSettings.registerContentObserverForUser(
mSecureSettings.getUriFor(mSettingName), false, this, mUserId);
} else {
@@ -77,9 +81,10 @@
@Override
public void onChange(boolean selfChange) {
- final int value = getValue();
- handleValueChanged(value, value != mObservedValue);
+ final int value = getValueFromProvider();
+ final boolean changed = value != mObservedValue;
mObservedValue = value;
+ handleValueChanged(value, changed);
}
public void setUserId(int userId) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 993bbd0..eef3b45 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -121,7 +121,7 @@
}
final ArrayList<QSTile> tilesToAdd = new ArrayList<>();
- if (mFeatureFlags.isProviderModelSettingEnabled()) {
+ if (mFeatureFlags.isProviderModelSettingEnabled(mContext)) {
possibleTiles.remove("cell");
possibleTiles.remove("wifi");
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index e896c7c..b1cd68e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -61,10 +61,12 @@
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.SecureSetting;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.volume.ZenModePanel;
import javax.inject.Inject;
@@ -81,6 +83,7 @@
private final ZenModeController mController;
private final DndDetailAdapter mDetailAdapter;
private final SharedPreferences mSharedPreferences;
+ private final SecureSetting mSettingZenDuration;
private boolean mListening;
private boolean mShowingDetail;
@@ -96,7 +99,8 @@
ActivityStarter activityStarter,
QSLogger qsLogger,
ZenModeController zenModeController,
- @Main SharedPreferences sharedPreferences
+ @Main SharedPreferences sharedPreferences,
+ SecureSettings secureSettings
) {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
@@ -104,8 +108,17 @@
mSharedPreferences = sharedPreferences;
mDetailAdapter = new DndDetailAdapter();
mController.observe(getLifecycle(), mZenCallback);
+ mSettingZenDuration = new SecureSetting(secureSettings, mUiHandler,
+ Settings.Secure.ZEN_DURATION, getHost().getUserId()) {
+ @Override
+ protected void handleValueChanged(int value, boolean observedChange) {
+ refreshState();
+ }
+ };
}
+
+
public static void setVisible(Context context, boolean visible) {
Prefs.putBoolean(context, Prefs.Key.DND_TILE_VISIBLE, visible);
}
@@ -144,14 +157,18 @@
if (mState.value) {
mController.setZen(ZEN_MODE_OFF, null, TAG);
} else {
- showDetail(true);
+ enableZenMode(view);
}
}
@Override
- public void showDetail(boolean show) {
- int zenDuration = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.ZEN_DURATION, 0);
+ protected void handleUserSwitch(int newUserId) {
+ super.handleUserSwitch(newUserId);
+ mSettingZenDuration.setUserId(newUserId);
+ }
+
+ private void enableZenMode(@Nullable View view) {
+ int zenDuration = mSettingZenDuration.getValue();
boolean showOnboarding = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0
&& Settings.Secure.getInt(mContext.getContentResolver(),
@@ -270,6 +287,8 @@
state.dualLabelContentDescription = mContext.getResources().getString(
R.string.accessibility_quick_settings_open_settings, getTileLabel());
state.expandedAccessibilityClassName = Switch.class.getName();
+ state.forceExpandIcon =
+ mSettingZenDuration.getValue() == Settings.Secure.ZEN_DURATION_PROMPT;
}
@Override
@@ -296,6 +315,13 @@
} else {
Prefs.unregisterListener(mContext, mPrefListener);
}
+ mSettingZenDuration.setListening(listening);
+ }
+
+ @Override
+ protected void handleDestroy() {
+ super.handleDestroy();
+ mSettingZenDuration.setListening(false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index 563c4cd..77b9cc1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -306,12 +306,8 @@
final boolean isWifiScanEnabled = mInternetDialogController.isWifiScanEnabled();
updateWifiToggle(isWifiEnabled, isDeviceLocked);
updateConnectedWifi(isWifiEnabled, isDeviceLocked);
+ updateWifiListAndSeeAll(isWifiEnabled, isDeviceLocked);
updateWifiScanNotify(isWifiEnabled, isWifiScanEnabled, isDeviceLocked);
-
- final int visibility = (isDeviceLocked || !isWifiEnabled || mWifiEntriesCount <= 0)
- ? View.GONE : View.VISIBLE;
- mWifiRecyclerView.setVisibility(visibility);
- mSeeAllLayout.setVisibility(visibility);
}
private void setOnClickListener() {
@@ -414,6 +410,18 @@
}
@MainThread
+ private void updateWifiListAndSeeAll(boolean isWifiEnabled, boolean isDeviceLocked) {
+ if (!isWifiEnabled || isDeviceLocked) {
+ mWifiRecyclerView.setVisibility(View.GONE);
+ mSeeAllLayout.setVisibility(View.GONE);
+ return;
+ }
+ mWifiRecyclerView.setVisibility(mWifiEntriesCount > 0 ? View.VISIBLE : View.GONE);
+ mSeeAllLayout.setVisibility(
+ (mConnectedWifiEntry != null || mWifiEntriesCount > 0) ? View.VISIBLE : View.GONE);
+ }
+
+ @MainThread
private void updateWifiScanNotify(boolean isWifiEnabled, boolean isWifiScanEnabled,
boolean isDeviceLocked) {
if (isWifiEnabled || !isWifiScanEnabled || isDeviceLocked) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 7cfa830..3fbed64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -33,11 +33,9 @@
import android.media.MediaMetadata;
import android.media.session.MediaController;
import android.media.session.MediaSession;
-import android.media.session.MediaSessionManager;
import android.media.session.PlaybackState;
import android.os.AsyncTask;
import android.os.Trace;
-import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationStats;
import android.service.notification.StatusBarNotification;
@@ -83,7 +81,6 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
-import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@@ -133,7 +130,6 @@
private final DelayableExecutor mMainExecutor;
private final Context mContext;
- private final MediaSessionManager mMediaSessionManager;
private final ArrayList<MediaListener> mMediaListeners;
private final Lazy<Optional<StatusBar>> mStatusBarOptionalLazy;
private final MediaArtworkProcessor mMediaArtworkProcessor;
@@ -196,10 +192,6 @@
mMediaArtworkProcessor = mediaArtworkProcessor;
mKeyguardBypassController = keyguardBypassController;
mMediaListeners = new ArrayList<>();
- // TODO: use MediaSessionManager.SessionListener to hook us up to future updates
- // in session state
- mMediaSessionManager = (MediaSessionManager) mContext.getSystemService(
- Context.MEDIA_SESSION_SERVICE);
// TODO: use KeyguardStateController#isOccluded to remove this dependency
mStatusBarOptionalLazy = statusBarOptionalLazy;
mNotificationShadeWindowController = notificationShadeWindowController;
@@ -476,35 +468,6 @@
}
}
}
- if (mediaNotification == null) {
- // Still nothing? OK, let's just look for live media sessions and see if they match
- // one of our notifications. This will catch apps that aren't (yet!) using media
- // notifications.
-
- if (mMediaSessionManager != null) {
- // TODO: Should this really be for all users? It appears that inactive users
- // can't have active sessions, which would mean it is fine.
- final List<MediaController> sessions =
- mMediaSessionManager.getActiveSessionsForUser(null, UserHandle.ALL);
-
- for (MediaController aController : sessions) {
- // now to see if we have one like this
- final String pkg = aController.getPackageName();
-
- for (NotificationEntry entry : allNotifications) {
- if (entry.getSbn().getPackageName().equals(pkg)) {
- if (DEBUG_MEDIA) {
- Log.v(TAG, "DEBUG_MEDIA: found controller matching "
- + entry.getSbn().getKey());
- }
- controller = aController;
- mediaNotification = entry;
- break;
- }
- }
- }
- }
- }
if (controller != null && !sameSessions(mMediaController, controller)) {
// We have a new media session
@@ -550,8 +513,6 @@
@Override
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
- pw.print(" mMediaSessionManager=");
- pw.println(mMediaSessionManager);
pw.print(" mMediaNotificationKey=");
pw.println(mMediaNotificationKey);
pw.print(" mMediaController=");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index ff3e97a..18c8b7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -33,6 +33,7 @@
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
import com.android.systemui.statusbar.notification.DynamicChildBindController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.LowPriorityInflationHelper;
@@ -91,6 +92,7 @@
private final DynamicPrivacyController mDynamicPrivacyController;
private final KeyguardBypassController mBypassController;
private final ForegroundServiceSectionController mFgsSectionController;
+ private final NotifPipelineFlags mNotifPipelineFlags;
private AssistantFeedbackController mAssistantFeedbackController;
private final Context mContext;
@@ -121,7 +123,8 @@
ForegroundServiceSectionController fgsSectionController,
DynamicChildBindController dynamicChildBindController,
LowPriorityInflationHelper lowPriorityInflationHelper,
- AssistantFeedbackController assistantFeedbackController) {
+ AssistantFeedbackController assistantFeedbackController,
+ NotifPipelineFlags notifPipelineFlags) {
mContext = context;
mHandler = mainHandler;
mFeatureFlags = featureFlags;
@@ -132,6 +135,7 @@
mStatusBarStateController = (SysuiStatusBarStateController) statusBarStateController;
mEntryManager = notificationEntryManager;
mFgsSectionController = fgsSectionController;
+ mNotifPipelineFlags = notifPipelineFlags;
Resources res = context.getResources();
mAlwaysExpandNonGroupedNotification =
res.getBoolean(R.bool.config_alwaysExpandNonGroupedNotifications);
@@ -157,7 +161,7 @@
//TODO: Rewrite this to focus on Entries, or some other data object instead of views
public void updateNotificationViews() {
Assert.isMainThread();
- if (!mFeatureFlags.checkLegacyPipelineEnabled()) {
+ if (!mNotifPipelineFlags.checkLegacyPipelineEnabled()) {
return;
}
@@ -435,7 +439,7 @@
*/
public void updateRowStates() {
Assert.isMainThread();
- if (!mFeatureFlags.checkLegacyPipelineEnabled()) {
+ if (!mNotifPipelineFlags.checkLegacyPipelineEnabled()) {
return;
}
@@ -524,7 +528,9 @@
@Override
public void onDynamicPrivacyChanged() {
- mFeatureFlags.assertLegacyPipelineEnabled();
+ if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+ throw new IllegalStateException("Old pipeline code running w/ new pipeline enabled");
+ }
if (mPerformingUpdate) {
Log.w(TAG, "onDynamicPrivacyChanged made a re-entrant call");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java
index 9ae7ea2..82e1cf8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java
@@ -227,7 +227,7 @@
mMobileStatusTracker = new MobileStatusTracker(mPhone, receiverLooper,
info, mDefaults, mMobileCallback);
mProviderModelBehavior = featureFlags.isCombinedStatusBarSignalIconsEnabled();
- mProviderModelSetting = featureFlags.isProviderModelSettingEnabled();
+ mProviderModelSetting = featureFlags.isProviderModelSettingEnabled(mContext);
}
void setConfiguration(Config config) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
index 26780eb..a87efd7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
@@ -442,7 +442,7 @@
mDemoModeController.addCallback(this);
mProviderModelBehavior = mFeatureFlags.isCombinedStatusBarSignalIconsEnabled();
- mProviderModelSetting = mFeatureFlags.isProviderModelSettingEnabled();
+ mProviderModelSetting = mFeatureFlags.isProviderModelSettingEnabled(mContext);
mDumpManager.registerDumpable(TAG, this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java
index 103ca0e..b5d3637 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java
@@ -68,7 +68,7 @@
new WifiTrafficStateCallback());
}
mCurrentState.iconGroup = mLastState.iconGroup = mUnmergedWifiIconGroup;
- mProviderModelSetting = featureFlags.isProviderModelSettingEnabled();
+ mProviderModelSetting = featureFlags.isProviderModelSettingEnabled(mContext);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
index d5cba72..77463fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
@@ -52,6 +52,7 @@
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
import com.android.systemui.statusbar.notification.DynamicChildBindController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -211,7 +212,8 @@
ForegroundServiceSectionController fgsSectionController,
DynamicChildBindController dynamicChildBindController,
LowPriorityInflationHelper lowPriorityInflationHelper,
- AssistantFeedbackController assistantFeedbackController) {
+ AssistantFeedbackController assistantFeedbackController,
+ NotifPipelineFlags notifPipelineFlags) {
return new NotificationViewHierarchyManager(
context,
mainHandler,
@@ -227,7 +229,8 @@
fgsSectionController,
dynamicChildBindController,
lowPriorityInflationHelper,
- assistantFeedbackController);
+ assistantFeedbackController,
+ notifPipelineFlags);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
new file mode 100644
index 0000000..914697b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
@@ -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.
+ */
+
+package com.android.systemui.statusbar.notification
+
+import android.content.Context
+import android.util.Log
+import android.widget.Toast
+import com.android.systemui.flags.FeatureFlags
+import javax.inject.Inject
+
+class NotifPipelineFlags @Inject constructor(
+ val context: Context,
+ val featureFlags: FeatureFlags
+) {
+ fun checkLegacyPipelineEnabled(): Boolean {
+ if (!featureFlags.isNewNotifPipelineRenderingEnabled) {
+ return true
+ }
+ Log.d("NotifPipeline", "Old pipeline code running w/ new pipeline enabled", Exception())
+ Toast.makeText(context, "Old pipeline code running!", Toast.LENGTH_SHORT).show()
+ return false
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index 5c8e8b2..4c7b2bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -25,12 +25,12 @@
import com.android.internal.util.NotificationMessagingUtil;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.InflationException;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationClicker;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.LowPriorityInflationHelper;
@@ -55,7 +55,6 @@
private static final String TAG = "NotificationViewManager";
private final Context mContext;
- private final FeatureFlags mFeatureFlags;
private final NotificationMessagingUtil mMessagingUtil;
private final NotificationRemoteInputManager mNotificationRemoteInputManager;
private final NotificationLockscreenUserManager mNotificationLockscreenUserManager;
@@ -66,6 +65,7 @@
mExpandableNotificationRowComponentBuilder;
private final IconManager mIconManager;
private final LowPriorityInflationHelper mLowPriorityInflationHelper;
+ private final NotifPipelineFlags mNotifPipelineFlags;
private NotificationPresenter mPresenter;
private NotificationListContainer mListContainer;
@@ -75,7 +75,6 @@
@Inject
public NotificationRowBinderImpl(
Context context,
- FeatureFlags featureFlags,
NotificationMessagingUtil notificationMessagingUtil,
NotificationRemoteInputManager notificationRemoteInputManager,
NotificationLockscreenUserManager notificationLockscreenUserManager,
@@ -84,9 +83,9 @@
Provider<RowInflaterTask> rowInflaterTaskProvider,
ExpandableNotificationRowComponent.Builder expandableNotificationRowComponentBuilder,
IconManager iconManager,
- LowPriorityInflationHelper lowPriorityInflationHelper) {
+ LowPriorityInflationHelper lowPriorityInflationHelper,
+ NotifPipelineFlags notifPipelineFlags) {
mContext = context;
- mFeatureFlags = featureFlags;
mNotifBindPipeline = notifBindPipeline;
mRowContentBindStage = rowContentBindStage;
mMessagingUtil = notificationMessagingUtil;
@@ -96,6 +95,7 @@
mExpandableNotificationRowComponentBuilder = expandableNotificationRowComponentBuilder;
mIconManager = iconManager;
mLowPriorityInflationHelper = lowPriorityInflationHelper;
+ mNotifPipelineFlags = notifPipelineFlags;
}
/**
@@ -126,7 +126,7 @@
throws InflationException {
if (params == null) {
// weak assert that the params should always be passed in the new pipeline
- mFeatureFlags.checkLegacyPipelineEnabled();
+ mNotifPipelineFlags.checkLegacyPipelineEnabled();
}
ViewGroup parent = mListContainer.getViewParentForNotification(entry);
@@ -187,7 +187,7 @@
NotificationUiAdjustment oldAdjustment,
NotificationUiAdjustment newAdjustment,
NotificationRowContentBinder.InflationCallback callback) {
- mFeatureFlags.checkLegacyPipelineEnabled();
+ mNotifPipelineFlags.checkLegacyPipelineEnabled();
if (NotificationUiAdjustment.needReinflate(oldAdjustment, newAdjustment)) {
if (entry.rowExists()) {
ExpandableNotificationRow row = entry.getRow();
@@ -238,7 +238,7 @@
isLowPriority = inflaterParams.isLowPriority();
} else {
// LEGACY pipeline
- mFeatureFlags.checkLegacyPipelineEnabled();
+ mNotifPipelineFlags.checkLegacyPipelineEnabled();
// If this is our first time inflating, we don't actually know the groupings for real
// yet, so we might actually inflate a low priority content view incorrectly here and
// have to correct it later in the pipeline. On subsequent inflations (i.e. updates),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LowPriorityInflationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LowPriorityInflationHelper.java
index dd1f948..ae4f2bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LowPriorityInflationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LowPriorityInflationHelper.java
@@ -17,7 +17,7 @@
package com.android.systemui.statusbar.notification.collection.legacy;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.RowContentBindParams;
@@ -31,18 +31,18 @@
*/
@SysUISingleton
public class LowPriorityInflationHelper {
- private final FeatureFlags mFeatureFlags;
private final NotificationGroupManagerLegacy mGroupManager;
private final RowContentBindStage mRowContentBindStage;
+ private final NotifPipelineFlags mNotifPipelineFlags;
@Inject
LowPriorityInflationHelper(
- FeatureFlags featureFlags,
NotificationGroupManagerLegacy groupManager,
- RowContentBindStage rowContentBindStage) {
- mFeatureFlags = featureFlags;
+ RowContentBindStage rowContentBindStage,
+ NotifPipelineFlags notifPipelineFlags) {
mGroupManager = groupManager;
mRowContentBindStage = rowContentBindStage;
+ mNotifPipelineFlags = notifPipelineFlags;
}
/**
@@ -59,7 +59,7 @@
public void recheckLowPriorityViewAndInflate(
NotificationEntry entry,
ExpandableNotificationRow row) {
- mFeatureFlags.checkLegacyPipelineEnabled();
+ mNotifPipelineFlags.checkLegacyPipelineEnabled();
RowContentBindParams params = mRowContentBindStage.getStageParams(entry);
final boolean shouldBeLowPriority = shouldUseLowPriorityView(entry);
if (!row.isRemoved() && row.isLowPriority() != shouldBeLowPriority) {
@@ -73,7 +73,7 @@
* Whether the notification should inflate a low priority version of its content views.
*/
public boolean shouldUseLowPriorityView(NotificationEntry entry) {
- mFeatureFlags.checkLegacyPipelineEnabled();
+ mNotifPipelineFlags.checkLegacyPipelineEnabled();
return entry.isAmbient() && !mGroupManager.isChildInGroup(entry);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
index 408c457..88198f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
@@ -22,10 +22,10 @@
import android.view.View
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.R
-import com.android.systemui.flags.FeatureFlags
import com.android.systemui.media.KeyguardMediaController
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.NotifPipelineFlags
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController
import com.android.systemui.statusbar.notification.collection.render.ShadeViewManager
@@ -54,12 +54,12 @@
* TODO: Move remaining sections logic from NSSL into this class.
*/
class NotificationSectionsManager @Inject internal constructor(
- private val featureFlags: FeatureFlags,
private val statusBarStateController: StatusBarStateController,
private val configurationController: ConfigurationController,
private val keyguardMediaController: KeyguardMediaController,
private val sectionsFeatureManager: NotificationSectionsFeatureManager,
private val logger: NotificationSectionsLogger,
+ private val notifPipelineFlags: NotifPipelineFlags,
@IncomingHeader private val incomingHeaderController: SectionHeaderController,
@PeopleHeader private val peopleHeaderController: SectionHeaderController,
@AlertingHeader private val alertingHeaderController: SectionHeaderController,
@@ -201,7 +201,7 @@
override var targetPosition: Int? = null
override fun adjustViewPosition() {
- featureFlags.checkLegacyPipelineEnabled()
+ notifPipelineFlags.checkLegacyPipelineEnabled()
val target = targetPosition
val current = currentPosition
if (target == null) {
@@ -228,7 +228,7 @@
private fun <T : StackScrollerDecorView> decorViewHeaderState(
header: T
): SectionUpdateState<T> {
- featureFlags.checkLegacyPipelineEnabled()
+ notifPipelineFlags.checkLegacyPipelineEnabled()
val inner = expandableViewHeaderState(header)
return object : SectionUpdateState<T> by inner {
override fun adjustViewPosition() {
@@ -245,7 +245,7 @@
* bookkeeping and adds/moves/removes section headers if appropriate.
*/
fun updateSectionBoundaries(reason: String) {
- featureFlags.checkLegacyPipelineEnabled()
+ notifPipelineFlags.checkLegacyPipelineEnabled()
if (!isUsingMultipleSections) {
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index a66af04..c4ec086 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -183,6 +183,7 @@
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
import com.android.systemui.statusbar.phone.panelstate.PanelState;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -3019,6 +3020,10 @@
mStatusBarTouchableRegionManager.setPanelExpanded(isExpanded);
mStatusBar.setPanelExpanded(isExpanded);
mPanelExpanded = isExpanded;
+
+ if (!isExpanded && mQs != null && mQs.isCustomizing()) {
+ mQs.closeCustomizer();
+ }
}
}
@@ -3317,10 +3322,20 @@
return mQs.isShowingDetail();
}
+ /** Returns whether the QS customizer is currently active. */
+ public boolean isQsCustomizing() {
+ return mQs.isCustomizing();
+ }
+
public void closeQsDetail() {
mQs.closeDetail();
}
+ /** Close the QS customizer if it is open. */
+ public void closeQsCustomizer() {
+ mQs.closeCustomizer();
+ }
+
public boolean isLaunchTransitionFinished() {
return mIsLaunchTransitionFinished;
}
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 06cf70d..2a54642 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -136,7 +136,6 @@
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.DelegateLaunchAnimatorController;
import com.android.systemui.assist.AssistManager;
-import com.android.systemui.battery.BatteryMeterViewController;
import com.android.systemui.biometrics.AuthRippleController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.camera.CameraIntents;
@@ -199,6 +198,7 @@
import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
@@ -216,6 +216,9 @@
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger;
+import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -487,6 +490,7 @@
private final DozeParameters mDozeParameters;
private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
private final StatusBarComponent.Factory mStatusBarComponentFactory;
+ private final StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory;
private final PluginManager mPluginManager;
private final Optional<LegacySplitScreen> mSplitScreenOptional;
private final StatusBarNotificationActivityStarter.Builder
@@ -668,10 +672,10 @@
private final Optional<Bubbles> mBubblesOptional;
private final Bubbles.BubbleExpandListener mBubbleExpandListener;
private final Optional<StartingSurface> mStartingSurfaceOptional;
+ private final NotifPipelineFlags mNotifPipelineFlags;
private final ActivityIntentHelper mActivityIntentHelper;
private NotificationStackScrollLayoutController mStackScrollerController;
- private BatteryMeterViewController mBatteryMeterViewController;
private final ColorExtractor.OnColorsChangedListener mOnColorsChangedListener =
(extractor, which) -> updateTheme();
@@ -743,6 +747,7 @@
CommandQueue commandQueue,
CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger,
StatusBarComponent.Factory statusBarComponentFactory,
+ StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory,
PluginManager pluginManager,
Optional<LegacySplitScreen> splitScreenOptional,
LightsOutNotifController lightsOutNotifController,
@@ -783,7 +788,8 @@
Optional<StartingSurface> startingSurfaceOptional,
TunerService tunerService,
DumpManager dumpManager,
- ActivityLaunchAnimator activityLaunchAnimator) {
+ ActivityLaunchAnimator activityLaunchAnimator,
+ NotifPipelineFlags notifPipelineFlags) {
super(context);
mNotificationsController = notificationsController;
mLightBarController = lightBarController;
@@ -847,6 +853,7 @@
mCommandQueue = commandQueue;
mCollapsedStatusBarFragmentLogger = collapsedStatusBarFragmentLogger;
mStatusBarComponentFactory = statusBarComponentFactory;
+ mStatusBarFragmentComponentFactory = statusBarFragmentComponentFactory;
mPluginManager = pluginManager;
mSplitScreenOptional = splitScreenOptional;
mStatusBarNotificationActivityStarterBuilder = statusBarNotificationActivityStarterBuilder;
@@ -880,6 +887,7 @@
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
mStartingSurfaceOptional = startingSurfaceOptional;
+ mNotifPipelineFlags = notifPipelineFlags;
lockscreenShadeTransitionController.setStatusbar(this);
mPanelExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged);
@@ -1131,28 +1139,21 @@
mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class);
mStatusBarWindowController.getFragmentHostManager()
.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
- CollapsedStatusBarFragment statusBarFragment =
- (CollapsedStatusBarFragment) fragment;
+ StatusBarFragmentComponent statusBarFragmentComponent =
+ ((CollapsedStatusBarFragment) fragment).getStatusBarFragmentComponent();
+ if (statusBarFragmentComponent == null) {
+ throw new IllegalStateException(
+ "CollapsedStatusBarFragment should have a valid component");
+ }
- PhoneStatusBarView oldStatusBarView = mStatusBarView;
- mStatusBarView = (PhoneStatusBarView) statusBarFragment.getView();
+ mStatusBarView = statusBarFragmentComponent.getPhoneStatusBarView();
+ // TODO(b/205609837): Migrate this to StatusBarFragmentComponent.
mPhoneStatusBarViewController = mPhoneStatusBarViewControllerFactory
.create(mStatusBarView, mNotificationPanelViewController
.getStatusBarTouchEventHandler());
mPhoneStatusBarViewController.init();
- mBatteryMeterViewController = new BatteryMeterViewController(
- mStatusBarView.findViewById(R.id.battery),
- mConfigurationController,
- mTunerService,
- mBroadcastDispatcher,
- mMainHandler,
- mContext.getContentResolver(),
- mBatteryController
- );
- mBatteryMeterViewController.init();
-
// Ensure we re-propagate panel expansion values to the panel controller and
// any listeners it may have, such as PanelBar. This will also ensure we
// re-display the notification panel if necessary (for example, if
@@ -1166,8 +1167,8 @@
// This view is being recreated, let's destroy the old one
mHeadsUpAppearanceController.destroy();
}
- // TODO: this should probably be scoped to the StatusBarComponent
// TODO (b/136993073) Separate notification shade and status bar
+ // TODO(b/205609837): Migrate this to StatusBarFragmentComponent.
mHeadsUpAppearanceController = new HeadsUpAppearanceController(
mNotificationIconAreaController, mHeadsUpManager,
mStackScrollerController,
@@ -1184,6 +1185,7 @@
.beginTransaction()
.replace(R.id.status_bar_container,
new CollapsedStatusBarFragment(
+ mStatusBarFragmentComponentFactory,
mOngoingCallController,
mAnimationScheduler,
mStatusBarLocationPublisher,
@@ -1475,7 +1477,8 @@
mInitController,
mNotificationInterruptStateProvider,
mRemoteInputManager,
- mConfigurationController);
+ mConfigurationController,
+ mNotifPipelineFlags);
mNotificationShelfController.setOnActivatedListener(mPresenter);
mRemoteInputManager.addControllerCallback(mNotificationShadeWindowController);
@@ -3280,6 +3283,10 @@
}
return true;
}
+ if (mNotificationPanelViewController.isQsCustomizing()) {
+ mNotificationPanelViewController.closeQsCustomizer();
+ return true;
+ }
if (mNotificationPanelViewController.isQsExpanded()) {
if (mNotificationPanelViewController.isQsDetailShowing()) {
mNotificationPanelViewController.closeQsDetail();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 7c0f923..58a018c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -57,6 +57,7 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.AboveShelfObserver;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
@@ -108,6 +109,7 @@
private final AccessibilityManager mAccessibilityManager;
private final KeyguardManager mKeyguardManager;
private final NotificationShadeWindowController mNotificationShadeWindowController;
+ private final NotifPipelineFlags mNotifPipelineFlags;
private final IStatusBarService mBarService;
private final DynamicPrivacyController mDynamicPrivacyController;
private boolean mReinflateNotificationsOnUserSwitched;
@@ -144,7 +146,8 @@
InitController initController,
NotificationInterruptStateProvider notificationInterruptStateProvider,
NotificationRemoteInputManager remoteInputManager,
- ConfigurationController configurationController) {
+ ConfigurationController configurationController,
+ NotifPipelineFlags notifPipelineFlags) {
mKeyguardStateController = keyguardStateController;
mNotificationPanel = panel;
mHeadsUpManager = headsUp;
@@ -167,6 +170,7 @@
mLockscreenGestureLogger = lockscreenGestureLogger;
mAboveShelfObserver = new AboveShelfObserver(stackScrollerController.getView());
mNotificationShadeWindowController = notificationShadeWindowController;
+ mNotifPipelineFlags = notifPipelineFlags;
mAboveShelfObserver.setListener(statusBarWindow.findViewById(
R.id.notification_container_parent));
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
@@ -305,7 +309,7 @@
@Override
public void updateNotificationViews(final String reason) {
- if (!mFeatureFlags.checkLegacyPipelineEnabled()) {
+ if (!mNotifPipelineFlags.checkLegacyPipelineEnabled()) {
return;
}
// The function updateRowStates depends on both of these being non-null, so check them here.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 3259f6b..1c3229f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -64,6 +64,7 @@
import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
@@ -75,7 +76,6 @@
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
-import com.android.systemui.statusbar.phone.CollapsedStatusBarFragmentLogger;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.DozeScrimController;
import com.android.systemui.statusbar.phone.DozeServiceHost;
@@ -99,6 +99,8 @@
import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger;
+import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -197,6 +199,7 @@
CommandQueue commandQueue,
CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger,
StatusBarComponent.Factory statusBarComponentFactory,
+ StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory,
PluginManager pluginManager,
Optional<LegacySplitScreen> splitScreenOptional,
LightsOutNotifController lightsOutNotifController,
@@ -237,7 +240,8 @@
Optional<StartingSurface> startingSurfaceOptional,
TunerService tunerService,
DumpManager dumpManager,
- ActivityLaunchAnimator activityLaunchAnimator) {
+ ActivityLaunchAnimator activityLaunchAnimator,
+ NotifPipelineFlags notifPipelineFlags) {
return new StatusBar(
context,
notificationsController,
@@ -297,6 +301,7 @@
commandQueue,
collapsedStatusBarFragmentLogger,
statusBarComponentFactory,
+ statusBarFragmentComponentFactory,
pluginManager,
splitScreenOptional,
lightsOutNotifController,
@@ -336,7 +341,8 @@
startingSurfaceOptional,
tunerService,
dumpManager,
- activityLaunchAnimator
+ activityLaunchAnimator,
+ notifPipelineFlags
);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index 2b62e0b..2880e4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -12,7 +12,7 @@
* permissions and limitations under the License.
*/
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.statusbar.phone.fragment;
import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS;
import static android.app.StatusBarManager.DISABLE_CLOCK;
@@ -52,7 +52,14 @@
import com.android.systemui.statusbar.connectivity.SignalCallback;
import com.android.systemui.statusbar.events.SystemStatusAnimationCallback;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
+import com.android.systemui.statusbar.phone.NotificationIconAreaController;
+import com.android.systemui.statusbar.phone.PhoneStatusBarView;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
+import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
+import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallListener;
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
@@ -83,6 +90,7 @@
public static final String STATUS_BAR_ICON_MANAGER_TAG = "status_bar_icon_manager";
public static final int FADE_IN_DURATION = 320;
public static final int FADE_IN_DELAY = 50;
+ private StatusBarFragmentComponent mStatusBarFragmentComponent;
private PhoneStatusBarView mStatusBar;
private final StatusBarStateController mStatusBarStateController;
private final KeyguardStateController mKeyguardStateController;
@@ -96,6 +104,7 @@
private int mDisabled2;
private Lazy<Optional<StatusBar>> mStatusBarOptionalLazy;
private DarkIconManager mDarkIconManager;
+ private final StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory;
private final CommandQueue mCommandQueue;
private final CollapsedStatusBarFragmentLogger mCollapsedStatusBarFragmentLogger;
private final OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
@@ -127,6 +136,7 @@
@Inject
public CollapsedStatusBarFragment(
+ StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory,
OngoingCallController ongoingCallController,
SystemStatusAnimationScheduler animationScheduler,
StatusBarLocationPublisher locationPublisher,
@@ -143,6 +153,7 @@
CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger,
OperatorNameViewController.Factory operatorNameViewControllerFactory
) {
+ mStatusBarFragmentComponentFactory = statusBarFragmentComponentFactory;
mOngoingCallController = ongoingCallController;
mAnimationScheduler = animationScheduler;
mLocationPublisher = locationPublisher;
@@ -169,6 +180,9 @@
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
+ mStatusBarFragmentComponent = mStatusBarFragmentComponentFactory.create(this);
+ mStatusBarFragmentComponent.init();
+
mStatusBar = (PhoneStatusBarView) view;
View contents = mStatusBar.findViewById(R.id.status_bar_contents);
contents.addOnLayoutChangeListener(mStatusBarLayoutListener);
@@ -252,6 +266,17 @@
updateNotificationIconAreaAndCallChip(mDisabled1, false);
}
+ /**
+ * Returns the dagger component for this fragment.
+ *
+ * TODO(b/205609837): Eventually, the dagger component should encapsulate all status bar
+ * fragment functionality and we won't need to expose it here anymore.
+ */
+ @Nullable
+ public StatusBarFragmentComponent getStatusBarFragmentComponent() {
+ return mStatusBarFragmentComponent;
+ }
+
@Override
public void disable(int displayId, int state1, int state2, boolean animate) {
if (displayId != getContext().getDisplayId()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLogger.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt
index 4d472e4..9ae378f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.phone
+package com.android.systemui.statusbar.phone.fragment
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
new file mode 100644
index 0000000..47c1875
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone.fragment.dagger;
+
+import com.android.systemui.battery.BatteryMeterViewController;
+import com.android.systemui.dagger.qualifiers.RootView;
+import com.android.systemui.statusbar.phone.PhoneStatusBarView;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
+
+import dagger.BindsInstance;
+import dagger.Subcomponent;
+
+/**
+ * A subcomponent that gets re-created each time we create a new {@link CollapsedStatusBarFragment}.
+ *
+ * This component will also re-create all classes that depend on {@link CollapsedStatusBarFragment}
+ * and friends. Specifically, the fragment creates a new {@link PhoneStatusBarView} and multiple
+ * controllers need access to that view, so those controllers will be re-created whenever the
+ * fragment is recreated.
+ *
+ * Note that this is completely separate from
+ * {@link com.android.systemui.statusbar.phone.dagger.StatusBarComponent}. This component gets
+ * re-created on each new fragment creation, whereas
+ * {@link com.android.systemui.statusbar.phone.dagger.StatusBarComponent} is only created once in
+ * {@link com.android.systemui.statusbar.phone.StatusBar} and never re-created.
+ */
+
+@Subcomponent(modules = {StatusBarFragmentModule.class})
+@StatusBarFragmentScope
+public interface StatusBarFragmentComponent {
+ /** Simple factory. */
+ @Subcomponent.Factory
+ interface Factory {
+ StatusBarFragmentComponent create(
+ @BindsInstance CollapsedStatusBarFragment collapsedStatusBarFragment);
+ }
+
+ /**
+ * Initialize anything extra for the component. Must be called after the component is created.
+ */
+ default void init() {
+ // No one accesses this controller, so we need to make sure we reference it here so it does
+ // get initialized.
+ getBatteryMeterViewController().init();
+ }
+
+ /** */
+ @StatusBarFragmentScope
+ BatteryMeterViewController getBatteryMeterViewController();
+
+ /** */
+ @StatusBarFragmentScope
+ @RootView
+ PhoneStatusBarView getPhoneStatusBarView();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
new file mode 100644
index 0000000..969361b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone.fragment.dagger;
+
+import com.android.systemui.R;
+import com.android.systemui.battery.BatteryMeterView;
+import com.android.systemui.dagger.qualifiers.RootView;
+import com.android.systemui.statusbar.phone.PhoneStatusBarView;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
+
+import dagger.Module;
+import dagger.Provides;
+
+/** Dagger module for {@link StatusBarFragmentComponent}. */
+@Module
+public interface StatusBarFragmentModule {
+ /** */
+ @Provides
+ @RootView
+ @StatusBarFragmentScope
+ static PhoneStatusBarView providePhoneStatusBarView(
+ CollapsedStatusBarFragment collapsedStatusBarFragment) {
+ return (PhoneStatusBarView) collapsedStatusBarFragment.getView();
+ }
+
+ /** */
+ @Provides
+ @StatusBarFragmentScope
+ static BatteryMeterView provideBatteryMeterView(@RootView PhoneStatusBarView view) {
+ return view.findViewById(R.id.battery);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentScope.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentScope.java
new file mode 100644
index 0000000..96cff59
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentScope.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone.fragment.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Scope;
+
+/**
+ * Scope annotation for singleton items within the {@link StatusBarFragmentComponent}.
+ */
+@Documented
+@Retention(RUNTIME)
+@Scope
+public @interface StatusBarFragmentScope {}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 6d176a7..50a0b80 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -176,6 +176,34 @@
? WallpaperManager.FLAG_LOCK : WallpaperManager.FLAG_SYSTEM;
}
+ private boolean isSeedColorSet(JSONObject jsonObject, WallpaperColors newWallpaperColors) {
+ if (newWallpaperColors == null) {
+ return false;
+ }
+ // Gets the color that was overridden in the theme setting if any.
+ String sysPaletteColor = (String) jsonObject.opt(OVERLAY_CATEGORY_SYSTEM_PALETTE);
+ if (sysPaletteColor == null) {
+ return false;
+ }
+ if (!sysPaletteColor.startsWith("#")) {
+ sysPaletteColor = "#" + sysPaletteColor;
+ }
+ final int systemPaletteColorArgb = Color.parseColor(sysPaletteColor);
+ // Gets seed colors from incoming {@link WallpaperColors} instance.
+ List<Integer> seedColors = ColorScheme.getSeedColors(newWallpaperColors);
+ for (int seedColor : seedColors) {
+ // The seed color from incoming {@link WallpaperColors} instance
+ // was set as color override.
+ if (seedColor == systemPaletteColorArgb) {
+ if (DEBUG) {
+ Log.d(TAG, "Same as previous set system palette: " + sysPaletteColor);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
private void handleWallpaperColors(WallpaperColors wallpaperColors, int flags) {
final boolean hadWallpaperColors = mCurrentColors != null;
int latestWallpaperType = getLatestWallpaperType();
@@ -213,8 +241,11 @@
try {
JSONObject jsonObject = (overlayPackageJson == null) ? new JSONObject()
: new JSONObject(overlayPackageJson);
+ // The latest applied wallpaper should be the source of system colors when:
+ // There is not preset color applied and the incoming wallpaper color is not applied
if (!COLOR_SOURCE_PRESET.equals(jsonObject.optString(OVERLAY_COLOR_SOURCE))
- && ((flags & latestWallpaperType) != 0)) {
+ && ((flags & latestWallpaperType) != 0 && !isSeedColorSet(jsonObject,
+ wallpaperColors))) {
mSkipSettingChange = true;
if (jsonObject.has(OVERLAY_CATEGORY_ACCENT_COLOR) || jsonObject.has(
OVERLAY_CATEGORY_SYSTEM_PALETTE)) {
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
index cebc931..cd3e2d3 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
@@ -100,11 +100,11 @@
fun provideShellProgressProvider(
config: UnfoldTransitionConfig,
provider: Optional<UnfoldTransitionProgressProvider>
- ): Optional<ShellUnfoldProgressProvider> =
+ ): ShellUnfoldProgressProvider =
if (config.isEnabled && provider.isPresent()) {
- Optional.of(UnfoldProgressProvider(provider.get()))
+ UnfoldProgressProvider(provider.get())
} else {
- Optional.empty()
+ ShellUnfoldProgressProvider.NO_PROVIDER
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
index db87c5d..4bdab76 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
@@ -75,8 +75,7 @@
shouldListenForFingerprintAssistant = false,
switchingUser = false,
udfps = false,
- userDoesNotHaveTrust = false,
- userNeedsStrongAuth = false
+ userDoesNotHaveTrust = false
)
private fun faceModel(user: Int) = KeyguardFaceListenModel(
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index ff5960b..de8cc89 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -19,6 +19,7 @@
import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE;
import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
import static com.google.common.truth.Truth.assertThat;
@@ -961,6 +962,19 @@
}
@Test
+ public void testStartUdfpsServiceStrongAuthRequiredAfterTimeout() {
+ // GIVEN status bar state is on the keyguard
+ mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
+
+ // WHEN user loses smart unlock trust
+ when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
+ .thenReturn(SOME_AUTH_REQUIRED_AFTER_USER_REQUEST);
+
+ // THEN we should still listen for udfps
+ assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(true);
+ }
+
+ @Test
public void testShouldNotListenForUdfps_whenTrustEnabled() {
// GIVEN a "we should listen for udfps" state
mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index d90eb73..9e42ff3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -642,12 +642,12 @@
mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent);
moveEvent.recycle();
- // THEN click haptic is played
+ // THEN low-tick haptic is played
verify(mVibrator).vibrate(
anyInt(),
anyString(),
- eq(mUdfpsController.EFFECT_CLICK),
- eq("udfps-onStart"),
+ any(),
+ eq("udfps-onStart-tick"),
eq(UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES));
// THEN make sure vibration attributes has so that it always will play the haptic,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
index 886f84e..5b472ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -51,6 +51,7 @@
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.concurrency.FakeThreadFactory;
@@ -93,6 +94,8 @@
DevicePostureController mDevicePostureController;
@Mock
DozeLog mDozeLog;
+ @Mock
+ private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
private FakeThreadFactory mFakeThreadFactory = new FakeThreadFactory(mFakeExecutor);
@@ -130,7 +133,8 @@
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
- mDozeLog);
+ mDozeLog,
+ mUnlockedScreenOffAnimationController);
}
@Test
@@ -236,7 +240,8 @@
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
- mDozeLog);
+ mDozeLog,
+ mUnlockedScreenOffAnimationController);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
reset(mDozeHost);
@@ -273,7 +278,8 @@
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
- mDozeLog);
+ mDozeLog,
+ mUnlockedScreenOffAnimationController);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
@@ -304,7 +310,8 @@
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
- mDozeLog);
+ mDozeLog,
+ mUnlockedScreenOffAnimationController);
// GIVEN the device is in AOD
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
@@ -342,7 +349,8 @@
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
- mDozeLog);
+ mDozeLog,
+ mUnlockedScreenOffAnimationController);
// GIVEN device is in AOD
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
@@ -384,7 +392,8 @@
mWakefulnessLifecycle,
mDozeParameters,
mDevicePostureController,
- mDozeLog);
+ mDozeLog,
+ mUnlockedScreenOffAnimationController);
verify(mDevicePostureController).addCallback(postureCallbackCaptor.capture());
// GIVEN device is in AOD
@@ -466,24 +475,26 @@
}
@Test
- public void transitionToDoze_duringScreenOff_afterTimeout_clampsToDim() {
+ public void transitionToDoze_duringUnlockedScreenOff_afterTimeout_clampsToDim() {
when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true);
+ when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(true);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
// If we're dozing after a timeout, and playing the unlocked screen animation, we should
- // stay at dim brightness, because the screen dims just before timeout.
- assertEquals(mServiceFake.screenBrightness, DIM_BRIGHTNESS);
+ // stay at or below dim brightness, because the screen dims just before timeout.
+ assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS);
}
@Test
- public void transitionToDoze_duringScreenOff_notAfterTimeout_doesNotClampToDim() {
+ public void transitionToDoze_duringUnlockedScreenOff_notAfterTimeout_doesNotClampToDim() {
when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true);
+ when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(true);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
@@ -494,10 +505,11 @@
}
@Test
- public void transitionToDoze_duringScreenOff_afterTimeout_noScreenOff_doesNotClampToDim() {
+ public void transitionToDoze_duringUnlockedScreenOff_afterTimeout_noScreenOff_doesNotClampToDim() {
when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false);
+ when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(false);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
@@ -506,6 +518,36 @@
assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
}
+ @Test
+ public void transitionToDoze_duringLockedScreenOff_afterTimeout_clampsToDim() {
+ when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
+ PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+ when(mWakefulnessLifecycle.getWakefulness()).thenReturn(
+ WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP);
+ when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false);
+ when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(false);
+
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+
+ assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS);
+ }
+
+ @Test
+ public void transitionToDoze_duringLockedScreenOff_notAfterTimeout_doesNotClampToDim() {
+ when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
+ PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
+ when(mWakefulnessLifecycle.getWakefulness()).thenReturn(
+ WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP);
+ when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false);
+ when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(false);
+
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+
+ assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
+ }
+
private void waitForSensorManager() {
mFakeExecutor.runAllReady();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
index 150ab77..3e19cc4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
@@ -82,6 +82,8 @@
private UdfpsController mUdfpsController;
@Mock
private DozeLog mDozeLog;
+ @Mock
+ private DozeScreenBrightness mDozeScreenBrightness;
@Before
public void setUp() throws Exception {
@@ -96,7 +98,8 @@
mHandlerFake = new FakeHandler(Looper.getMainLooper());
mWakeLock = new WakeLockFake();
mScreen = new DozeScreenState(mServiceFake, mHandlerFake, mDozeHost, mDozeParameters,
- mWakeLock, mAuthController, mUdfpsControllerProvider, mDozeLog);
+ mWakeLock, mAuthController, mUdfpsControllerProvider, mDozeLog,
+ mDozeScreenBrightness);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index aba043b..ce36935 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -151,7 +151,7 @@
mSecureSettings, mCustomTileStatePersister, mTileServiceRequestControllerBuilder,
mFeatureFlags);
setUpTileFactory();
- when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(false);
+ when(mFeatureFlags.isProviderModelSettingEnabled(mContext)).thenReturn(false);
}
private void setUpTileFactory() {
@@ -200,7 +200,7 @@
@Test
public void testRemoveWifiAndCellularWithoutInternet() {
- when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ when(mFeatureFlags.isProviderModelSettingEnabled(mContext)).thenReturn(true);
mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "wifi, spec1, cell, spec2");
assertEquals("internet", mQSTileHost.mTileSpecs.get(0));
@@ -210,7 +210,7 @@
@Test
public void testRemoveWifiAndCellularWithInternet() {
- when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ when(mFeatureFlags.isProviderModelSettingEnabled(mContext)).thenReturn(true);
mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "wifi, spec1, cell, spec2, internet");
assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
@@ -220,7 +220,7 @@
@Test
public void testRemoveWifiWithoutInternet() {
- when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ when(mFeatureFlags.isProviderModelSettingEnabled(mContext)).thenReturn(true);
mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1, wifi, spec2");
assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
@@ -230,7 +230,7 @@
@Test
public void testRemoveCellWithInternet() {
- when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ when(mFeatureFlags.isProviderModelSettingEnabled(mContext)).thenReturn(true);
mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1, spec2, cell, internet");
assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
@@ -240,7 +240,7 @@
@Test
public void testNoWifiNoCellularNoInternet() {
- when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ when(mFeatureFlags.isProviderModelSettingEnabled(mContext)).thenReturn(true);
mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1,spec2");
assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index 018806e..05db1eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -136,7 +136,7 @@
}
}
).when(mQSTileHost).createTile(anyString());
- when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(false);
+ when(mFeatureFlags.isProviderModelSettingEnabled(mContext)).thenReturn(false);
FakeSystemClock clock = new FakeSystemClock();
mMainExecutor = new FakeExecutor(clock);
mBgExecutor = new FakeExecutor(clock);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
new file mode 100644
index 0000000..f99703e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles
+
+import android.content.ContextWrapper
+import android.content.SharedPreferences
+import android.os.Handler
+import android.provider.Settings
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.logging.UiEventLogger
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.FalsingManagerFake
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.qs.QSHost
+import com.android.systemui.qs.logging.QSLogger
+import com.android.systemui.statusbar.policy.ZenModeController
+import com.android.systemui.util.settings.FakeSettings
+import com.android.systemui.util.settings.SecureSettings
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.MockitoAnnotations
+import java.io.File
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class DndTileTest : SysuiTestCase() {
+
+ companion object {
+ private const val DEFAULT_USER = 0
+ private const val KEY = Settings.Secure.ZEN_DURATION
+ }
+
+ @Mock
+ private lateinit var qsHost: QSHost
+ @Mock
+ private lateinit var metricsLogger: MetricsLogger
+ @Mock
+ private lateinit var statusBarStateController: StatusBarStateController
+ @Mock
+ private lateinit var activityStarter: ActivityStarter
+ @Mock
+ private lateinit var qsLogger: QSLogger
+ @Mock
+ private lateinit var uiEventLogger: UiEventLogger
+ @Mock
+ private lateinit var zenModeController: ZenModeController
+ @Mock
+ private lateinit var sharedPreferences: SharedPreferences
+
+ private lateinit var secureSettings: SecureSettings
+ private lateinit var testableLooper: TestableLooper
+ private lateinit var tile: DndTile
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ testableLooper = TestableLooper.get(this)
+ secureSettings = FakeSettings()
+
+ Mockito.`when`(qsHost.userId).thenReturn(DEFAULT_USER)
+ Mockito.`when`(qsHost.uiEventLogger).thenReturn(uiEventLogger)
+
+ val wrappedContext = object : ContextWrapper(context) {
+ override fun getSharedPreferences(file: File?, mode: Int): SharedPreferences {
+ return sharedPreferences
+ }
+ }
+ Mockito.`when`(qsHost.context).thenReturn(wrappedContext)
+
+ tile = DndTile(
+ qsHost,
+ testableLooper.looper,
+ Handler(testableLooper.looper),
+ FalsingManagerFake(),
+ metricsLogger,
+ statusBarStateController,
+ activityStarter,
+ qsLogger,
+ zenModeController,
+ sharedPreferences,
+ secureSettings
+ )
+ }
+
+ @After
+ fun tearDown() {
+ tile.handleSetListening(false)
+ }
+
+ @Test
+ fun testForceExpandIcon_durationAskAlways_true() {
+ secureSettings.putIntForUser(KEY, Settings.Secure.ZEN_DURATION_PROMPT, DEFAULT_USER)
+
+ tile.refreshState()
+ testableLooper.processAllMessages()
+
+ assertThat(tile.state.forceExpandIcon).isTrue()
+ }
+
+ @Test
+ fun testForceExpandIcon_durationNotAskAlways_false() {
+ secureSettings.putIntForUser(KEY, 60, DEFAULT_USER)
+
+ tile.refreshState()
+ testableLooper.processAllMessages()
+
+ assertThat(tile.state.forceExpandIcon).isFalse()
+ }
+
+ @Test
+ fun testForceExpandIcon_changeWhileListening() {
+ secureSettings.putIntForUser(KEY, 60, DEFAULT_USER)
+
+ tile.refreshState()
+ testableLooper.processAllMessages()
+
+ assertThat(tile.state.forceExpandIcon).isFalse()
+
+ tile.handleSetListening(true)
+
+ secureSettings.putIntForUser(KEY, Settings.Secure.ZEN_DURATION_PROMPT, DEFAULT_USER)
+ testableLooper.processAllMessages()
+
+ assertThat(tile.state.forceExpandIcon).isTrue()
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
index b6e8979..b32b4d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
@@ -219,61 +219,89 @@
}
@Test
- public void updateDialog_wifiOnAndNoWifiList_hideWifiListAndSeeAll() {
+ public void updateDialog_wifiOnAndNoWifiEntry_hideWifiEntryAndSeeAll() {
// The precondition WiFi ON is already in setUp()
+ mInternetDialog.mConnectedWifiEntry = null;
mInternetDialog.mWifiEntriesCount = 0;
mInternetDialog.updateDialog(false);
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
}
@Test
- public void updateDialog_wifiOnAndHasWifiList_showWifiListAndSeeAll() {
+ public void updateDialog_wifiOnAndHasConnectedWifi_showConnectedWifiAndSeeAll() {
// The preconditions WiFi ON and WiFi entries are already in setUp()
+ mInternetDialog.mWifiEntriesCount = 0;
mInternetDialog.updateDialog(false);
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void updateDialog_wifiOnAndHasWifiList_showWifiListAndSeeAll() {
+ // The preconditions WiFi ON and WiFi entries are already in setUp()
+ mInternetDialog.mConnectedWifiEntry = null;
+
+ mInternetDialog.updateDialog(false);
+
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
- public void updateDialog_deviceLockedAndHasInternetWifi_showHighlightWifiToggle() {
- // The preconditions WiFi ON and Internet WiFi are already in setUp()
- when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+ public void updateDialog_wifiOnAndHasBothWifiEntry_showBothWifiEntryAndSeeAll() {
+ // The preconditions WiFi ON and WiFi entries are already in setUp()
mInternetDialog.updateDialog(false);
- assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mWifiToggle.getBackground()).isNotNull();
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
- public void updateDialog_deviceLockedAndHasInternetWifi_hideConnectedWifi() {
- // The preconditions WiFi ON and Internet WiFi are already in setUp()
- when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
-
- mInternetDialog.updateDialog(false);
-
- assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
- }
-
- @Test
- public void updateDialog_deviceLockedAndHasWifiList_hideWifiListAndSeeAll() {
+ public void updateDialog_deviceLockedAndNoConnectedWifi_showWifiToggle() {
// The preconditions WiFi entries are already in setUp()
when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+ mInternetDialog.mConnectedWifiEntry = null;
mInternetDialog.updateDialog(false);
+ // Show WiFi Toggle without background
+ assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mWifiToggle.getBackground()).isNull();
+ // Hide Wi-Fi networks and See all
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void updateDialog_deviceLockedAndHasConnectedWifi_showWifiToggleWithBackground() {
+ // The preconditions WiFi ON and WiFi entries are already in setUp()
+ when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+
+ mInternetDialog.updateDialog(false);
+
+ // Show WiFi Toggle with highlight background
+ assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mWifiToggle.getBackground()).isNotNull();
+ // Hide Wi-Fi networks and See all
+ assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
}
@Test
public void updateDialog_wifiOn_hideWifiScanNotify() {
- // The preconditions WiFi ON and Internet WiFi are already in setUp()
+ // The preconditions WiFi ON and WiFi entries are already in setUp()
mInternetDialog.updateDialog(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 9a23eb6..7210d9c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -41,6 +41,7 @@
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
import com.android.systemui.statusbar.notification.DynamicChildBindController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -77,6 +78,7 @@
// Dependency mocks:
@Mock private FeatureFlags mFeatureFlags;
+ @Mock private NotifPipelineFlags mNotifPipelineFlags;
@Mock private NotificationEntryManager mEntryManager;
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock private NotificationGroupManagerLegacy mGroupManager;
@@ -103,7 +105,8 @@
when(mVisualStabilityManager.areGroupChangesAllowed()).thenReturn(true);
when(mVisualStabilityManager.isReorderingAllowed()).thenReturn(true);
- when(mFeatureFlags.checkLegacyPipelineEnabled()).thenReturn(true);
+ when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
+ when(mNotifPipelineFlags.checkLegacyPipelineEnabled()).thenReturn(true);
mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this));
@@ -117,7 +120,8 @@
mock(ForegroundServiceSectionController.class),
mock(DynamicChildBindController.class),
mock(LowPriorityInflationHelper.class),
- mock(AssistantFeedbackController.class));
+ mock(AssistantFeedbackController.class),
+ mNotifPipelineFlags);
mViewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
index 47a11fc..344d6f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
@@ -158,11 +158,9 @@
public void setUp() throws Exception {
mMockingSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
.mockStatic(FeatureFlags.class).startMocking();
- ExtendedMockito.doReturn(true).when(() ->
- FeatureFlags.isProviderModelSettingEnabled(mContext));
mFeatureFlags = mock(FeatureFlags.class);
when(mFeatureFlags.isCombinedStatusBarSignalIconsEnabled()).thenReturn(false);
- when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+ when(mFeatureFlags.isProviderModelSettingEnabled(mContext)).thenReturn(true);
mInstrumentation = InstrumentationRegistry.getInstrumentation();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
index a53fb78..4521610 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -62,6 +62,7 @@
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.notification.ConversationNotificationProcessor;
import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationClicker;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -143,6 +144,7 @@
@Mock private NotificationGroupManagerLegacy mGroupMembershipManager;
@Mock private NotificationGroupManagerLegacy mGroupExpansionManager;
@Mock private FeatureFlags mFeatureFlags;
+ @Mock private NotifPipelineFlags mNotifPipelineFlags;
@Mock private LeakDetector mLeakDetector;
@Mock private ActivatableNotificationViewController mActivatableNotificationViewController;
@@ -179,6 +181,7 @@
.setNotification(notification)
.build();
+ when(mNotifPipelineFlags.checkLegacyPipelineEnabled()).thenReturn(true);
when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
mEntryManager = new NotificationEntryManager(
@@ -282,7 +285,6 @@
mRowBinder = new NotificationRowBinderImpl(
mContext,
- mFeatureFlags,
new NotificationMessagingUtil(mContext),
mRemoteInputManager,
mLockscreenUserManager,
@@ -294,7 +296,8 @@
mEntryManager,
mock(LauncherApps.class),
new IconBuilder(mContext)),
- mock(LowPriorityInflationHelper.class));
+ mock(LowPriorityInflationHelper.class),
+ mNotifPipelineFlags);
mEntryManager.setUpWithPresenter(mPresenter);
mEntryManager.addNotificationEntryListener(mEntryListener);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
index 58e3cc8..276f246 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
@@ -52,6 +52,7 @@
import com.android.systemui.media.KeyguardMediaController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
@@ -80,11 +81,8 @@
@Rule public final MockitoRule mockitoRule = MockitoJUnit.rule();
@Mock private NotificationStackScrollLayout mNssl;
- @Mock private FeatureFlags mFeatureFlags;
- @Mock private ActivityStarterDelegate mActivityStarterDelegate;
@Mock private StatusBarStateController mStatusBarStateController;
@Mock private ConfigurationController mConfigurationController;
- @Mock private PeopleHubViewAdapter mPeopleHubAdapter;
@Mock private KeyguardMediaController mKeyguardMediaController;
@Mock private NotificationSectionsFeatureManager mSectionsFeatureManager;
@Mock private NotificationRowComponent mNotificationRowComponent;
@@ -94,6 +92,7 @@
@Mock private SectionHeaderController mPeopleHeaderController;
@Mock private SectionHeaderController mAlertingHeaderController;
@Mock private SectionHeaderController mSilentHeaderController;
+ @Mock private NotifPipelineFlags mNotifPipelineFlags;
private NotificationSectionsManager mSectionsManager;
@@ -122,12 +121,12 @@
when(mSilentHeaderController.getHeaderView()).thenReturn(mock(SectionHeaderView.class));
mSectionsManager =
new NotificationSectionsManager(
- mFeatureFlags,
mStatusBarStateController,
mConfigurationController,
mKeyguardMediaController,
mSectionsFeatureManager,
mLogger,
+ mNotifPipelineFlags,
mIncomingHeaderController,
mPeopleHeaderController,
mAlertingHeaderController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index 4e6b0a2..ffef55b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -49,6 +49,7 @@
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -128,7 +129,8 @@
mInitController,
mNotificationInterruptStateProvider,
mock(NotificationRemoteInputManager.class),
- mock(ConfigurationController.class));
+ mock(ConfigurationController.class),
+ mock(NotifPipelineFlags.class));
mInitController.executePostInitTasks();
ArgumentCaptor<NotificationInterruptSuppressor> suppressorCaptor =
ArgumentCaptor.forClass(NotificationInterruptSuppressor.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 371b91f..6cc6490 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -114,6 +114,7 @@
import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
@@ -133,6 +134,8 @@
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger;
+import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -243,6 +246,8 @@
@Mock private CollapsedStatusBarFragmentLogger mCollapsedStatusBarFragmentLogger;
@Mock private StatusBarComponent.Factory mStatusBarComponentFactory;
@Mock private StatusBarComponent mStatusBarComponent;
+ @Mock private StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory;
+ @Mock private StatusBarFragmentComponent mStatusBarFragmentComponent;
@Mock private PluginManager mPluginManager;
@Mock private LegacySplitScreen mLegacySplitScreen;
@Mock private LightsOutNotifController mLightsOutNotifController;
@@ -277,6 +282,7 @@
@Mock private OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
@Mock private PhoneStatusBarViewController.Factory mPhoneStatusBarViewControllerFactory;
@Mock private ActivityLaunchAnimator mActivityLaunchAnimator;
+ @Mock private NotifPipelineFlags mNotifPipelineFlags;
private ShadeController mShadeController;
private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
private FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
@@ -356,6 +362,8 @@
when(mBiometricUnlockControllerLazy.get()).thenReturn(mBiometricUnlockController);
when(mStatusBarComponentFactory.create()).thenReturn(mStatusBarComponent);
+ when(mStatusBarFragmentComponentFactory.create(any()))
+ .thenReturn(mStatusBarFragmentComponent);
when(mStatusBarComponent.getNotificationShadeWindowViewController()).thenReturn(
mNotificationShadeWindowViewController);
@@ -425,6 +433,7 @@
mCommandQueue,
mCollapsedStatusBarFragmentLogger,
mStatusBarComponentFactory,
+ mStatusBarFragmentComponentFactory,
mPluginManager,
Optional.of(mLegacySplitScreen),
mLightsOutNotifController,
@@ -464,7 +473,8 @@
Optional.of(mStartingSurface),
mTunerService,
mDumpManager,
- mActivityLaunchAnimator);
+ mActivityLaunchAnimator,
+ mNotifPipelineFlags);
when(mKeyguardViewMediator.registerStatusBar(
any(StatusBar.class),
any(NotificationPanelViewController.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
similarity index 97%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLoggerTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
index bf8cc37..1ee8875 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.phone
+package com.android.systemui.statusbar.phone.fragment
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
similarity index 89%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index 75a8624..0ee4e7a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -12,7 +12,7 @@
* permissions and limitations under the License.
*/
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.statusbar.phone.fragment;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -48,6 +48,13 @@
import com.android.systemui.statusbar.OperatorNameViewController;
import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
+import com.android.systemui.statusbar.phone.NotificationIconAreaController;
+import com.android.systemui.statusbar.phone.NotificationPanelViewController;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
+import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -72,7 +79,6 @@
private OngoingCallController mOngoingCallController;
private SystemStatusAnimationScheduler mAnimationScheduler;
private StatusBarLocationPublisher mLocationPublisher;
-
// Set in instantiate()
private StatusBarIconController mStatusBarIconController;
private NetworkController mNetworkController;
@@ -84,6 +90,8 @@
private OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
private OperatorNameViewController mOperatorNameViewController;
+ private StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory;
+ private StatusBarFragmentComponent mStatusBarFragmentComponent;
public CollapsedStatusBarFragmentTest() {
super(CollapsedStatusBarFragment.class);
@@ -245,8 +253,22 @@
Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.VISIBLE));
}
+ @Test
+ public void setUp_fragmentCreatesDaggerComponent() {
+ mFragments.dispatchResume();
+ processAllMessages();
+ CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+
+ assertEquals(mStatusBarFragmentComponent, fragment.getStatusBarFragmentComponent());
+ }
+
@Override
protected Fragment instantiate(Context context, String className, Bundle arguments) {
+ mStatusBarFragmentComponentFactory =
+ mock(StatusBarFragmentComponent.Factory.class);
+ mStatusBarFragmentComponent = mock(StatusBarFragmentComponent.class);
+ when(mStatusBarFragmentComponentFactory.create(any()))
+ .thenReturn(mStatusBarFragmentComponent);
mOngoingCallController = mock(OngoingCallController.class);
mAnimationScheduler = mock(SystemStatusAnimationScheduler.class);
mLocationPublisher = mock(StatusBarLocationPublisher.class);
@@ -261,6 +283,7 @@
setUpNotificationIconAreaController();
return new CollapsedStatusBarFragment(
+ mStatusBarFragmentComponentFactory,
mOngoingCallController,
mAnimationScheduler,
mLocationPublisher,
@@ -282,7 +305,6 @@
mOperatorNameViewControllerFactory);
}
-
private void setUpNotificationIconAreaController() {
mMockNotificationAreaController = mock(NotificationIconAreaController.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index 766471b..3ff5666 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -248,8 +248,9 @@
Color.valueOf(Color.BLUE), null);
String jsonString =
- "{\"android.theme.customization.system_palette\":\"override.package.name\","
- + "\"android.theme.customization.color_source\":\"home_wallpaper\","
+ "{\"android.theme.customization.color_source\":\"home_wallpaper\","
+ + "\"android.theme.customization.system_palette\":\"A16B00\","
+ + "\"android.theme.customization.accent_color\":\"A16B00\","
+ "\"android.theme.customization.color_index\":\"2\"}";
when(mSecureSettings.getStringForUser(
@@ -274,14 +275,15 @@
}
@Test
- public void onWallpaperColorsChanged_ResetThemeWithDifferentWallpapers() {
+ public void onWallpaperColorsChanged_ResetThemeWithNewHomeWallpapers() {
// Should ask for a new theme when wallpaper colors change
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
String jsonString =
- "{\"android.theme.customization.system_palette\":\"override.package.name\","
- + "\"android.theme.customization.color_source\":\"home_wallpaper\","
+ "{\"android.theme.customization.color_source\":\"home_wallpaper\","
+ + "\"android.theme.customization.system_palette\":\"A16B00\","
+ + "\"android.theme.customization.accent_color\":\"A16B00\","
+ "\"android.theme.customization.color_index\":\"2\"}";
when(mSecureSettings.getStringForUser(
@@ -304,14 +306,15 @@
}
@Test
- public void onWallpaperColorsChanged_ResetThemeWithSameWallpaper() {
+ public void onWallpaperColorsChanged_ResetThemeWithNewHomeAndLockWallpaper() {
// Should ask for a new theme when wallpaper colors change
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
String jsonString =
- "{\"android.theme.customization.system_palette\":\"override.package.name\","
- + "\"android.theme.customization.color_source\":\"home_wallpaper\","
+ "{\"android.theme.customization.color_source\":\"home_wallpaper\","
+ + "\"android.theme.customization.system_palette\":\"A16B00\","
+ + "\"android.theme.customization.accent_color\":\"A16B00\","
+ "\"android.theme.customization.color_index\":\"2\"}";
when(mSecureSettings.getStringForUser(
@@ -339,8 +342,9 @@
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
String jsonString =
- "{\"android.theme.customization.system_palette\":\"override.package.name\","
- + "\"android.theme.customization.color_source\":\"home_wallpaper\","
+ "{\"android.theme.customization.color_source\":\"home_wallpaper\","
+ + "\"android.theme.customization.system_palette\":\"A16B00\","
+ + "\"android.theme.customization.accent_color\":\"A16B00\","
+ "\"android.theme.customization.color_index\":\"2\"}";
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
@@ -366,8 +370,9 @@
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
Color.valueOf(Color.BLUE), null);
String jsonString =
- "{\"android.theme.customization.system_palette\":\"override.package.name\","
- + "\"android.theme.customization.color_source\":\"lock_wallpaper\","
+ "{\"android.theme.customization.color_source\":\"lock_wallpaper\","
+ + "\"android.theme.customization.system_palette\":\"A16B00\","
+ + "\"android.theme.customization.accent_color\":\"A16B00\","
+ "\"android.theme.customization.color_index\":\"2\"}";
when(mSecureSettings.getStringForUser(
eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
@@ -394,8 +399,9 @@
Color.valueOf(Color.BLUE), null);
String jsonString =
- "{\"android.theme.customization.system_palette\":\"override.package.name\","
- + "\"android.theme.customization.color_source\":\"home_wallpaper\","
+ "{\"android.theme.customization.color_source\":\"home_wallpaper\","
+ + "\"android.theme.customization.system_palette\":\"A16B00\","
+ + "\"android.theme.customization.accent_color\":\"A16B00\","
+ "\"android.theme.customization.color_index\":\"2\"}";
when(mSecureSettings.getStringForUser(
@@ -416,6 +422,36 @@
}
@Test
+ public void onWallpaperColorsChanged_keepThemeWhenFromLatestWallpaperAndSpecifiedColor() {
+ // Shouldn't ask for a new theme when the colors of the last applied wallpaper change
+ // with the same specified system palette one.
+ WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
+ Color.valueOf(0xffa16b00), null);
+
+ String jsonString =
+ "{\"android.theme.customization.color_source\":\"home_wallpaper\","
+ + "\"android.theme.customization.system_palette\":\"A16B00\","
+ + "\"android.theme.customization.accent_color\":\"A16B00\","
+ + "\"android.theme.customization.color_index\":\"2\"}";
+
+ when(mSecureSettings.getStringForUser(
+ eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
+ .thenReturn(jsonString);
+ when(mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_LOCK)).thenReturn(1);
+ // SYSTEM wallpaper is the last applied one
+ when(mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_SYSTEM)).thenReturn(2);
+
+ mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
+
+ ArgumentCaptor<String> updatedSetting = ArgumentCaptor.forClass(String.class);
+ verify(mSecureSettings, never()).putString(
+ eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), updatedSetting.capture());
+
+ // Apply overlay by existing theme from secure setting
+ verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any());
+ }
+
+ @Test
public void onWallpaperColorsChanged_keepThemeIfNotLatestWallpaper() {
// Shouldn't ask for a new theme when the colors of the wallpaper that is not the last
// applied one change
@@ -423,8 +459,9 @@
Color.valueOf(Color.BLUE), null);
String jsonString =
- "{\"android.theme.customization.system_palette\":\"override.package.name\","
- + "\"android.theme.customization.color_source\":\"home_wallpaper\","
+ "{\"android.theme.customization.color_source\":\"home_wallpaper\","
+ + "\"android.theme.customization.system_palette\":\"A16B00\","
+ + "\"android.theme.customization.accent_color\":\"A16B00\","
+ "\"android.theme.customization.color_index\":\"2\"}";
when(mSecureSettings.getStringForUser(
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 311555e..6f009b6 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3713,8 +3713,19 @@
}
@Override
- public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
- final int userId = UserHandle.getUserId(uid);
+ public StorageVolume[] getVolumeList(int userId, String callingPackage, int flags) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getUserId(callingUid);
+
+ if (!isUidOwnerOfPackageOrSystem(callingPackage, callingUid)) {
+ throw new SecurityException("callingPackage does not match UID");
+ }
+ if (callingUserId != userId) {
+ // Callers can ask for volumes of different users, but only with the correct permissions
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ "Need INTERACT_ACROSS_USERS to get volumes for another user");
+ }
final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
@@ -3730,7 +3741,7 @@
// should never attempt to augment the actual storage volume state,
// otherwise we risk confusing it with race conditions as users go
// through various unlocked states
- final boolean callerIsMediaStore = UserHandle.isSameApp(Binder.getCallingUid(),
+ final boolean callerIsMediaStore = UserHandle.isSameApp(callingUid,
mMediaStoreAuthorityAppId);
final boolean userIsDemo;
@@ -3740,8 +3751,9 @@
try {
userIsDemo = LocalServices.getService(UserManagerInternal.class)
.getUserInfo(userId).isDemo();
+ storagePermission = mStorageManagerInternal.hasExternalStorage(callingUid,
+ callingPackage);
userKeyUnlocked = isUserKeyUnlocked(userId);
- storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4c2cd53..5188a72 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4666,7 +4666,8 @@
app.getCompat(), getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
- app.getDisabledCompatChanges(), serializedSystemFontMap);
+ app.getDisabledCompatChanges(), serializedSystemFontMap,
+ app.getStartElapsedTime(), app.getStartUptime());
} else {
thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
null, null, null, testMode,
@@ -4676,7 +4677,8 @@
app.getCompat(), getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
- app.getDisabledCompatChanges(), serializedSystemFontMap);
+ app.getDisabledCompatChanges(), serializedSystemFontMap,
+ app.getStartElapsedTime(), app.getStartUptime());
}
if (profilerInfo != null) {
profilerInfo.closeFd();
@@ -11951,6 +11953,15 @@
// If this is a preceding instance of another process instance
allowRestart = mProcessList.handlePrecedingAppDiedLocked(app);
+ // If somehow this process was still waiting for the death of its predecessor,
+ // (probably it's "killed" before starting for real), reset the bookkeeping.
+ final ProcessRecord predecessor = app.mPredecessor;
+ if (predecessor != null) {
+ predecessor.mSuccessor = null;
+ predecessor.mSuccessorStartRunnable = null;
+ app.mPredecessor = null;
+ }
+
// If the caller is restarting this app, then leave it in its
// current lists and let the caller take care of it.
if (restarting) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 74c35e9..bbd41f7 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1794,13 +1794,14 @@
if (app.isPendingStart()) {
return true;
}
- long startTime = SystemClock.uptimeMillis();
+ final long startUptime = SystemClock.uptimeMillis();
+ final long startElapsedTime = SystemClock.elapsedRealtime();
if (app.getPid() > 0 && app.getPid() != ActivityManagerService.MY_PID) {
- checkSlow(startTime, "startProcess: removing from pids map");
+ checkSlow(startUptime, "startProcess: removing from pids map");
mService.removePidLocked(app.getPid(), app);
app.setBindMountPending(false);
mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
- checkSlow(startTime, "startProcess: done removing from pids map");
+ checkSlow(startUptime, "startProcess: done removing from pids map");
app.setPid(0);
app.setStartSeq(0);
}
@@ -1813,9 +1814,9 @@
"startProcessLocked removing on hold: " + app);
mService.mProcessesOnHold.remove(app);
- checkSlow(startTime, "startProcess: starting to update cpu stats");
+ checkSlow(startUptime, "startProcess: starting to update cpu stats");
mService.updateCpuStats();
- checkSlow(startTime, "startProcess: done updating cpu stats");
+ checkSlow(startUptime, "startProcess: done updating cpu stats");
try {
final int userId = UserHandle.getUserId(app.uid);
@@ -1832,7 +1833,7 @@
if (!app.isolated) {
int[] permGids = null;
try {
- checkSlow(startTime, "startProcess: getting gids from package manager");
+ checkSlow(startUptime, "startProcess: getting gids from package manager");
final IPackageManager pm = AppGlobals.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName,
MATCH_DIRECT_BOOT_AUTO, app.userId);
@@ -1870,7 +1871,7 @@
gids = computeGidsForProcess(mountExternal, uid, permGids, externalStorageAccess);
}
app.setMountMode(mountExternal);
- checkSlow(startTime, "startProcess: building args");
+ checkSlow(startUptime, "startProcess: building args");
if (mService.mAtmInternal.isFactoryTestProcess(app.getWindowProcessController())) {
uid = 0;
}
@@ -2028,7 +2029,7 @@
return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
- instructionSet, invokeWith, startTime);
+ instructionSet, invokeWith, startUptime, startElapsedTime);
} catch (RuntimeException e) {
Slog.e(ActivityManagerService.TAG, "Failure starting process " + app.processName, e);
@@ -2048,7 +2049,7 @@
boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
- long startTime) {
+ long startUptime, long startElapsedTime) {
app.setPendingStart(true);
app.setRemoved(false);
synchronized (mProcLock) {
@@ -2069,7 +2070,7 @@
}
final long startSeq = ++mProcStartSeqCounter;
app.setStartSeq(startSeq);
- app.setStartParams(uid, hostingRecord, seInfo, startTime);
+ app.setStartParams(uid, hostingRecord, seInfo, startUptime, startElapsedTime);
app.setUsingWrapper(invokeWith != null
|| Zygote.getWrapProperty(app.processName) != null);
mPendingStarts.put(startSeq, app);
@@ -2086,7 +2087,7 @@
final Process.ProcessStartResult startResult = startProcess(hostingRecord,
entryPoint, app,
uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
- requiredAbi, instructionSet, invokeWith, startTime);
+ requiredAbi, instructionSet, invokeWith, startUptime);
handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
startSeq, false);
} catch (RuntimeException e) {
@@ -5144,7 +5145,8 @@
}
Watchdog.getInstance().processDied(app.processName, app.getPid());
- if (app.getDeathRecipient() == null) {
+ if (app.getDeathRecipient() == null
+ && mDyingProcesses.get(app.processName, app.uid) == app) {
// If we've done unlinkDeathRecipient before calling into this, remove from dying list.
mDyingProcesses.remove(app.processName, app.uid);
app.setDyingPid(0);
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 8ae1259..8c55626 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -178,9 +178,14 @@
private volatile String mSeInfo;
/**
- * When the process is started.
+ * When the process is started. (before zygote fork)
*/
- private volatile long mStartTime;
+ private volatile long mStartUptime;
+
+ /**
+ * When the process is started. (before zygote fork)
+ */
+ private volatile long mStartElapsedTime;
/**
* This will be same as {@link #uid} usually except for some apps used during factory testing.
@@ -372,16 +377,18 @@
Runnable mSuccessorStartRunnable;
void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
- long startTime) {
+ long startUptime, long startElapsedTime) {
this.mStartUid = startUid;
this.mHostingRecord = hostingRecord;
this.mSeInfo = seInfo;
- this.mStartTime = startTime;
+ this.mStartUptime = startUptime;
+ this.mStartElapsedTime = startElapsedTime;
}
@GuardedBy({"mService", "mProcLock"})
void dump(PrintWriter pw, String prefix) {
final long nowUptime = SystemClock.uptimeMillis();
+ final long nowElapsedTime = SystemClock.elapsedRealtime();
pw.print(prefix); pw.print("user #"); pw.print(userId);
pw.print(" uid="); pw.print(info.uid);
@@ -442,6 +449,10 @@
pw.print(prefix); pw.print("pid="); pw.println(mPid);
pw.print(prefix); pw.print("lastActivityTime=");
TimeUtils.formatDuration(mLastActivityTime, nowUptime, pw);
+ pw.print(prefix); pw.print("startUptimeTime=");
+ TimeUtils.formatDuration(mStartElapsedTime, nowUptime, pw);
+ pw.print(prefix); pw.print("startElapsedTime=");
+ TimeUtils.formatDuration(mStartElapsedTime, nowElapsedTime, pw);
pw.println();
if (mPersistent || mRemoved) {
pw.print(prefix); pw.print("persistent="); pw.print(mPersistent);
@@ -671,12 +682,21 @@
mSeInfo = seInfo;
}
- long getStartTime() {
- return mStartTime;
+ long getStartUptime() {
+ return mStartUptime;
}
- void setStartTime(long startTime) {
- mStartTime = startTime;
+ /**
+ * Same as {@link #getStartUptime()}.
+ * @deprecated use {@link #getStartUptime()} instead for clarity.
+ */
+ @Deprecated
+ long getStartTime() {
+ return mStartUptime;
+ }
+
+ long getStartElapsedTime() {
+ return mStartElapsedTime;
}
int getStartUid() {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 4dd1682..18be9a10 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4638,12 +4638,13 @@
* or recording for VOICE_COMMUNICATION.
* or
* - It requests a mode different from MODE_IN_COMMUNICATION or MODE_NORMAL
+ * Note: only privileged apps can request MODE_IN_CALL, MODE_CALL_REDIRECT
+ * or MODE_COMMUNICATION_REDIRECT.
*/
public boolean isActive() {
return mIsPrivileged
|| ((mMode == AudioSystem.MODE_IN_COMMUNICATION)
&& (mRecordingActive || mPlaybackActive))
- || mMode == AudioSystem.MODE_IN_CALL
|| mMode == AudioSystem.MODE_RINGTONE
|| mMode == AudioSystem.MODE_CALL_SCREENING;
}
@@ -4752,9 +4753,13 @@
final boolean hasModifyPhoneStatePermission = mContext.checkCallingOrSelfPermission(
android.Manifest.permission.MODIFY_PHONE_STATE)
== PackageManager.PERMISSION_GRANTED;
- if ((mode == AudioSystem.MODE_IN_CALL) && !hasModifyPhoneStatePermission) {
- Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
- + pid + ", uid=" + Binder.getCallingUid());
+ if ((mode == AudioSystem.MODE_IN_CALL
+ || mode == AudioSystem.MODE_CALL_REDIRECT
+ || mode == AudioSystem.MODE_COMMUNICATION_REDIRECT)
+ && !hasModifyPhoneStatePermission) {
+ Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode("
+ + AudioSystem.modeToString(mode) + ") from pid=" + pid
+ + ", uid=" + Binder.getCallingUid());
return;
}
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index fb74170..e2e56ae 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -223,11 +223,18 @@
* Overrides the enabled state for a given change and app.
*
*
- * @param overrides list of overrides to default changes config.
- * @param packageName app for which the overrides will be applied.
+ * @param overrides list of overrides to default changes config.
+ * @param packageName app for which the overrides will be applied.
+ * @param skipUnknownChangeIds whether to skip unknown change IDs in {@code overrides}.
*/
- synchronized void addOverrides(CompatibilityOverrideConfig overrides, String packageName) {
+ synchronized void addPackageOverrides(CompatibilityOverrideConfig overrides,
+ String packageName, boolean skipUnknownChangeIds) {
for (Long changeId : overrides.overrides.keySet()) {
+ if (skipUnknownChangeIds && !isKnownChangeId(changeId)) {
+ Slog.w(TAG, "Trying to add overrides for unknown Change ID " + changeId + ". "
+ + "Skipping Change ID.");
+ continue;
+ }
addOverrideUnsafe(changeId, packageName, overrides.overrides.get(changeId));
}
saveOverrides();
@@ -338,7 +345,8 @@
/**
* Removes all overrides previously added via {@link #addOverride(long, String, boolean)} or
- * {@link #addOverrides(CompatibilityOverrideConfig, String)} for a certain package.
+ * {@link #addPackageOverrides(CompatibilityOverrideConfig, String, boolean)} for a certain
+ * package.
*
* <p>This restores the default behaviour for the given app.
*
@@ -359,7 +367,8 @@
/**
* Removes overrides whose change ID is specified in {@code overridesToRemove} that were
* previously added via {@link #addOverride(long, String, boolean)} or
- * {@link #addOverrides(CompatibilityOverrideConfig, String)} for a certain package.
+ * {@link #addPackageOverrides(CompatibilityOverrideConfig, String, boolean)} for a certain
+ * package.
*
* <p>This restores the default behaviour for the given change IDs and app.
*
@@ -370,6 +379,11 @@
String packageName) {
boolean shouldInvalidateCache = false;
for (Long changeId : overridesToRemove.changeIds) {
+ if (!isKnownChangeId(changeId)) {
+ Slog.w(TAG, "Trying to remove overrides for unknown Change ID " + changeId + ". "
+ + "Skipping Change ID.");
+ continue;
+ }
shouldInvalidateCache |= removeOverrideUnsafe(changeId, packageName);
}
if (shouldInvalidateCache) {
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index b32d1d7..6ea89d4 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -205,7 +205,8 @@
overridesMap.put(change, new PackageOverride.Builder().setEnabled(false)
.build());
}
- mCompatConfig.addOverrides(new CompatibilityOverrideConfig(overridesMap), packageName);
+ mCompatConfig.addPackageOverrides(new CompatibilityOverrideConfig(overridesMap),
+ packageName, /* skipUnknownChangeIds */ false);
killPackage(packageName);
}
@@ -220,7 +221,8 @@
overridesMap.put(change, new PackageOverride.Builder().setEnabled(false)
.build());
}
- mCompatConfig.addOverrides(new CompatibilityOverrideConfig(overridesMap), packageName);
+ mCompatConfig.addPackageOverrides(new CompatibilityOverrideConfig(overridesMap),
+ packageName, /* skipUnknownChangeIds */ false);
}
@Override
@@ -229,7 +231,7 @@
// TODO(b/183630314): Unify the permission enforcement with the other setOverrides* methods.
checkCompatChangeOverrideOverridablePermission();
checkAllCompatOverridesAreOverridable(overrides.overrides.keySet());
- mCompatConfig.addOverrides(overrides, packageName);
+ mCompatConfig.addPackageOverrides(overrides, packageName, /* skipUnknownChangeIds= */ true);
}
@Override
@@ -435,7 +437,7 @@
private void checkAllCompatOverridesAreOverridable(Collection<Long> changeIds) {
for (Long changeId : changeIds) {
- if (!mCompatConfig.isOverridable(changeId)) {
+ if (isKnownChangeId(changeId) && !mCompatConfig.isOverridable(changeId)) {
throw new SecurityException("Only change ids marked as Overridable can be "
+ "overridden.");
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 2f3342f..22dd2c0 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -108,8 +108,6 @@
// screen state returns. Playing the animation can also be somewhat slow.
private static final boolean USE_COLOR_FADE_ON_ANIMATION = false;
- // The minimum reduction in brightness when dimmed.
- private static final float SCREEN_DIM_MINIMUM_REDUCTION_FLOAT = 0.04f;
private static final float SCREEN_ANIMATION_RATE_MINIMUM = 0.0f;
private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250;
@@ -200,6 +198,10 @@
// The dim screen brightness.
private final float mScreenBrightnessDimConfig;
+ // The minimum dim amount to use if the screen brightness is already below
+ // mScreenBrightnessDimConfig.
+ private final float mScreenBrightnessMinimumDimAmount;
+
private final float mScreenBrightnessDefault;
// The minimum allowed brightness while in VR.
@@ -485,6 +487,9 @@
pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DOZE));
mScreenBrightnessDimConfig = clampAbsoluteBrightness(
pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DIM));
+ mScreenBrightnessMinimumDimAmount = resources.getFloat(
+ com.android.internal.R.dimen.config_screenBrightnessMinimumDimAmountFloat);
+
// NORMAL SCREEN SETTINGS
mScreenBrightnessDefault = clampAbsoluteBrightness(
@@ -1284,7 +1289,7 @@
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
if (brightnessState > PowerManager.BRIGHTNESS_MIN) {
brightnessState = Math.max(
- Math.min(brightnessState - SCREEN_DIM_MINIMUM_REDUCTION_FLOAT,
+ Math.min(brightnessState - mScreenBrightnessMinimumDimAmount,
mScreenBrightnessDimConfig),
PowerManager.BRIGHTNESS_MIN);
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED);
diff --git a/services/core/java/com/android/server/locales/LocaleManagerShellCommand.java b/services/core/java/com/android/server/locales/LocaleManagerShellCommand.java
index 769ea17..803b5a3 100644
--- a/services/core/java/com/android/server/locales/LocaleManagerShellCommand.java
+++ b/services/core/java/com/android/server/locales/LocaleManagerShellCommand.java
@@ -133,7 +133,7 @@
try {
LocaleList locales = mBinderService.getApplicationLocales(packageName, userId);
getOutPrintWriter().println("Locales for " + packageName
- + " for user " + userId + " are " + locales);
+ + " for user " + userId + " are [" + locales.toLanguageTags() + "]");
} catch (RemoteException e) {
getOutPrintWriter().println("Remote Exception: " + e);
} catch (IllegalArgumentException e) {
diff --git a/services/core/java/com/android/server/locales/TEST_MAPPING b/services/core/java/com/android/server/locales/TEST_MAPPING
index 097c2bc..27d2851 100644
--- a/services/core/java/com/android/server/locales/TEST_MAPPING
+++ b/services/core/java/com/android/server/locales/TEST_MAPPING
@@ -10,6 +10,9 @@
},
{
"name": "CtsLocaleManagerTestCases"
+ },
+ {
+ "name": "CtsLocaleManagerHostTestCases"
}
]
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 7fd7505..c47ca4b 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -558,7 +558,10 @@
Slog.d(TAG, "Marking session " + sessionId + " as failed: " + errorMessage);
childSessions = getChildSessionsLocked();
}
- cleanStageDir(childSessions);
+ destroyInternal();
+ for (PackageInstallerSession child : childSessions) {
+ child.destroyInternal();
+ }
mCallback.onStagedSessionChanged(PackageInstallerSession.this);
}
@@ -576,7 +579,10 @@
Slog.d(TAG, "Marking session " + sessionId + " as applied");
childSessions = getChildSessionsLocked();
}
- cleanStageDir(childSessions);
+ destroyInternal();
+ for (PackageInstallerSession child : childSessions) {
+ child.destroyInternal();
+ }
mCallback.onStagedSessionChanged(PackageInstallerSession.this);
}
@@ -699,13 +705,11 @@
return;
}
mDestroyed = true;
- List<PackageInstallerSession> childSessions = getChildSessionsLocked();
r = () -> {
assertNotLocked("abandonStaged");
if (mCommitted.get()) {
mStagingManager.abortCommittedSession(this);
}
- cleanStageDir(childSessions);
destroyInternal();
dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null);
maybeCleanUpChildSessions();
@@ -2102,10 +2106,6 @@
destroyInternal();
// Dispatch message to remove session from PackageInstallerService.
dispatchSessionFinished(error, detailMessage, null);
- // TODO(b/173194203): clean up staged session in destroyInternal() call instead
- if (isStaged() && stageDir != null) {
- cleanStageDir();
- }
}
private void onSessionVerificationFailure(int error, String msg) {
@@ -4282,41 +4282,13 @@
incrementalFileStorages = mIncrementalFileStorages;
mIncrementalFileStorages = null;
}
- // For staged sessions, we don't delete the directory where the packages have been copied,
- // since these packages are supposed to be read on reboot.
- // Those dirs are deleted when the staged session has reached a final state.
- if (stageDir != null && !params.isStaged) {
- try {
- if (incrementalFileStorages != null) {
- incrementalFileStorages.cleanUpAndMarkComplete();
- }
- mInstaller.rmPackageDir(stageDir.getAbsolutePath());
- } catch (InstallerException ignored) {
- }
- }
- }
-
- private void cleanStageDir(List<PackageInstallerSession> childSessions) {
- if (isMultiPackage()) {
- for (PackageInstallerSession childSession : childSessions) {
- childSession.cleanStageDir();
- }
- } else {
- cleanStageDir();
- }
- }
-
- private void cleanStageDir() {
- final IncrementalFileStorages incrementalFileStorages;
- synchronized (mLock) {
- incrementalFileStorages = mIncrementalFileStorages;
- mIncrementalFileStorages = null;
- }
try {
if (incrementalFileStorages != null) {
incrementalFileStorages.cleanUpAndMarkComplete();
}
- mInstaller.rmPackageDir(stageDir.getAbsolutePath());
+ if (stageDir != null) {
+ mInstaller.rmPackageDir(stageDir.getAbsolutePath());
+ }
} catch (InstallerException ignored) {
}
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 3855e65..a01c358 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -4205,7 +4205,7 @@
// Make sure all dynamic permissions have been assigned to a package,
// and make sure there are no dangling permissions.
boolean permissionSourcePackageChanged = updatePermissionSourcePackage(changingPkgName,
- changingPkg, callback);
+ callback);
if (permissionTreesSourcePackageChanged | permissionSourcePackageChanged) {
// Permission ownership has changed. This e.g. changes which packages can get signature
@@ -4244,22 +4244,12 @@
/**
* Update which app declares a permission.
*
- * <p>Possible parameter combinations
- * <table>
- * <tr><th></th><th>packageName != null</th><th>packageName == null</th></tr>
- * <tr><th>pkg != null</th><td>package is updated</td><td>invalid</td></tr>
- * <tr><th>pkg == null</th><td>package is deleted</td><td>all packages are updated</td></tr>
- * </table>
- *
* @param packageName The package that is updated, or {@code null} if all packages should be
* updated
- * @param pkg The package that is updated, or {@code null} if all packages should be updated or
- * package is deleted
*
* @return {@code true} if a permission source package might have changed
*/
private boolean updatePermissionSourcePackage(@Nullable String packageName,
- @Nullable AndroidPackage pkg,
final @Nullable PermissionCallback callback) {
// Always need update if packageName is null
if (packageName == null) {
@@ -4289,6 +4279,7 @@
}
}
if (needsUpdate != null) {
+ final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
for (final Permission bp : needsUpdate) {
// If the target package is being uninstalled, we need to revoke this permission
// From all other packages
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index ea3ef650..c6ff8a0 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -951,7 +951,7 @@
powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
} else if (count == 3) {
powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
- } else if (interactive && !beganFromNonInteractive) {
+ } else if (count == 1 && interactive && !beganFromNonInteractive) {
if (mSideFpsEventHandler.onSinglePressDetected(eventTime)) {
Slog.i(TAG, "Suppressing power key because the user is interacting with the "
+ "fingerprint sensor");
@@ -3479,13 +3479,23 @@
if (!mSystemBooted) {
// If we have not yet booted, don't let key events do anything.
// Exception: Wake and power key events are forwarded to PowerManager to allow it to
- // wake from quiescent mode during boot.
+ // wake from quiescent mode during boot. On these key events we also explicitly turn on
+ // the connected TV and switch HDMI input if we're a HDMI playback device.
+ boolean shouldTurnOnTv = false;
if (down && (keyCode == KeyEvent.KEYCODE_POWER
|| keyCode == KeyEvent.KEYCODE_TV_POWER)) {
wakeUpFromPowerKey(event.getDownTime());
+ shouldTurnOnTv = true;
} else if (down && (isWakeKey || keyCode == KeyEvent.KEYCODE_WAKEUP)
&& isWakeKeyWhenScreenOff(keyCode)) {
wakeUpFromWakeKey(event);
+ shouldTurnOnTv = true;
+ }
+ if (shouldTurnOnTv) {
+ final HdmiControl hdmiControl = getHdmiControl();
+ if (hdmiControl != null) {
+ hdmiControl.turnOnTv();
+ }
}
return 0;
}
diff --git a/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java b/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
index b7fb6e5..0276b37 100644
--- a/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
+++ b/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
@@ -44,7 +44,7 @@
private static final int MSG_KEY_VERY_LONG_PRESS = 1;
private static final int MSG_KEY_DELAYED_PRESS = 2;
- private volatile int mKeyPressCounter;
+ private int mKeyPressCounter;
private boolean mBeganFromNonInteractive = false;
private final ArrayList<SingleKeyRule> mRules = new ArrayList();
@@ -53,7 +53,6 @@
// Key code of current key down event, reset when key up.
private int mDownKeyCode = KeyEvent.KEYCODE_UNKNOWN;
private volatile boolean mHandledByLongPress = false;
- private volatile boolean mHandledByMultiPress = false;
private final Handler mHandler;
private long mLastDownTime = 0;
private static final long MULTI_PRESS_TIMEOUT = ViewConfiguration.getMultiPressTimeout();
@@ -223,7 +222,6 @@
reset();
}
mDownKeyCode = keyCode;
- mLastDownTime = event.getDownTime();
// Picks a new rule, return if no rule picked.
if (mActiveRule == null) {
@@ -238,12 +236,21 @@
break;
}
}
+ mLastDownTime = 0;
}
if (mActiveRule == null) {
return;
}
- if (mKeyPressCounter == 0) {
+ final long keyDownInterval = event.getDownTime() - mLastDownTime;
+ mLastDownTime = event.getDownTime();
+ if (keyDownInterval >= MULTI_PRESS_TIMEOUT) {
+ mKeyPressCounter = 1;
+ } else {
+ mKeyPressCounter++;
+ }
+
+ if (mKeyPressCounter == 1) {
if (mActiveRule.supportLongPress()) {
final Message msg = mHandler.obtainMessage(MSG_KEY_LONG_PRESS, keyCode, 0,
mActiveRule);
@@ -263,17 +270,16 @@
mHandler.removeMessages(MSG_KEY_DELAYED_PRESS);
// Trigger multi press immediately when reach max count.( > 1)
- if (mKeyPressCounter == mActiveRule.getMaxMultiPressCount() - 1) {
+ if (mActiveRule.getMaxMultiPressCount() > 1
+ && mKeyPressCounter == mActiveRule.getMaxMultiPressCount()) {
if (DEBUG) {
Log.i(TAG, "Trigger multi press " + mActiveRule.toString() + " for it"
- + " reached the max count " + (mKeyPressCounter + 1));
+ + " reached the max count " + mKeyPressCounter);
}
final Message msg = mHandler.obtainMessage(MSG_KEY_DELAYED_PRESS, keyCode,
- mKeyPressCounter + 1, mActiveRule);
+ mKeyPressCounter, mActiveRule);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
- mHandledByMultiPress = true;
- mKeyPressCounter = 0;
}
}
}
@@ -286,10 +292,10 @@
return false;
}
- if (mHandledByLongPress || mHandledByMultiPress) {
+ if (mHandledByLongPress) {
mHandledByLongPress = false;
- mHandledByMultiPress = false;
mKeyPressCounter = 0;
+ mActiveRule = null;
return true;
}
@@ -303,16 +309,17 @@
1, mActiveRule);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
- reset();
+ mActiveRule = null;
return true;
}
// This could be a multi-press. Wait a little bit longer to confirm.
- mKeyPressCounter++;
- Message msg = mHandler.obtainMessage(MSG_KEY_DELAYED_PRESS, mActiveRule.mKeyCode,
- mKeyPressCounter, mActiveRule);
- msg.setAsynchronous(true);
- mHandler.sendMessageDelayed(msg, MULTI_PRESS_TIMEOUT);
+ if (mKeyPressCounter < mActiveRule.getMaxMultiPressCount()) {
+ Message msg = mHandler.obtainMessage(MSG_KEY_DELAYED_PRESS, mActiveRule.mKeyCode,
+ mKeyPressCounter, mActiveRule);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageDelayed(msg, MULTI_PRESS_TIMEOUT);
+ }
return true;
}
reset();
@@ -342,7 +349,6 @@
}
mHandledByLongPress = false;
- mHandledByMultiPress = false;
mDownKeyCode = KeyEvent.KEYCODE_UNKNOWN;
}
@@ -373,9 +379,6 @@
Log.wtf(TAG, "No active rule.");
return;
}
- // We count the press count when interceptKeyUp. Reset the counter here to prevent if
- // the multi-press or press happened but the count is less than max multi-press count.
- mKeyPressCounter = 0;
final int keyCode = msg.arg1;
final int pressCount = msg.arg2;
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 0394d4c..7cdae58 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -93,8 +93,12 @@
import android.content.pm.PermissionInfo;
import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.display.DisplayManager;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
+import android.media.AudioManager;
+import android.media.MediaDrm;
+import android.media.UnsupportedSchemeException;
import android.net.ConnectivityManager;
import android.net.INetworkStatsService;
import android.net.INetworkStatsSession;
@@ -163,6 +167,7 @@
import android.util.SparseArray;
import android.util.StatsEvent;
import android.util.proto.ProtoOutputStream;
+import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.procstats.IProcessStats;
@@ -743,6 +748,8 @@
return pullAccessibilityShortcutStatsLocked(atomTag, data);
case FrameworkStatsLog.ACCESSIBILITY_FLOATING_MENU_STATS:
return pullAccessibilityFloatingMenuStatsLocked(atomTag, data);
+ case FrameworkStatsLog.MEDIA_CAPABILITIES:
+ return pullMediaCapabilitiesStats(atomTag, data);
default:
throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
}
@@ -940,6 +947,7 @@
registerKeystoreCrashStats();
registerAccessibilityShortcutStats();
registerAccessibilityFloatingMenuStats();
+ registerMediaCapabilitiesStats();
}
private void initAndRegisterNetworkStatsPullers() {
@@ -4188,6 +4196,16 @@
);
}
+ private void registerMediaCapabilitiesStats() {
+ int tagId = FrameworkStatsLog.MEDIA_CAPABILITIES;
+ mStatsManager.setPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ DIRECT_EXECUTOR,
+ mStatsCallbackImpl
+ );
+ }
+
int parseKeystoreStorageStats(KeystoreAtom[] atoms, List<StatsEvent> pulledData) {
for (KeystoreAtom atomWrapper : atoms) {
if (atomWrapper.payload.getTag() != KeystoreAtomPayload.storageStats) {
@@ -4470,6 +4488,162 @@
return StatsManager.PULL_SUCCESS;
}
+ int pullMediaCapabilitiesStats(int atomTag, List<StatsEvent> pulledData) {
+ AudioManager audioManager = mContext.getSystemService(AudioManager.class);
+ if (audioManager == null) {
+ return StatsManager.PULL_SKIP;
+ }
+
+ // get the surround sound metrics information
+ Map<Integer, Boolean> surroundEncodingsMap = audioManager.getSurroundFormats();
+ byte[] surroundEncodings = toBytes(new ArrayList(surroundEncodingsMap.keySet()));
+ byte[] sinkSurroundEncodings = toBytes(audioManager.getReportedSurroundFormats());
+ List<Integer> disabledSurroundEncodingsList = new ArrayList<>();
+ List<Integer> enabledSurroundEncodingsList = new ArrayList<>();
+ for (int surroundEncoding: surroundEncodingsMap.keySet()) {
+ if (!surroundEncodingsMap.get(surroundEncoding)) {
+ disabledSurroundEncodingsList.add(surroundEncoding);
+ } else {
+ enabledSurroundEncodingsList.add(surroundEncoding);
+ }
+ }
+ byte[] disabledSurroundEncodings = toBytes(disabledSurroundEncodingsList);
+ byte[] enabledSurroundEncodings = toBytes(enabledSurroundEncodingsList);
+ int surroundOutputMode = audioManager.getEncodedSurroundMode();
+
+ DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+ Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+ // get the display capabilities metrics information
+ Display.HdrCapabilities hdrCapabilities = display.getHdrCapabilities();
+ byte[] sinkHdrFormats = new byte[]{};
+ if (hdrCapabilities != null) {
+ sinkHdrFormats = toBytes(hdrCapabilities.getSupportedHdrTypes());
+ }
+ byte[] sinkDisplayModes = toBytes(display.getSupportedModes());
+ int hdcpLevel = -1;
+ List<UUID> uuids = MediaDrm.getSupportedCryptoSchemes();
+ try {
+ if (!uuids.isEmpty()) {
+ MediaDrm mediaDrm = new MediaDrm(uuids.get(0));
+ hdcpLevel = mediaDrm.getConnectedHdcpLevel();
+ }
+ } catch (UnsupportedSchemeException exception) {
+ Slog.e(TAG, "pulling hdcp level failed.", exception);
+ hdcpLevel = -1;
+ }
+
+ // get the display settings metrics information
+ int matchContentFrameRateUserPreference =
+ displayManager.getMatchContentFrameRateUserPreference();
+ byte[] userDisabledHdrTypes = toBytes(displayManager.getUserDisabledHdrTypes());
+ Display.Mode userPreferredDisplayMode = displayManager.getUserPreferredDisplayMode();
+ int userPreferredWidth = userPreferredDisplayMode != null
+ ? userPreferredDisplayMode.getPhysicalWidth() : -1;
+ int userPreferredHeight = userPreferredDisplayMode != null
+ ? userPreferredDisplayMode.getPhysicalHeight() : -1;
+ float userPreferredRefreshRate = userPreferredDisplayMode != null
+ ? userPreferredDisplayMode.getRefreshRate() : 0.0f;
+ boolean hasUserDisabledAllm = false;
+ try {
+ hasUserDisabledAllm = Settings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED,
+ 1) == 0;
+ } catch (Settings.SettingNotFoundException exception) {
+ Slog.e(
+ TAG, "unable to find setting for MINIMAL_POST_PROCESSING_ALLOWED.",
+ exception);
+ hasUserDisabledAllm = false;
+ }
+
+ pulledData.add(
+ FrameworkStatsLog.buildStatsEvent(
+ atomTag, surroundEncodings, sinkSurroundEncodings,
+ disabledSurroundEncodings, enabledSurroundEncodings, surroundOutputMode,
+ sinkHdrFormats, sinkDisplayModes, hdcpLevel,
+ matchContentFrameRateUserPreference, userDisabledHdrTypes,
+ userPreferredWidth, userPreferredHeight, userPreferredRefreshRate,
+ hasUserDisabledAllm));
+
+ return StatsManager.PULL_SUCCESS;
+ }
+
+ private byte[] toBytes(List<Integer> audioEncodings) {
+ ProtoOutputStream protoOutputStream = new ProtoOutputStream();
+ for (int audioEncoding : audioEncodings) {
+ protoOutputStream.write(
+ ProtoOutputStream.FIELD_COUNT_REPEATED | ProtoOutputStream.FIELD_TYPE_ENUM | 1,
+ audioEncoding);
+ }
+ return protoOutputStream.getBytes();
+ }
+
+ private byte[] toBytes(int[] array) {
+ ProtoOutputStream protoOutputStream = new ProtoOutputStream();
+ for (int element : array) {
+ protoOutputStream.write(
+ ProtoOutputStream.FIELD_COUNT_REPEATED | ProtoOutputStream.FIELD_TYPE_ENUM | 1,
+ element);
+ }
+ return protoOutputStream.getBytes();
+ }
+
+ private byte[] toBytes(Display.Mode[] displayModes) {
+ Map<Integer, Integer> modeGroupIds = createModeGroups(displayModes);
+ ProtoOutputStream protoOutputStream = new ProtoOutputStream();
+ for (Display.Mode element : displayModes) {
+ ProtoOutputStream protoOutputStreamMode = new ProtoOutputStream();
+ protoOutputStreamMode.write(
+ ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_INT32 | 1,
+ element.getPhysicalHeight());
+ protoOutputStreamMode.write(
+ ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_INT32 | 2,
+ element.getPhysicalWidth());
+ protoOutputStreamMode.write(
+ ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_FLOAT | 3,
+ element.getRefreshRate());
+ protoOutputStreamMode.write(
+ ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_INT32 | 4,
+ modeGroupIds.get(element.getModeId()));
+ protoOutputStream.write(
+ ProtoOutputStream.FIELD_COUNT_REPEATED
+ | ProtoOutputStream.FIELD_TYPE_MESSAGE | 1,
+ protoOutputStreamMode.getBytes());
+ }
+ return protoOutputStream.getBytes();
+ }
+
+ // Returns map modeId -> groupId such that all modes with the same group have alternative
+ // refresh rates
+ private Map<Integer, Integer> createModeGroups(Display.Mode[] supportedModes) {
+ Map<Integer, Integer> modeGroupIds = new ArrayMap<>();
+ int groupId = 1;
+ for (Display.Mode mode : supportedModes) {
+ if (modeGroupIds.containsKey(mode.getModeId())) {
+ continue;
+ }
+ modeGroupIds.put(mode.getModeId(), groupId);
+ for (float refreshRate : mode.getAlternativeRefreshRates()) {
+ int alternativeModeId = findModeId(supportedModes, mode.getPhysicalWidth(),
+ mode.getPhysicalHeight(), refreshRate);
+ if (alternativeModeId != -1 && !modeGroupIds.containsKey(alternativeModeId)) {
+ modeGroupIds.put(alternativeModeId, groupId);
+ }
+ }
+ groupId++;
+ }
+ return modeGroupIds;
+ }
+
+ private int findModeId(Display.Mode[] modes, int width, int height, float refreshRate) {
+ for (Display.Mode mode : modes) {
+ if (mode.matches(width, height, refreshRate)) {
+ return mode.getModeId();
+ }
+ }
+ return -1;
+ }
+
/**
* Counts how many accessibility services (including features) there are in the colon-separated
* string list.
diff --git a/services/core/java/com/android/server/timezonedetector/Dumpable.java b/services/core/java/com/android/server/timezonedetector/Dumpable.java
index 5603c38..1dd9637 100644
--- a/services/core/java/com/android/server/timezonedetector/Dumpable.java
+++ b/services/core/java/com/android/server/timezonedetector/Dumpable.java
@@ -24,18 +24,4 @@
/** Dump internal state. */
void dump(@NonNull IndentingPrintWriter pw, @Nullable String[] args);
-
- /**
- * An interface that can be used expose when one component allows another to be registered so
- * that it is dumped at the same time.
- */
- interface Container {
-
- /**
- * Registers the supplied {@link Dumpable}. When the implementation is dumped
- * {@link Dumpable#dump(IndentingPrintWriter, String[])} should be called on the
- * {@code dumpable}.
- */
- void addDumpable(@NonNull Dumpable dumpable);
- }
}
diff --git a/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java b/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java
index b84f8a8..fc6e372 100644
--- a/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java
@@ -72,8 +72,8 @@
mLocationManager = context.getSystemService(LocationManager.class);
mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
- // Wire up the config change listeners. All invocations are performed on the mHandler
- // thread.
+ // Wire up the config change listeners for anything that could affect the return values from
+ // this object. All listener invocations are performed on the mHandler thread.
// Listen for the user changing / the user's location mode changing.
IntentFilter filter = new IntentFilter();
@@ -88,25 +88,19 @@
// Add async callbacks for global settings being changed.
ContentResolver contentResolver = mContext.getContentResolver();
+ ContentObserver contentObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ handleConfigChangeOnHandlerThread();
+ }
+ };
contentResolver.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.AUTO_TIME_ZONE), true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- handleConfigChangeOnHandlerThread();
- }
- });
+ Settings.Global.getUriFor(Settings.Global.AUTO_TIME_ZONE), true, contentObserver);
// Add async callbacks for user scoped location settings being changed.
contentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- handleConfigChangeOnHandlerThread();
- }
- }, UserHandle.USER_ALL);
+ true, contentObserver, UserHandle.USER_ALL);
}
private void handleConfigChangeOnHandlerThread() {
diff --git a/services/core/java/com/android/server/timezonedetector/GeolocationTimeZoneSuggestion.java b/services/core/java/com/android/server/timezonedetector/GeolocationTimeZoneSuggestion.java
index 3b32549..f4a6ef0 100644
--- a/services/core/java/com/android/server/timezonedetector/GeolocationTimeZoneSuggestion.java
+++ b/services/core/java/com/android/server/timezonedetector/GeolocationTimeZoneSuggestion.java
@@ -39,12 +39,11 @@
* <ul>
* <li>{@code effectiveFromElapsedMillis}: The time according to the elapsed realtime clock
* after which the suggestion should be considered in effect. For example, when a location fix
- * used to establish the time zone is old, then the suggestion
- * {@code effectiveFromElapsedMillis} should reflect this and indicates the time zone that was
- * detected / correct at that time. The time_zone_detector is only expected to use the latest
- * suggestion it has received, and so later suggestions always counteract previous suggestions.
- * The inclusion of this information means that the time_zone_detector can take into account
- * ordering when comparing suggestions from different sources.
+ * used to establish the time zone is old, then the suggestion's {@code
+ * effectiveFromElapsedMillis} should reflect this and indicates the time zone that was
+ * detected / correct at that time. The inclusion of this information means that the
+ * time_zone_detector <em>may</em> take this into account if comparing suggestions or signals
+ * from different sources.
* <br />Note: Because the times can be back-dated, time_zone_detector can be sent a sequence of
* suggestions where the {@code effectiveFromElapsedMillis} of later suggestions is before
* the {@code effectiveFromElapsedMillis} of an earlier one.</li>
diff --git a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
index 20f4fa1..f7ac9b6 100644
--- a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
+++ b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
@@ -21,7 +21,6 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
-import android.os.SystemProperties;
import android.util.ArraySet;
import com.android.internal.R;
@@ -64,11 +63,11 @@
public static final @ProviderMode String PROVIDER_MODE_ENABLED = "enabled";
/**
- * Device config keys that affect the {@link TimeZoneDetectorService} service and {@link
- * com.android.server.timezonedetector.location.LocationTimeZoneManagerService}.
+ * Device config keys that can affect {@link
+ * com.android.server.timezonedetector.location.LocationTimeZoneManagerService} behavior.
*/
- private static final Set<String> SERVER_FLAGS_KEYS_TO_WATCH = Collections.unmodifiableSet(
- new ArraySet<>(new String[] {
+ private static final Set<String> LOCATION_TIME_ZONE_MANAGER_SERVER_FLAGS_KEYS_TO_WATCH =
+ Collections.unmodifiableSet(new ArraySet<>(new String[] {
ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT,
ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE,
@@ -94,14 +93,6 @@
@NonNull private final Context mContext;
- /**
- * An ultimate "feature switch" for location-based time zone detection. If this is
- * {@code false}, the device cannot support the feature without a config change or a reboot:
- * This affects what services are started on boot to minimize expense when the feature is not
- * wanted.
- */
- private final boolean mGeoDetectionFeatureSupportedInConfig;
-
@NonNull private final ServerFlags mServerFlags;
/**
@@ -148,14 +139,6 @@
private ServiceConfigAccessor(@NonNull Context context) {
mContext = Objects.requireNonNull(context);
- // The config value is expected to be the main feature flag. Platform developers can also
- // force enable the feature using a persistent system property. Because system properties
- // can change, this value is cached and only changes on reboot.
- mGeoDetectionFeatureSupportedInConfig = context.getResources().getBoolean(
- com.android.internal.R.bool.config_enableGeolocationTimeZoneDetection)
- || SystemProperties.getBoolean(
- "persist.sys.location_time_zone_detection_feature_supported", false);
-
mServerFlags = ServerFlags.getInstance(mContext);
}
@@ -170,14 +153,15 @@
}
/**
- * Adds a listener that will be called when server flags related to this class change. The
- * callbacks are delivered on the main looper thread.
+ * Adds a listener that will be called when server flags related to location_time_zone_manager
+ * change. The callbacks are delivered on the main looper thread.
*
* <p>Note: Only for use by long-lived objects. There is deliberately no associated remove
* method.
*/
- public void addListener(@NonNull ConfigurationChangeListener listener) {
- mServerFlags.addListener(listener, SERVER_FLAGS_KEYS_TO_WATCH);
+ public void addLocationTimeZoneManagerConfigListener(
+ @NonNull ConfigurationChangeListener listener) {
+ mServerFlags.addListener(listener, LOCATION_TIME_ZONE_MANAGER_SERVER_FLAGS_KEYS_TO_WATCH);
}
/** Returns {@code true} if any form of automatic time zone detection is supported. */
@@ -197,11 +181,19 @@
/**
* Returns {@code true} if the location-based time zone detection feature can be supported on
* this device at all according to config. When {@code false}, implies that various other
- * location-based settings will be turned off or rendered meaningless. Typically {@link
- * #isGeoTimeZoneDetectionFeatureSupported()} should be used instead.
+ * location-based services and settings will be turned off or rendered meaningless.
+ *
+ * <p>This is the ultimate "feature switch" for location-based time zone detection. If this is
+ * {@code false}, the device cannot support the feature without a config change or a reboot:
+ * This affects what services are started on boot to minimize expense when the feature is not
+ * wanted.
+ *
+ * Typically {@link #isGeoTimeZoneDetectionFeatureSupported()} should be used except during
+ * boot.
*/
public boolean isGeoTimeZoneDetectionFeatureSupportedInConfig() {
- return mGeoDetectionFeatureSupportedInConfig;
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableGeolocationTimeZoneDetection);
}
/**
@@ -213,7 +205,7 @@
// 1) Be turned on in config.
// 2) Not be turned off via a server flag.
// 3) There must be at least one location time zone provider enabled / configured.
- return mGeoDetectionFeatureSupportedInConfig
+ return isGeoTimeZoneDetectionFeatureSupportedInConfig()
&& isGeoTimeZoneDetectionFeatureSupportedInternal()
&& atLeastOneProviderIsEnabled();
}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
index d429b87..4161177 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
@@ -25,7 +25,7 @@
* <p>The methods on this class can be called from any thread.
* @hide
*/
-public interface TimeZoneDetectorInternal extends Dumpable.Container {
+public interface TimeZoneDetectorInternal {
/** Adds a listener that will be invoked when {@link ConfigurationInternal} may have changed. */
void addConfigurationListener(@NonNull ConfigurationChangeListener listener);
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java
index 4e78f5a..ca87811 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java
@@ -57,11 +57,6 @@
}
@Override
- public void addDumpable(@NonNull Dumpable dumpable) {
- mTimeZoneDetectorStrategy.addDumpable(dumpable);
- }
-
- @Override
public void addConfigurationListener(ConfigurationChangeListener listener) {
synchronized (mConfigurationListeners) {
mConfigurationListeners.add(Objects.requireNonNull(listener));
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
index b1b537b..e6a58a1 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
@@ -45,6 +45,8 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
/**
@@ -59,6 +61,7 @@
implements IBinder.DeathRecipient {
static final String TAG = "time_zone_detector";
+ static final boolean DBG = false;
/**
* Handles the service lifecycle for {@link TimeZoneDetectorService} and
@@ -112,17 +115,22 @@
*/
@GuardedBy("mListeners")
@NonNull
- private final ArrayMap<IBinder, ITimeZoneDetectorListener> mListeners =
- new ArrayMap<>();
+ private final ArrayMap<IBinder, ITimeZoneDetectorListener> mListeners = new ArrayMap<>();
+
+ /**
+ * References to components that should be dumped when {@link
+ * #dump(FileDescriptor, PrintWriter, String[])} is called on the service.
+ */
+ @GuardedBy("mDumpables")
+ private final List<Dumpable> mDumpables = new ArrayList<>();
private static TimeZoneDetectorService create(
@NonNull Context context, @NonNull Handler handler,
@NonNull TimeZoneDetectorStrategy timeZoneDetectorStrategy) {
CallerIdentityInjector callerIdentityInjector = CallerIdentityInjector.REAL;
- TimeZoneDetectorService service = new TimeZoneDetectorService(
+ return new TimeZoneDetectorService(
context, handler, callerIdentityInjector, timeZoneDetectorStrategy);
- return service;
}
@VisibleForTesting
@@ -251,7 +259,7 @@
if (!removedListener) {
Slog.w(TAG, "Notified of binder death for who=" + who
+ ", but did not remove any listeners."
- + " mConfigurationListeners=" + mListeners);
+ + " mListeners=" + mListeners);
}
}
}
@@ -314,8 +322,17 @@
boolean isGeoTimeZoneDetectionSupported() {
enforceManageTimeZoneDetectorPermission();
- return ServiceConfigAccessor.getInstance(mContext)
- .isGeoTimeZoneDetectionFeatureSupported();
+ return ServiceConfigAccessor.getInstance(mContext).isGeoTimeZoneDetectionFeatureSupported();
+ }
+
+ /**
+ * Registers the supplied {@link Dumpable} for dumping. When the service is dumped
+ * {@link Dumpable#dump(IndentingPrintWriter, String[])} will be called on the {@code dumpable}.
+ */
+ void addDumpable(@NonNull Dumpable dumpable) {
+ synchronized (mDumpables) {
+ mDumpables.add(dumpable);
+ }
}
@Override
@@ -325,6 +342,13 @@
IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
mTimeZoneDetectorStrategy.dump(ipw, args);
+
+ synchronized (mDumpables) {
+ for (Dumpable dumpable : mDumpables) {
+ dumpable.dump(ipw, args);
+ }
+ }
+
ipw.flush();
}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
index e3f31b6..e2cc679 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
@@ -30,7 +30,7 @@
* Suggestions are acted on or ignored as needed, depending on previously received suggestions and
* the current user's configuration (see {@link ConfigurationInternal}).
*
- * <p>Devices can have zero, one or two automatic time zone detection algorithm available at any
+ * <p>Devices can have zero, one or two automatic time zone detection algorithms available at any
* point in time.
*
* <p>The two automatic detection algorithms supported are "telephony" and "geolocation". Algorithm
@@ -63,6 +63,13 @@
* have an empty suggestion submitted in order to "withdraw" their previous suggestion otherwise it
* will remain in use.
*
+ * <p>The strategy uses only one algorithm at a time and does not attempt consensus even when
+ * more than one is available on a device. This "use only one" behavior is deliberate as different
+ * algorithms have edge cases and blind spots that lead to incorrect answers or uncertainty;
+ * different algorithms aren't guaranteed to agree, and algorithms may frequently lose certainty as
+ * users enter areas without the necessary signals. Ultimately, with no perfect algorithm available,
+ * the user is left to choose which algorithm works best for their circumstances.
+ *
* <p>Threading:
*
* <p>Suggestion calls with a void return type may be handed off to a separate thread and handled
@@ -73,7 +80,7 @@
*
* @hide
*/
-public interface TimeZoneDetectorStrategy extends Dumpable, Dumpable.Container {
+public interface TimeZoneDetectorStrategy extends Dumpable {
/**
* Adds a listener that will be triggered whenever {@link ConfigurationInternal} may have
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
index ab2a88b..1b09f44 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
@@ -98,7 +98,7 @@
}
private static final String LOG_TAG = TimeZoneDetectorService.TAG;
- private static final boolean DBG = false;
+ private static final boolean DBG = TimeZoneDetectorService.DBG;
/**
* The abstract score for an empty or invalid telephony suggestion.
@@ -168,7 +168,7 @@
@GuardedBy("this")
@NonNull
- private List<ConfigurationChangeListener> mConfigChangeListeners = new ArrayList<>();
+ private final List<ConfigurationChangeListener> mConfigChangeListeners = new ArrayList<>();
/**
* A log that records the decisions / decision metadata that affected the device's time zone.
@@ -183,7 +183,7 @@
* to be stable.
*/
@GuardedBy("this")
- private ArrayMapWithHistory<Integer, QualifiedTelephonyTimeZoneSuggestion>
+ private final ArrayMapWithHistory<Integer, QualifiedTelephonyTimeZoneSuggestion>
mTelephonySuggestionsBySlotIndex =
new ArrayMapWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
@@ -192,18 +192,16 @@
* detection then the latest suggestion is cleared.
*/
@GuardedBy("this")
- private ReferenceWithHistory<GeolocationTimeZoneSuggestion> mLatestGeoLocationSuggestion =
+ private final ReferenceWithHistory<GeolocationTimeZoneSuggestion> mLatestGeoLocationSuggestion =
new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
/**
* The latest manual suggestion received.
*/
@GuardedBy("this")
- private ReferenceWithHistory<ManualTimeZoneSuggestion> mLatestManualSuggestion =
+ private final ReferenceWithHistory<ManualTimeZoneSuggestion> mLatestManualSuggestion =
new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
- @GuardedBy("this")
- private final List<Dumpable> mDumpables = new ArrayList<>();
/**
* Creates a new instance of {@link TimeZoneDetectorStrategyImpl}.
@@ -291,16 +289,19 @@
}
Objects.requireNonNull(suggestion);
- if (currentUserConfig.getGeoDetectionEnabledBehavior()) {
- // Only store a geolocation suggestion if geolocation detection is currently enabled.
- // See also clearGeolocationSuggestionIfNeeded().
- mLatestGeoLocationSuggestion.set(suggestion);
+ // Geolocation suggestions may be stored but not used during time zone detection if the
+ // configuration doesn't have geo time zone detection enabled. The caller is expected to
+ // withdraw a previous suggestion (i.e. submit an "uncertain" suggestion, when geo time zone
+ // detection is disabled.
- // Now perform auto time zone detection. The new suggestion may be used to modify the
- // time zone setting.
- String reason = "New geolocation time zone suggested. suggestion=" + suggestion;
- doAutoTimeZoneDetection(currentUserConfig, reason);
- }
+ // The suggestion's "effective from" time is ignored: we currently assume suggestions
+ // are made in a sensible order and the most recent is always the best one to use.
+ mLatestGeoLocationSuggestion.set(suggestion);
+
+ // Now perform auto time zone detection. The new suggestion may be used to modify the
+ // time zone setting.
+ String reason = "New geolocation time zone suggested. suggestion=" + suggestion;
+ doAutoTimeZoneDetection(currentUserConfig, reason);
}
@Override
@@ -365,10 +366,8 @@
// Now perform auto time zone detection. The new suggestion may be used to modify the time
// zone setting.
- if (!currentUserConfig.getGeoDetectionEnabledBehavior()) {
- String reason = "New telephony time zone suggested. suggestion=" + suggestion;
- doAutoTimeZoneDetection(currentUserConfig, reason);
- }
+ String reason = "New telephony time zone suggested. suggestion=" + suggestion;
+ doAutoTimeZoneDetection(currentUserConfig, reason);
}
@Override
@@ -427,7 +426,8 @@
return;
}
- // Use the right suggestions based on the current configuration.
+ // Use the correct algorithm based on the user's current configuration. If it changes, then
+ // detection will be re-run.
if (currentUserConfig.getGeoDetectionEnabledBehavior()) {
doGeolocationTimeZoneDetection(detectionReason);
} else {
@@ -598,15 +598,6 @@
Slog.d(LOG_TAG, "handleConfigChanged()");
}
- clearGeolocationSuggestionIfNeeded();
-
- for (ConfigurationChangeListener listener : mConfigChangeListeners) {
- listener.onChange();
- }
- }
-
- @GuardedBy("this")
- private void clearGeolocationSuggestionIfNeeded() {
// This method is called whenever the user changes or the config for any user changes. We
// don't know what happened, so we capture the current user's config, check to see if we
// need to clear state associated with a previous user, and rerun detection.
@@ -614,24 +605,14 @@
ConfigurationInternal currentUserConfig =
mEnvironment.getConfigurationInternal(currentUserId);
- GeolocationTimeZoneSuggestion latestGeoLocationSuggestion =
- mLatestGeoLocationSuggestion.get();
- if (latestGeoLocationSuggestion != null
- && !currentUserConfig.getGeoDetectionEnabledBehavior()) {
- // The current user's config has geodetection disabled, so clear the latest suggestion.
- // This is done to ensure we only ever keep a geolocation suggestion if the user has
- // said it is ok to do so.
- mLatestGeoLocationSuggestion.set(null);
- mTimeZoneChangesLog.log(
- "clearGeolocationSuggestionIfNeeded: Cleared latest Geolocation suggestion.");
+ // The configuration change may have changed available suggestions or the way suggestions
+ // are used, so re-run detection.
+ doAutoTimeZoneDetection(currentUserConfig, "handleConfigChanged()");
+
+ // Pass on the signal to sub-components.
+ for (ConfigurationChangeListener listener : mConfigChangeListeners) {
+ listener.onChange();
}
-
- doAutoTimeZoneDetection(currentUserConfig, "clearGeolocationSuggestionIfNeeded()");
- }
-
- @Override
- public synchronized void addDumpable(@NonNull Dumpable dumpable) {
- mDumpables.add(dumpable);
}
/**
@@ -671,10 +652,6 @@
mTelephonySuggestionsBySlotIndex.dump(ipw);
ipw.decreaseIndent(); // level 2
ipw.decreaseIndent(); // level 1
-
- for (Dumpable dumpable : mDumpables) {
- dumpable.dump(ipw, args);
- }
}
/**
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
index c5c59ce..942df53 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
@@ -168,7 +168,8 @@
// According to the SystemService docs: All lifecycle methods are called from the system
// server's main looper thread.
void onSystemReady() {
- mServiceConfigAccessor.addListener(this::handleServiceConfigurationChangedOnMainThread);
+ mServiceConfigAccessor.addLocationTimeZoneManagerConfigListener(
+ this::handleServiceConfigurationChangedOnMainThread);
}
private void handleServiceConfigurationChangedOnMainThread() {
diff --git a/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java
index cf212df..8bbac7a 100644
--- a/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java
@@ -18,31 +18,41 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.media.tv.interactive.ITvIAppClient;
import android.media.tv.interactive.ITvIAppManager;
import android.media.tv.interactive.ITvIAppService;
import android.media.tv.interactive.ITvIAppServiceCallback;
import android.media.tv.interactive.ITvIAppSession;
import android.media.tv.interactive.ITvIAppSessionCallback;
+import android.media.tv.interactive.TvIAppInfo;
import android.media.tv.interactive.TvIAppService;
import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.util.ArrayMap;
import android.util.SparseArray;
import android.view.Surface;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.content.PackageMonitor;
import com.android.server.SystemService;
import com.android.server.utils.Slogf;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -82,6 +92,75 @@
mContext = context;
}
+ @GuardedBy("mLock")
+ private void buildTvIAppServiceListLocked(int userId, String[] updatedPackages) {
+ UserState userState = getOrCreateUserStateLocked(userId);
+ userState.mPackageSet.clear();
+
+ if (DEBUG) {
+ Slogf.d(TAG, "buildTvIAppServiceListLocked");
+ }
+ PackageManager pm = mContext.getPackageManager();
+ List<ResolveInfo> services = pm.queryIntentServicesAsUser(
+ new Intent(TvIAppService.SERVICE_INTERFACE),
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
+ userId);
+ List<TvIAppInfo> iAppList = new ArrayList<>();
+
+ for (ResolveInfo ri : services) {
+ ServiceInfo si = ri.serviceInfo;
+ // TODO: add BIND_TV_IAPP permission and check it here
+
+ ComponentName component = new ComponentName(si.packageName, si.name);
+ try {
+ TvIAppInfo info = new TvIAppInfo.Builder(mContext, component).build();
+ iAppList.add(info);
+ } catch (Exception e) {
+ Slogf.e(TAG, "failed to load TV IApp service " + si.name, e);
+ continue;
+ }
+ userState.mPackageSet.add(si.packageName);
+ }
+
+ // sort the iApp list by iApp service id
+ Collections.sort(iAppList, Comparator.comparing(TvIAppInfo::getId));
+ Map<String, TvIAppState> iAppMap = new HashMap<>();
+ ArrayMap<String, Integer> tiasAppCount = new ArrayMap<>(iAppMap.size());
+ for (TvIAppInfo info : iAppList) {
+ String iAppServiceId = info.getId();
+ if (DEBUG) {
+ Slogf.d(TAG, "add " + iAppServiceId);
+ }
+ // Running count of IApp for each IApp service
+ Integer count = tiasAppCount.get(iAppServiceId);
+ count = count == null ? 1 : count + 1;
+ tiasAppCount.put(iAppServiceId, count);
+ TvIAppState iAppState = userState.mIAppMap.get(iAppServiceId);
+ if (iAppState == null) {
+ iAppState = new TvIAppState();
+ }
+ iAppState.mInfo = info;
+ iAppState.mUid = getIAppUid(info);
+ iAppMap.put(iAppServiceId, iAppState);
+ iAppState.mIAppNumber = count;
+ }
+
+ // TODO: notify iApp added / removed
+
+ userState.mIAppMap.clear();
+ userState.mIAppMap = iAppMap;
+ }
+
+ private int getIAppUid(TvIAppInfo info) {
+ try {
+ return getContext().getPackageManager().getApplicationInfo(
+ info.getServiceInfo().packageName, 0).uid;
+ } catch (PackageManager.NameNotFoundException e) {
+ Slogf.w(TAG, "Unable to get UID for " + info, e);
+ return Process.INVALID_UID;
+ }
+ }
+
@Override
public void onStart() {
if (DEBUG) {
@@ -90,6 +169,96 @@
publishBinderService(Context.TV_IAPP_SERVICE, new BinderService());
}
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ registerBroadcastReceivers();
+ } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
+ synchronized (mLock) {
+ buildTvIAppServiceListLocked(mCurrentUserId, null);
+ }
+ }
+ }
+
+ private void registerBroadcastReceivers() {
+ PackageMonitor monitor = new PackageMonitor() {
+ private void buildTvIAppServiceList(String[] packages) {
+ int userId = getChangingUserId();
+ synchronized (mLock) {
+ if (mCurrentUserId == userId || mRunningProfiles.contains(userId)) {
+ buildTvIAppServiceListLocked(userId, packages);
+ }
+ }
+ }
+
+ @Override
+ public void onPackageUpdateFinished(String packageName, int uid) {
+ if (DEBUG) Slogf.d(TAG, "onPackageUpdateFinished(packageName=" + packageName + ")");
+ // This callback is invoked when the TV iApp service is reinstalled.
+ // In this case, isReplacing() always returns true.
+ buildTvIAppServiceList(new String[] { packageName });
+ }
+
+ @Override
+ public void onPackagesAvailable(String[] packages) {
+ if (DEBUG) {
+ Slogf.d(TAG, "onPackagesAvailable(packages=" + Arrays.toString(packages) + ")");
+ }
+ // This callback is invoked when the media on which some packages exist become
+ // available.
+ if (isReplacing()) {
+ buildTvIAppServiceList(packages);
+ }
+ }
+
+ @Override
+ public void onPackagesUnavailable(String[] packages) {
+ // This callback is invoked when the media on which some packages exist become
+ // unavailable.
+ if (DEBUG) {
+ Slogf.d(TAG, "onPackagesUnavailable(packages=" + Arrays.toString(packages)
+ + ")");
+ }
+ if (isReplacing()) {
+ buildTvIAppServiceList(packages);
+ }
+ }
+
+ @Override
+ public void onSomePackagesChanged() {
+ if (DEBUG) Slogf.d(TAG, "onSomePackagesChanged()");
+ if (isReplacing()) {
+ if (DEBUG) Slogf.d(TAG, "Skipped building TV iApp list due to replacing");
+ // When the package is updated, buildTvIAppServiceListLocked is called in other
+ // methods instead.
+ return;
+ }
+ buildTvIAppServiceList(null);
+ }
+
+ @Override
+ public boolean onPackageChanged(String packageName, int uid, String[] components) {
+ // The iApp list needs to be updated in any cases, regardless of whether
+ // it happened to the whole package or a specific component. Returning true so that
+ // the update can be handled in {@link #onSomePackagesChanged}.
+ return true;
+ }
+ };
+ monitor.register(mContext, null, UserHandle.ALL, true);
+
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
+ intentFilter.addAction(Intent.ACTION_USER_REMOVED);
+ intentFilter.addAction(Intent.ACTION_USER_STARTED);
+ intentFilter.addAction(Intent.ACTION_USER_STOPPED);
+ mContext.registerReceiverAsUser(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // TODO: handle switch / start / stop user
+ }
+ }, UserHandle.ALL, intentFilter, null, null);
+ }
+
private SessionState getSessionState(IBinder sessionToken) {
// TODO: implement user state and get session from it.
return null;
@@ -462,19 +631,20 @@
// A mapping from the token of a TV IApp session to its state.
private final Map<IBinder, SessionState> mSessionStateMap = new HashMap<>();
+ // A set of all TV IApp service packages.
+ private final Set<String> mPackageSet = new HashSet<>();
+
private UserState(int userId) {
mUserId = userId;
}
}
private static final class TvIAppState {
- private final String mIAppServiceId;
- private final ComponentName mComponentName;
-
- TvIAppState(String id, ComponentName componentName) {
- mIAppServiceId = id;
- mComponentName = componentName;
- }
+ private String mIAppServiceId;
+ private ComponentName mComponentName;
+ private TvIAppInfo mInfo;
+ private int mUid;
+ private int mIAppNumber;
}
private final class SessionState implements IBinder.DeathRecipient {
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index b1cad7c..318ad06 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -295,6 +295,9 @@
// surface for this token.
if (mSurfaceControl == null) {
createSurfaceControl(true /* force */);
+
+ // Layers could have been assigned before the surface was created, update them again
+ reassignLayer(getSyncTransaction());
}
if (!mChildren.contains(win)) {
ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", win, this);
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 6be872f..0a55003 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -28,7 +28,6 @@
#include <android/hardware/gnss/2.1/IGnssAntennaInfo.h>
#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
#include <android/hardware/gnss/BnGnss.h>
-#include <android/hardware/gnss/BnGnssBatchingCallback.h>
#include <android/hardware/gnss/BnGnssCallback.h>
#include <android/hardware/gnss/BnGnssMeasurementCallback.h>
#include <android/hardware/gnss/BnGnssPowerIndicationCallback.h>
@@ -52,6 +51,7 @@
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/Log.h"
#include "gnss/GnssAntennaInfoCallback.h"
+#include "gnss/GnssBatching.h"
#include "gnss/GnssConfiguration.h"
#include "gnss/GnssMeasurement.h"
#include "gnss/Utils.h"
@@ -60,12 +60,9 @@
#include "utils/Log.h"
#include "utils/misc.h"
-static jclass class_location;
static jclass class_gnssNavigationMessage;
static jclass class_gnssPowerStats;
-jobject android::mCallbacksObj = nullptr;
-
static jmethodID method_reportLocation;
static jmethodID method_reportStatus;
static jmethodID method_reportSvStatus;
@@ -87,7 +84,6 @@
static jmethodID method_reportGeofencePauseStatus;
static jmethodID method_reportGeofenceResumeStatus;
static jmethodID method_reportNavigationMessages;
-static jmethodID method_reportLocationBatch;
static jmethodID method_reportGnssServiceDied;
static jmethodID method_reportGnssPowerStats;
static jmethodID method_setSubHalMeasurementCorrectionsCapabilities;
@@ -117,7 +113,6 @@
static jmethodID method_correctionPlaneAzimDeg;
static jmethodID method_reportNfwNotification;
static jmethodID method_isInEmergencySession;
-static jmethodID method_locationCtor;
static jmethodID method_gnssNavigationMessageCtor;
static jmethodID method_gnssPowerStatsCtor;
static jmethodID method_setSubHalPowerIndicationCapabilities;
@@ -179,10 +174,6 @@
using IAGnss_V2_0 = android::hardware::gnss::V2_0::IAGnss;
using IAGnssCallback_V1_0 = android::hardware::gnss::V1_0::IAGnssCallback;
using IAGnssCallback_V2_0 = android::hardware::gnss::V2_0::IAGnssCallback;
-using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching;
-using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching;
-using IGnssBatchingCallback_V1_0 = android::hardware::gnss::V1_0::IGnssBatchingCallback;
-using IGnssBatchingCallback_V2_0 = android::hardware::gnss::V2_0::IGnssBatchingCallback;
using IMeasurementCorrections_V1_0 = android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
using IMeasurementCorrections_V1_1 = android::hardware::gnss::measurement_corrections::V1_1::IMeasurementCorrections;
@@ -199,8 +190,6 @@
using android::hardware::gnss::IGnssPowerIndicationCallback;
using android::hardware::gnss::PsdsType;
using IGnssAidl = android::hardware::gnss::IGnss;
-using IGnssBatchingAidl = android::hardware::gnss::IGnssBatching;
-using IGnssBatchingCallbackAidl = android::hardware::gnss::IGnssBatchingCallback;
using IGnssCallbackAidl = android::hardware::gnss::IGnssCallback;
using IGnssPsdsAidl = android::hardware::gnss::IGnssPsds;
using IGnssPsdsCallbackAidl = android::hardware::gnss::IGnssPsdsCallback;
@@ -227,7 +216,6 @@
sp<IGnss_V2_0> gnssHal_V2_0 = nullptr;
sp<IGnss_V2_1> gnssHal_V2_1 = nullptr;
sp<IGnssAidl> gnssHalAidl = nullptr;
-sp<IGnssBatchingAidl> gnssBatchingAidlIface = nullptr;
sp<IGnssPsdsAidl> gnssPsdsAidlIface = nullptr;
sp<IGnssXtra> gnssXtraIface = nullptr;
sp<IAGnssRil_V1_0> agnssRilIface = nullptr;
@@ -235,8 +223,6 @@
sp<IGnssGeofencing> gnssGeofencingIface = nullptr;
sp<IAGnss_V1_0> agnssIface = nullptr;
sp<IAGnss_V2_0> agnssIface_V2_0 = nullptr;
-sp<IGnssBatching_V1_0> gnssBatchingIface = nullptr;
-sp<IGnssBatching_V2_0> gnssBatchingIface_V2_0 = nullptr;
sp<IGnssDebug_V1_0> gnssDebugIface = nullptr;
sp<IGnssDebug_V2_0> gnssDebugIface_V2_0 = nullptr;
sp<IGnssNi> gnssNiIface = nullptr;
@@ -249,6 +235,7 @@
std::unique_ptr<GnssConfigurationInterface> gnssConfigurationIface = nullptr;
std::unique_ptr<android::gnss::GnssMeasurementInterface> gnssMeasurementIface = nullptr;
+std::unique_ptr<android::gnss::GnssBatchingInterface> gnssBatchingIface = nullptr;
#define WAKE_LOCK_NAME "GPS"
@@ -301,103 +288,6 @@
const char* mNativeString;
};
-static jobject translateGnssLocation(JNIEnv* env, const GnssLocationAidl& location) {
- JavaObject object(env, class_location, method_locationCtor, "gps");
-
- uint32_t flags = static_cast<uint32_t>(location.gnssLocationFlags);
- if (flags & GnssLocationAidl::HAS_LAT_LONG) {
- SET(Latitude, location.latitudeDegrees);
- SET(Longitude, location.longitudeDegrees);
- }
- if (flags & GnssLocationAidl::HAS_ALTITUDE) {
- SET(Altitude, location.altitudeMeters);
- }
- if (flags & GnssLocationAidl::HAS_SPEED) {
- SET(Speed, (float)location.speedMetersPerSec);
- }
- if (flags & GnssLocationAidl::HAS_BEARING) {
- SET(Bearing, (float)location.bearingDegrees);
- }
- if (flags & GnssLocationAidl::HAS_HORIZONTAL_ACCURACY) {
- SET(Accuracy, (float)location.horizontalAccuracyMeters);
- }
- if (flags & GnssLocationAidl::HAS_VERTICAL_ACCURACY) {
- SET(VerticalAccuracyMeters, (float)location.verticalAccuracyMeters);
- }
- if (flags & GnssLocationAidl::HAS_SPEED_ACCURACY) {
- SET(SpeedAccuracyMetersPerSecond, (float)location.speedAccuracyMetersPerSecond);
- }
- if (flags & GnssLocationAidl::HAS_BEARING_ACCURACY) {
- SET(BearingAccuracyDegrees, (float)location.bearingAccuracyDegrees);
- }
- SET(Time, location.timestampMillis);
-
- flags = static_cast<uint32_t>(location.elapsedRealtime.flags);
- if (flags & android::hardware::gnss::ElapsedRealtime::HAS_TIMESTAMP_NS) {
- SET(ElapsedRealtimeNanos, location.elapsedRealtime.timestampNs);
- }
- if (flags & android::hardware::gnss::ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS) {
- SET(ElapsedRealtimeUncertaintyNanos,
- static_cast<double>(location.elapsedRealtime.timeUncertaintyNs));
- }
-
- return object.get();
-}
-
-static jobject translateGnssLocation(JNIEnv* env,
- const GnssLocation_V1_0& location) {
- JavaObject object(env, class_location, method_locationCtor, "gps");
-
- uint16_t flags = static_cast<uint16_t>(location.gnssLocationFlags);
- if (flags & GnssLocationFlags::HAS_LAT_LONG) {
- SET(Latitude, location.latitudeDegrees);
- SET(Longitude, location.longitudeDegrees);
- }
- if (flags & GnssLocationFlags::HAS_ALTITUDE) {
- SET(Altitude, location.altitudeMeters);
- }
- if (flags & GnssLocationFlags::HAS_SPEED) {
- SET(Speed, location.speedMetersPerSec);
- }
- if (flags & GnssLocationFlags::HAS_BEARING) {
- SET(Bearing, location.bearingDegrees);
- }
- if (flags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
- SET(Accuracy, location.horizontalAccuracyMeters);
- }
- if (flags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
- SET(VerticalAccuracyMeters, location.verticalAccuracyMeters);
- }
- if (flags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
- SET(SpeedAccuracyMetersPerSecond, location.speedAccuracyMetersPerSecond);
- }
- if (flags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
- SET(BearingAccuracyDegrees, location.bearingAccuracyDegrees);
- }
- SET(Time, location.timestamp);
- SET(ElapsedRealtimeNanos, android::elapsedRealtimeNano());
-
- return object.get();
-}
-
-static jobject translateGnssLocation(JNIEnv* env,
- const GnssLocation_V2_0& location) {
- JavaObject object(env, class_location, translateGnssLocation(env, location.v1_0));
-
- const uint16_t flags = static_cast<uint16_t>(location.elapsedRealtime.flags);
-
- // Overwrite ElapsedRealtimeNanos when available from HAL.
- if (flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
- SET(ElapsedRealtimeNanos, location.elapsedRealtime.timestampNs);
- }
-
- if (flags & ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) {
- SET(ElapsedRealtimeUncertaintyNanos, static_cast<double>(location.elapsedRealtime.timeUncertaintyNs));
- }
-
- return object.get();
-}
-
static GnssLocation_V1_0 createGnssLocation_V1_0(
jint gnssLocationFlags, jdouble latitudeDegrees, jdouble longitudeDegrees,
jdouble altitudeMeters, jfloat speedMetersPerSec, jfloat bearingDegrees,
@@ -1219,66 +1109,6 @@
return Void();
}
-struct GnssBatchingCallbackUtil {
- template<class T>
- static Return<void> gnssLocationBatchCbImpl(const hidl_vec<T>& locations);
-private:
- GnssBatchingCallbackUtil() = delete;
-};
-
-template<class T>
-Return<void> GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(const hidl_vec<T>& locations) {
- JNIEnv* env = getJniEnv();
-
- jobjectArray jLocations = env->NewObjectArray(locations.size(), class_location, nullptr);
-
- for (uint16_t i = 0; i < locations.size(); ++i) {
- jobject jLocation = translateGnssLocation(env, locations[i]);
- env->SetObjectArrayElement(jLocations, i, jLocation);
- env->DeleteLocalRef(jLocation);
- }
-
- env->CallVoidMethod(mCallbacksObj, method_reportLocationBatch, jLocations);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
-
- env->DeleteLocalRef(jLocations);
-
- return Void();
-}
-
-/*
- * GnssBatchingCallbackAidl class implements the callback methods required by the
- * android::hardware::gnss::IGnssBatching interface.
- */
-struct GnssBatchingCallbackAidl : public android::hardware::gnss::BnGnssBatchingCallback {
- Status gnssLocationBatchCb(const std::vector<GnssLocationAidl>& locations) {
- GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(hidl_vec<GnssLocationAidl>(locations));
- return Status::ok();
- }
-};
-
-/*
- * GnssBatchingCallback_V1_0 class implements the callback methods required by the
- * IGnssBatching 1.0 interface.
- */
-struct GnssBatchingCallback_V1_0 : public IGnssBatchingCallback_V1_0 {
- /** Methods from ::android::hardware::gps::V1_0::IGnssBatchingCallback follow. */
- Return<void> gnssLocationBatchCb(const hidl_vec<GnssLocation_V1_0>& locations) override {
- return GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(locations);
- }
-};
-
-/*
- * GnssBatchingCallback_V2_0 class implements the callback methods required by the
- * IGnssBatching 2.0 interface.
- */
-struct GnssBatchingCallback_V2_0 : public IGnssBatchingCallback_V2_0 {
- /** Methods from ::android::hardware::gps::V2_0::IGnssBatchingCallback follow. */
- Return<void> gnssLocationBatchCb(const hidl_vec<GnssLocation_V2_0>& locations) override {
- return GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(locations);
- }
-};
-
/* Initializes the GNSS service handle. */
static void android_location_gnss_hal_GnssNative_set_gps_service_handle() {
gnssHalAidl = waitForVintfService<IGnssAidl>();
@@ -1354,10 +1184,6 @@
clazz,
"reportNavigationMessage",
"(Landroid/location/GnssNavigationMessage;)V");
- method_reportLocationBatch = env->GetMethodID(
- clazz,
- "reportLocationBatch",
- "([Landroid/location/Location;)V");
method_reportGnssServiceDied = env->GetMethodID(clazz, "reportGnssServiceDied", "()V");
method_reportNfwNotification = env->GetMethodID(clazz, "reportNfwNotification",
"(Ljava/lang/String;BLjava/lang/String;BLjava/lang/String;BZZ)V");
@@ -1427,17 +1253,15 @@
class_gnssPowerStats = (jclass)env->NewGlobalRef(gnssPowerStatsClass);
method_gnssPowerStatsCtor = env->GetMethodID(class_gnssPowerStats, "<init>", "(IJDDDDDD[D)V");
- jclass locationClass = env->FindClass("android/location/Location");
- class_location = (jclass) env->NewGlobalRef(locationClass);
- method_locationCtor = env->GetMethodID(class_location, "<init>", "(Ljava/lang/String;)V");
-
jclass gnssNavigationMessageClass = env->FindClass("android/location/GnssNavigationMessage");
class_gnssNavigationMessage = (jclass) env->NewGlobalRef(gnssNavigationMessageClass);
method_gnssNavigationMessageCtor = env->GetMethodID(class_gnssNavigationMessage, "<init>", "()V");
+ gnss::GnssAntennaInfo_class_init_once(env, clazz);
+ gnss::GnssBatching_class_init_once(env, clazz);
gnss::GnssConfiguration_class_init_once(env);
gnss::GnssMeasurement_class_init_once(env, clazz);
- gnss::GnssAntennaInfo_class_init_once(env, clazz);
+ gnss::Utils_class_init_once(env);
}
/* Initialization needed at system boot and whenever GNSS service dies. */
@@ -1672,25 +1496,21 @@
}
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
- sp<IGnssBatchingAidl> gnssBatchingAidl;
+ sp<android::hardware::gnss::IGnssBatching> gnssBatchingAidl;
auto status = gnssHalAidl->getExtensionGnssBatching(&gnssBatchingAidl);
if (checkAidlStatus(status, "Unable to get a handle to GnssBatching interface.")) {
- gnssBatchingAidlIface = gnssBatchingAidl;
+ gnssBatchingIface = std::make_unique<gnss::GnssBatching>(gnssBatchingAidl);
}
} else if (gnssHal_V2_0 != nullptr) {
auto gnssBatching_V2_0 = gnssHal_V2_0->getExtensionGnssBatching_2_0();
- if (!gnssBatching_V2_0.isOk()) {
- ALOGD("Unable to get a handle to GnssBatching_V2_0");
- } else {
- gnssBatchingIface_V2_0 = gnssBatching_V2_0;
+ if (checkHidlReturn(gnssBatching_V2_0, "Unable to get a handle to GnssBatching_V2_0")) {
+ gnssBatchingIface = std::make_unique<gnss::GnssBatching_V2_0>(gnssBatching_V2_0);
}
}
- if (gnssBatchingIface_V2_0 == nullptr ) {
+ if (gnssBatchingIface == nullptr) {
auto gnssBatching_V1_0 = gnssHal->getExtensionGnssBatching();
- if (!gnssBatching_V1_0.isOk()) {
- ALOGD("Unable to get a handle to GnssBatching");
- } else {
- gnssBatchingIface = gnssBatching_V1_0;
+ if (checkHidlReturn(gnssBatching_V1_0, "Unable to get a handle to GnssBatching")) {
+ gnssBatchingIface = std::make_unique<gnss::GnssBatching_V1_0>(gnssBatching_V1_0);
}
}
@@ -2786,92 +2606,46 @@
}
static jint android_location_gnss_hal_GnssNative_get_batch_size(JNIEnv*) {
- if (gnssBatchingAidlIface != nullptr) {
- int size = 0;
- auto status = gnssBatchingAidlIface->getBatchSize(&size);
- if (!checkAidlStatus(status, "IGnssBatchingAidl getBatchSize() failed")) {
- return 0;
- }
- return size;
- } else if (gnssBatchingIface != nullptr) {
- auto result = gnssBatchingIface->getBatchSize();
- if (!checkHidlReturn(result, "IGnssBatching getBatchSize() failed.")) {
- return 0; // failure in binder, don't support batching
- }
- return static_cast<jint>(result);
+ if (gnssBatchingIface == nullptr) {
+ return 0; // batching not supported, size = 0
}
- return 0; // batching not supported, size = 0
+ return gnssBatchingIface->getBatchSize();
}
static jboolean android_location_gnss_hal_GnssNative_init_batching(JNIEnv*, jclass) {
- if (gnssBatchingAidlIface != nullptr) {
- sp<IGnssBatchingCallbackAidl> gnssBatchingCbIface = new GnssBatchingCallbackAidl();
- auto status = gnssBatchingAidlIface->init(gnssBatchingCbIface);
- return checkAidlStatus(status, "IGnssBatchingAidl init() failed.");
- } else if (gnssBatchingIface_V2_0 != nullptr) {
- sp<IGnssBatchingCallback_V2_0> gnssBatchingCbIface_V2_0 = new GnssBatchingCallback_V2_0();
- auto result = gnssBatchingIface_V2_0->init_2_0(gnssBatchingCbIface_V2_0);
- return checkHidlReturn(result, "IGnssBatching init_2_0() failed.");
- } else if (gnssBatchingIface != nullptr) {
- sp<IGnssBatchingCallback_V1_0> gnssBatchingCbIface_V1_0 = new GnssBatchingCallback_V1_0();
- auto result = gnssBatchingIface->init(gnssBatchingCbIface_V1_0);
- return checkHidlReturn(result, "IGnssBatching init() failed.");
- } else {
+ if (gnssBatchingIface == nullptr) {
return JNI_FALSE; // batching not supported
}
+ return gnssBatchingIface->init(std::make_unique<gnss::GnssBatchingCallback>());
}
static void android_location_gnss_hal_GnssNative_cleanup_batching(JNIEnv*, jclass) {
- if (gnssBatchingAidlIface != nullptr) {
- auto status = gnssBatchingAidlIface->cleanup();
- checkAidlStatus(status, "IGnssBatchingAidl cleanup() failed");
- } else if (gnssBatchingIface != nullptr) {
- auto result = gnssBatchingIface->cleanup();
- checkHidlReturn(result, "IGnssBatching cleanup() failed.");
+ if (gnssBatchingIface == nullptr) {
+ return; // batching not supported
}
- return;
+ gnssBatchingIface->cleanup();
}
static jboolean android_location_gnss_hal_GnssNative_start_batch(JNIEnv*, jclass, jlong periodNanos,
jboolean wakeOnFifoFull) {
- IGnssBatching_V1_0::Options options;
- options.periodNanos = periodNanos;
- if (wakeOnFifoFull) {
- options.flags = static_cast<uint8_t>(IGnssBatching_V1_0::Flag::WAKEUP_ON_FIFO_FULL);
- } else {
- options.flags = 0;
+ if (gnssBatchingIface == nullptr) {
+ return JNI_FALSE; // batching not supported
}
-
- if (gnssBatchingAidlIface != nullptr) {
- auto status = gnssBatchingAidlIface->start(periodNanos, (int)options.flags);
- return checkAidlStatus(status, "IGnssBatchingAidl start() failed.");
- } else if (gnssBatchingIface != nullptr) {
- auto result = gnssBatchingIface->start(options);
- return checkHidlReturn(result, "IGnssBatching start() failed.");
- }
- return JNI_FALSE; // batching not supported
+ return gnssBatchingIface->start(periodNanos, wakeOnFifoFull);
}
static void android_location_gnss_hal_GnssNative_flush_batch(JNIEnv*, jclass) {
- if (gnssBatchingAidlIface != nullptr) {
- auto status = gnssBatchingAidlIface->flush();
- checkAidlStatus(status, "IGnssBatchingAidl flush() failed.");
- } else if (gnssBatchingIface != nullptr) {
- auto result = gnssBatchingIface->flush();
- checkHidlReturn(result, "IGnssBatching flush() failed.");
+ if (gnssBatchingIface == nullptr) {
+ return; // batching not supported
}
- return;
+ gnssBatchingIface->flush();
}
static jboolean android_location_gnss_hal_GnssNative_stop_batch(JNIEnv*, jclass) {
- if (gnssBatchingAidlIface != nullptr) {
- auto status = gnssBatchingAidlIface->stop();
- return checkAidlStatus(status, "IGnssBatchingAidl stop() failed.");
- } else if (gnssBatchingIface != nullptr) {
- auto result = gnssBatchingIface->stop();
- return checkHidlReturn(result, "IGnssBatching stop() failed.");
+ if (gnssBatchingIface == nullptr) {
+ return JNI_FALSE; // batching not supported
}
- return JNI_FALSE; // batching not supported
+ return gnssBatchingIface->stop();
}
static jboolean android_location_GnssVisibilityControl_enable_nfw_location_access(
diff --git a/services/core/jni/gnss/Android.bp b/services/core/jni/gnss/Android.bp
index 9085fa7..090166a 100644
--- a/services/core/jni/gnss/Android.bp
+++ b/services/core/jni/gnss/Android.bp
@@ -24,6 +24,8 @@
srcs: [
"GnssAntennaInfoCallback.cpp",
+ "GnssBatching.cpp",
+ "GnssBatchingCallback.cpp",
"GnssConfiguration.cpp",
"GnssMeasurement.cpp",
"GnssMeasurementCallback.cpp",
diff --git a/services/core/jni/gnss/GnssBatching.cpp b/services/core/jni/gnss/GnssBatching.cpp
new file mode 100644
index 0000000..b66bf21
--- /dev/null
+++ b/services/core/jni/gnss/GnssBatching.cpp
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+// Define LOG_TAG before <log/log.h> to overwrite the default value.
+#define LOG_TAG "GnssBatchingJni"
+
+#include "GnssBatching.h"
+
+#include "Utils.h"
+
+using android::hardware::gnss::IGnssBatching;
+using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching;
+using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching;
+
+namespace android::gnss {
+
+// Implementation of GnssBatching (AIDL HAL)
+
+GnssBatching::GnssBatching(const sp<IGnssBatching>& iGnssBatching) : mIGnssBatching(iGnssBatching) {
+ assert(mIGnssBatching != nullptr);
+}
+
+jboolean GnssBatching::init(const std::unique_ptr<GnssBatchingCallback>& callback) {
+ auto status = mIGnssBatching->init(callback->getAidl());
+ return checkAidlStatus(status, "IGnssBatchingAidl init() failed.");
+}
+
+jint GnssBatching::getBatchSize() {
+ int size = 0;
+ auto status = mIGnssBatching->getBatchSize(&size);
+ if (!checkAidlStatus(status, "IGnssBatchingAidl getBatchSize() failed")) {
+ return 0;
+ }
+ return size;
+}
+
+jboolean GnssBatching::start(long periodNanos, bool wakeOnFifoFull) {
+ int flags = (wakeOnFifoFull) ? IGnssBatching::WAKEUP_ON_FIFO_FULL : 0;
+ auto status = mIGnssBatching->start(periodNanos, flags);
+ return checkAidlStatus(status, "IGnssBatchingAidl start() failed.");
+}
+
+jboolean GnssBatching::stop() {
+ auto status = mIGnssBatching->stop();
+ return checkAidlStatus(status, "IGnssBatchingAidl stop() failed.");
+}
+
+jboolean GnssBatching::flush() {
+ auto status = mIGnssBatching->flush();
+ return checkAidlStatus(status, "IGnssBatchingAidl flush() failed.");
+}
+
+jboolean GnssBatching::cleanup() {
+ auto status = mIGnssBatching->cleanup();
+ return checkAidlStatus(status, "IGnssBatchingAidl cleanup() failed");
+}
+
+// Implementation of GnssBatching_V1_0
+
+GnssBatching_V1_0::GnssBatching_V1_0(const sp<IGnssBatching_V1_0>& iGnssBatching)
+ : mIGnssBatching_V1_0(iGnssBatching) {
+ assert(mIGnssBatching_V1_0 != nullptr);
+}
+
+jboolean GnssBatching_V1_0::init(const std::unique_ptr<GnssBatchingCallback>& callback) {
+ auto result = mIGnssBatching_V1_0->init(callback->getV1_0());
+ return checkHidlReturn(result, "IGnssBatching_V1_0 init() failed.");
+}
+
+jint GnssBatching_V1_0::getBatchSize() {
+ auto result = mIGnssBatching_V1_0->getBatchSize();
+ if (!checkHidlReturn(result, "IGnssBatching getBatchSize() failed.")) {
+ return 0; // failure in binder, don't support batching
+ }
+ return static_cast<jint>(result);
+}
+
+jboolean GnssBatching_V1_0::start(long periodNanos, bool wakeOnFifoFull) {
+ IGnssBatching_V1_0::Options options;
+ options.periodNanos = periodNanos;
+ if (wakeOnFifoFull) {
+ options.flags = static_cast<uint8_t>(IGnssBatching_V1_0::Flag::WAKEUP_ON_FIFO_FULL);
+ } else {
+ options.flags = 0;
+ }
+
+ auto result = mIGnssBatching_V1_0->start(options);
+ return checkHidlReturn(result, "IGnssBatching start() failed.");
+}
+
+jboolean GnssBatching_V1_0::stop() {
+ auto result = mIGnssBatching_V1_0->stop();
+ return checkHidlReturn(result, "IGnssBatching stop() failed.");
+}
+
+jboolean GnssBatching_V1_0::flush() {
+ auto result = mIGnssBatching_V1_0->flush();
+ return checkHidlReturn(result, "IGnssBatching flush() failed.");
+}
+
+jboolean GnssBatching_V1_0::cleanup() {
+ auto result = mIGnssBatching_V1_0->cleanup();
+ return checkHidlReturn(result, "IGnssBatching cleanup() failed.");
+}
+
+// Implementation of GnssBatching_V2_0
+
+GnssBatching_V2_0::GnssBatching_V2_0(const sp<IGnssBatching_V2_0>& iGnssBatching)
+ : GnssBatching_V1_0{iGnssBatching}, mIGnssBatching_V2_0(iGnssBatching) {
+ assert(mIGnssBatching_V2_0 != nullptr);
+}
+
+jboolean GnssBatching_V2_0::init(const std::unique_ptr<GnssBatchingCallback>& callback) {
+ auto result = mIGnssBatching_V2_0->init_2_0(callback->getV2_0());
+ return checkHidlReturn(result, "IGnssBatching_V2_0 init() failed.");
+}
+
+} // namespace android::gnss
diff --git a/services/core/jni/gnss/GnssBatching.h b/services/core/jni/gnss/GnssBatching.h
new file mode 100644
index 0000000..a98ca9b
--- /dev/null
+++ b/services/core/jni/gnss/GnssBatching.h
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_SERVER_GNSS_GNSSBATCHING_H
+#define _ANDROID_SERVER_GNSS_GNSSBATCHING_H
+
+#pragma once
+
+#ifndef LOG_TAG
+#error LOG_TAG must be defined before including this file.
+#endif
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <android/hardware/gnss/2.0/IGnssBatching.h>
+#include <android/hardware/gnss/BnGnssBatching.h>
+#include <log/log.h>
+
+#include "GnssBatchingCallback.h"
+#include "jni.h"
+
+namespace android::gnss {
+
+class GnssBatchingInterface {
+public:
+ virtual ~GnssBatchingInterface() {}
+ virtual jboolean init(const std::unique_ptr<GnssBatchingCallback>& callback) = 0;
+ virtual jint getBatchSize() = 0;
+ virtual jboolean start(long periodNanos, bool wakeupOnFifoFull) = 0;
+ virtual jboolean stop() = 0;
+ virtual jboolean flush() = 0;
+ virtual jboolean cleanup() = 0;
+};
+
+class GnssBatching : public GnssBatchingInterface {
+public:
+ GnssBatching(const sp<android::hardware::gnss::IGnssBatching>& iGnssBatching);
+ jboolean init(const std::unique_ptr<GnssBatchingCallback>& callback) override;
+ jint getBatchSize() override;
+ jboolean start(long periodNanos, bool wakeupOnFifoFull) override;
+ jboolean stop() override;
+ jboolean flush() override;
+ jboolean cleanup() override;
+
+private:
+ const sp<android::hardware::gnss::IGnssBatching> mIGnssBatching;
+};
+
+class GnssBatching_V1_0 : public GnssBatchingInterface {
+public:
+ GnssBatching_V1_0(const sp<android::hardware::gnss::V1_0::IGnssBatching>& iGnssBatching);
+ jboolean init(const std::unique_ptr<GnssBatchingCallback>& callback) override;
+ jint getBatchSize() override;
+ jboolean start(long periodNanos, bool wakeupOnFifoFull) override;
+ jboolean stop() override;
+ jboolean flush() override;
+ jboolean cleanup() override;
+
+private:
+ const sp<android::hardware::gnss::V1_0::IGnssBatching> mIGnssBatching_V1_0;
+};
+
+class GnssBatching_V2_0 : public GnssBatching_V1_0 {
+public:
+ GnssBatching_V2_0(const sp<android::hardware::gnss::V2_0::IGnssBatching>& iGnssBatching);
+ jboolean init(const std::unique_ptr<GnssBatchingCallback>& callback) override;
+
+private:
+ const sp<android::hardware::gnss::V2_0::IGnssBatching> mIGnssBatching_V2_0;
+};
+
+} // namespace android::gnss
+
+#endif // _ANDROID_SERVER_GNSS_GNSSBATCHING_H
diff --git a/services/core/jni/gnss/GnssBatchingCallback.cpp b/services/core/jni/gnss/GnssBatchingCallback.cpp
new file mode 100644
index 0000000..d2a5547
--- /dev/null
+++ b/services/core/jni/gnss/GnssBatchingCallback.cpp
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "GnssBatchingCbJni"
+
+#include "GnssBatchingCallback.h"
+
+namespace android::gnss {
+
+namespace {
+
+jmethodID method_reportLocationBatch;
+
+} // anonymous namespace
+
+using android::hardware::hidl_vec;
+using binder::Status;
+using hardware::Return;
+
+using GnssLocationAidl = android::hardware::gnss::GnssLocation;
+using GnssLocation_V1_0 = android::hardware::gnss::V1_0::GnssLocation;
+using GnssLocation_V2_0 = android::hardware::gnss::V2_0::GnssLocation;
+
+void GnssBatching_class_init_once(JNIEnv* env, jclass clazz) {
+ method_reportLocationBatch =
+ env->GetMethodID(clazz, "reportLocationBatch", "([Landroid/location/Location;)V");
+}
+
+Status GnssBatchingCallbackAidl::gnssLocationBatchCb(
+ const std::vector<android::hardware::gnss::GnssLocation>& locations) {
+ GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(hidl_vec<GnssLocationAidl>(locations));
+ return Status::ok();
+}
+
+Return<void> GnssBatchingCallback_V1_0::gnssLocationBatchCb(
+ const hidl_vec<GnssLocation_V1_0>& locations) {
+ return GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(locations);
+}
+
+Return<void> GnssBatchingCallback_V2_0::gnssLocationBatchCb(
+ const hidl_vec<GnssLocation_V2_0>& locations) {
+ return GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(locations);
+}
+
+} // namespace android::gnss
diff --git a/services/core/jni/gnss/GnssBatchingCallback.h b/services/core/jni/gnss/GnssBatchingCallback.h
new file mode 100644
index 0000000..a9dd4304
--- /dev/null
+++ b/services/core/jni/gnss/GnssBatchingCallback.h
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_SERVER_GNSS_GNSSBATCHCALLBACK_H
+#define _ANDROID_SERVER_GNSS_GNSSBATCHCALLBACK_H
+
+#pragma once
+
+#ifndef LOG_TAG
+#error LOG_TAG must be defined before including this file.
+#endif
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <android/hardware/gnss/2.0/IGnssBatching.h>
+#include <android/hardware/gnss/BnGnssBatchingCallback.h>
+#include <log/log.h>
+
+#include <vector>
+
+#include "Utils.h"
+#include "jni.h"
+
+namespace android::gnss {
+
+namespace {
+
+extern jmethodID method_reportLocationBatch;
+
+} // anonymous namespace
+
+void GnssBatching_class_init_once(JNIEnv* env, jclass clazz);
+
+class GnssBatchingCallbackAidl : public hardware::gnss::BnGnssBatchingCallback {
+public:
+ GnssBatchingCallbackAidl() {}
+ android::binder::Status gnssLocationBatchCb(
+ const std::vector<android::hardware::gnss::GnssLocation>& locations) override;
+};
+
+class GnssBatchingCallback_V1_0 : public hardware::gnss::V1_0::IGnssBatchingCallback {
+public:
+ GnssBatchingCallback_V1_0() {}
+ hardware::Return<void> gnssLocationBatchCb(
+ const hardware::hidl_vec<hardware::gnss::V1_0::GnssLocation>& locations) override;
+};
+
+class GnssBatchingCallback_V2_0 : public hardware::gnss::V2_0::IGnssBatchingCallback {
+public:
+ GnssBatchingCallback_V2_0() {}
+ hardware::Return<void> gnssLocationBatchCb(
+ const hardware::hidl_vec<hardware::gnss::V2_0::GnssLocation>& locations) override;
+};
+
+class GnssBatchingCallback {
+public:
+ GnssBatchingCallback() {}
+ sp<GnssBatchingCallbackAidl> getAidl() {
+ if (callbackAidl == nullptr) {
+ callbackAidl = sp<GnssBatchingCallbackAidl>::make();
+ }
+ return callbackAidl;
+ }
+
+ sp<GnssBatchingCallback_V1_0> getV1_0() {
+ if (callbackV1_0 == nullptr) {
+ callbackV1_0 = sp<GnssBatchingCallback_V1_0>::make();
+ }
+ return callbackV1_0;
+ }
+
+ sp<GnssBatchingCallback_V2_0> getV2_0() {
+ if (callbackV2_0 == nullptr) {
+ callbackV2_0 = sp<GnssBatchingCallback_V2_0>::make();
+ }
+ return callbackV2_0;
+ }
+
+private:
+ sp<GnssBatchingCallbackAidl> callbackAidl;
+ sp<GnssBatchingCallback_V1_0> callbackV1_0;
+ sp<GnssBatchingCallback_V2_0> callbackV2_0;
+};
+
+struct GnssBatchingCallbackUtil {
+ template <class T>
+ static hardware::Return<void> gnssLocationBatchCbImpl(const hardware::hidl_vec<T>& locations);
+
+private:
+ GnssBatchingCallbackUtil() = delete;
+};
+
+template <class T>
+hardware::Return<void> GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(
+ const hardware::hidl_vec<T>& locations) {
+ JNIEnv* env = getJniEnv();
+
+ jobjectArray jLocations = env->NewObjectArray(locations.size(), class_location, nullptr);
+
+ for (uint16_t i = 0; i < locations.size(); ++i) {
+ jobject jLocation = translateGnssLocation(env, locations[i]);
+ env->SetObjectArrayElement(jLocations, i, jLocation);
+ env->DeleteLocalRef(jLocation);
+ }
+
+ env->CallVoidMethod(android::getCallbacksObj(), method_reportLocationBatch, jLocations);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+
+ env->DeleteLocalRef(jLocations);
+
+ return hardware::Void();
+}
+
+} // namespace android::gnss
+
+#endif // _ANDROID_SERVER_GNSS_GNSSBATCHCALLBACK_H
\ No newline at end of file
diff --git a/services/core/jni/gnss/Utils.cpp b/services/core/jni/gnss/Utils.cpp
index 8cbdfb8..40a94ce 100644
--- a/services/core/jni/gnss/Utils.cpp
+++ b/services/core/jni/gnss/Utils.cpp
@@ -18,6 +18,9 @@
#include "Utils.h"
+#include <android/hardware/gnss/1.0/IGnss.h>
+#include <android/hardware/gnss/2.0/IGnss.h>
+#include <utils/SystemClock.h>
/*
* Save a pointer to JavaVm to attach/detach threads executing
* callback methods that need to make JNI calls.
@@ -29,9 +32,29 @@
namespace {
thread_local std::unique_ptr<ScopedJniThreadAttach> tJniThreadAttacher;
+jmethodID method_locationCtor;
} // anonymous namespace
+jclass class_location;
+
+namespace gnss {
+void Utils_class_init_once(JNIEnv* env) {
+ jclass locationClass = env->FindClass("android/location/Location");
+ class_location = (jclass)env->NewGlobalRef(locationClass);
+ method_locationCtor = env->GetMethodID(class_location, "<init>", "(Ljava/lang/String;)V");
+}
+} // namespace gnss
+
+jobject mCallbacksObj = nullptr;
+
+jobject& getCallbacksObj() {
+ return mCallbacksObj;
+}
+
+using GnssLocation_V1_0 = android::hardware::gnss::V1_0::GnssLocation;
+using GnssLocation_V2_0 = android::hardware::gnss::V2_0::GnssLocation;
+
// Define Java method signatures for all known types.
template <>
const char* const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
@@ -130,4 +153,103 @@
return env;
}
+template <>
+jobject translateGnssLocation(JNIEnv* env, const android::hardware::gnss::GnssLocation& location) {
+ JavaObject object(env, class_location, method_locationCtor, "gps");
+
+ uint32_t flags = static_cast<uint32_t>(location.gnssLocationFlags);
+ if (flags & android::hardware::gnss::GnssLocation::HAS_LAT_LONG) {
+ SET(Latitude, location.latitudeDegrees);
+ SET(Longitude, location.longitudeDegrees);
+ }
+ if (flags & android::hardware::gnss::GnssLocation::HAS_ALTITUDE) {
+ SET(Altitude, location.altitudeMeters);
+ }
+ if (flags & android::hardware::gnss::GnssLocation::HAS_SPEED) {
+ SET(Speed, (float)location.speedMetersPerSec);
+ }
+ if (flags & android::hardware::gnss::GnssLocation::HAS_BEARING) {
+ SET(Bearing, (float)location.bearingDegrees);
+ }
+ if (flags & android::hardware::gnss::GnssLocation::HAS_HORIZONTAL_ACCURACY) {
+ SET(Accuracy, (float)location.horizontalAccuracyMeters);
+ }
+ if (flags & android::hardware::gnss::GnssLocation::HAS_VERTICAL_ACCURACY) {
+ SET(VerticalAccuracyMeters, (float)location.verticalAccuracyMeters);
+ }
+ if (flags & android::hardware::gnss::GnssLocation::HAS_SPEED_ACCURACY) {
+ SET(SpeedAccuracyMetersPerSecond, (float)location.speedAccuracyMetersPerSecond);
+ }
+ if (flags & android::hardware::gnss::GnssLocation::HAS_BEARING_ACCURACY) {
+ SET(BearingAccuracyDegrees, (float)location.bearingAccuracyDegrees);
+ }
+ SET(Time, location.timestampMillis);
+
+ flags = static_cast<uint32_t>(location.elapsedRealtime.flags);
+ if (flags & android::hardware::gnss::ElapsedRealtime::HAS_TIMESTAMP_NS) {
+ SET(ElapsedRealtimeNanos, location.elapsedRealtime.timestampNs);
+ }
+ if (flags & android::hardware::gnss::ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS) {
+ SET(ElapsedRealtimeUncertaintyNanos,
+ static_cast<double>(location.elapsedRealtime.timeUncertaintyNs));
+ }
+
+ return object.get();
+}
+
+template <>
+jobject translateGnssLocation(JNIEnv* env, const GnssLocation_V1_0& location) {
+ JavaObject object(env, class_location, method_locationCtor, "gps");
+
+ uint16_t flags = static_cast<uint16_t>(location.gnssLocationFlags);
+ if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_LAT_LONG) {
+ SET(Latitude, location.latitudeDegrees);
+ SET(Longitude, location.longitudeDegrees);
+ }
+ if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_ALTITUDE) {
+ SET(Altitude, location.altitudeMeters);
+ }
+ if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_SPEED) {
+ SET(Speed, location.speedMetersPerSec);
+ }
+ if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_BEARING) {
+ SET(Bearing, location.bearingDegrees);
+ }
+ if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
+ SET(Accuracy, location.horizontalAccuracyMeters);
+ }
+ if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
+ SET(VerticalAccuracyMeters, location.verticalAccuracyMeters);
+ }
+ if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_SPEED_ACCURACY) {
+ SET(SpeedAccuracyMetersPerSecond, location.speedAccuracyMetersPerSecond);
+ }
+ if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_BEARING_ACCURACY) {
+ SET(BearingAccuracyDegrees, location.bearingAccuracyDegrees);
+ }
+ SET(Time, location.timestamp);
+ SET(ElapsedRealtimeNanos, android::elapsedRealtimeNano());
+
+ return object.get();
+}
+
+template <>
+jobject translateGnssLocation(JNIEnv* env, const GnssLocation_V2_0& location) {
+ JavaObject object(env, class_location, translateGnssLocation(env, location.v1_0));
+
+ const uint16_t flags = static_cast<uint16_t>(location.elapsedRealtime.flags);
+
+ // Overwrite ElapsedRealtimeNanos when available from HAL.
+ if (flags & android::hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
+ SET(ElapsedRealtimeNanos, location.elapsedRealtime.timestampNs);
+ }
+
+ if (flags & android::hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) {
+ SET(ElapsedRealtimeUncertaintyNanos,
+ static_cast<double>(location.elapsedRealtime.timeUncertaintyNs));
+ }
+
+ return object.get();
+}
+
} // namespace android
diff --git a/services/core/jni/gnss/Utils.h b/services/core/jni/gnss/Utils.h
index 0938a1b..1bd69c4 100644
--- a/services/core/jni/gnss/Utils.h
+++ b/services/core/jni/gnss/Utils.h
@@ -37,11 +37,19 @@
// Must match the value from GnssMeasurement.java
const uint32_t ADR_STATE_HALF_CYCLE_REPORTED = (1 << 4);
+extern jmethodID method_locationCtor;
} // anonymous namespace
+extern jclass class_location;
extern jobject mCallbacksObj;
+namespace gnss {
+void Utils_class_init_once(JNIEnv* env);
+} // namespace gnss
+
+jobject& getCallbacksObj();
+
jboolean checkHidlReturn(hardware::Return<bool>& result, const char* errorMessage);
jboolean checkAidlStatus(const android::binder::Status& status, const char* errorMessage);
@@ -190,6 +198,9 @@
JNIEnv* getJniEnv();
+template <class T>
+jobject translateGnssLocation(JNIEnv* env, const T& location);
+
} // namespace android
#endif // _ANDROID_SERVER_GNSS_UTILS_H
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index 37a84f3..df9ab50 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -16,7 +16,7 @@
package com.android.server.devicepolicy;
-import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_DISABLED;
+import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
@@ -161,10 +161,10 @@
int mPasswordComplexity = PASSWORD_COMPLEXITY_NONE;
@DevicePolicyManager.NearbyStreamingPolicy
- int mNearbyNotificationStreamingPolicy = NEARBY_STREAMING_DISABLED;
+ int mNearbyNotificationStreamingPolicy = NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY;
@DevicePolicyManager.NearbyStreamingPolicy
- int mNearbyAppStreamingPolicy = NEARBY_STREAMING_DISABLED;
+ int mNearbyAppStreamingPolicy = NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY;
@Nullable
FactoryResetProtectionPolicy mFactoryResetProtectionPolicy = null;
@@ -553,11 +553,11 @@
if (mPasswordComplexity != PASSWORD_COMPLEXITY_NONE) {
writeAttributeValueToXml(out, TAG_PASSWORD_COMPLEXITY, mPasswordComplexity);
}
- if (mNearbyNotificationStreamingPolicy != NEARBY_STREAMING_DISABLED) {
+ if (mNearbyNotificationStreamingPolicy != NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY) {
writeAttributeValueToXml(out, TAG_NEARBY_NOTIFICATION_STREAMING_POLICY,
mNearbyNotificationStreamingPolicy);
}
- if (mNearbyAppStreamingPolicy != NEARBY_STREAMING_DISABLED) {
+ if (mNearbyAppStreamingPolicy != NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY) {
writeAttributeValueToXml(out, TAG_NEARBY_APP_STREAMING_POLICY,
mNearbyAppStreamingPolicy);
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 752ad0b..7ef80ae 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -631,7 +631,8 @@
mStartCount = SystemProperties.getInt(SYSPROP_START_COUNT, 0) + 1;
mRuntimeStartElapsedTime = SystemClock.elapsedRealtime();
mRuntimeStartUptime = SystemClock.uptimeMillis();
- Process.setStartTimes(mRuntimeStartElapsedTime, mRuntimeStartUptime);
+ Process.setStartTimes(mRuntimeStartElapsedTime, mRuntimeStartUptime,
+ mRuntimeStartElapsedTime, mRuntimeStartUptime);
// Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
// We don't use "mStartCount > 1" here because it'll be wrong on a FDE device.
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
index 0248b9b..d926dcb 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
@@ -265,9 +265,10 @@
}
@Test
- public void testInstallerCanSetOverrides() throws Exception {
+ public void testInstallerCanAddOverrides() throws Exception {
final long disabledChangeId1 = 1234L;
final long disabledChangeId2 = 1235L;
+ final long unknownChangeId = 1236L;
// We make disabledChangeId2 non-overridable to make sure it is ignored.
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
.addDisabledOverridableChangeWithId(disabledChangeId1)
@@ -284,19 +285,25 @@
// Force the validator to prevent overriding non-overridable changes by using a user build.
when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
when(mBuildClassifier.isFinalBuild()).thenReturn(true);
+ Map<Long, PackageOverride> overrides = new HashMap<>();
+ overrides.put(disabledChangeId1, new PackageOverride.Builder()
+ .setMaxVersionCode(99L)
+ .setEnabled(true)
+ .build());
+ // Adding an unknown change ID to make sure it's skipped if skipUnknownChangeIds is true.
+ overrides.put(unknownChangeId, new PackageOverride.Builder().setEnabled(false).build());
+ CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
- CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(
- Collections.singletonMap(disabledChangeId1,
- new PackageOverride.Builder()
- .setMaxVersionCode(99L)
- .setEnabled(true)
- .build()));
-
- compatConfig.addOverrides(config, "com.some.package");
+ compatConfig.addPackageOverrides(config, "com.some.package", /* skipUnknownChangeIds */
+ true);
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isTrue();
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isFalse();
+ // Making sure the unknown change ID is still unknown and isChangeEnabled returns true.
+ assertThat(compatConfig.isKnownChangeId(unknownChangeId)).isFalse();
+ assertThat(compatConfig.isChangeEnabled(unknownChangeId, applicationInfo)).isTrue();
}
+
@Test
public void testPreventInstallerSetNonOverridable() throws Exception {
final long disabledChangeId1 = 1234L;
@@ -326,7 +333,8 @@
CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
assertThrows(SecurityException.class,
- () -> compatConfig.addOverrides(config, "com.some.package")
+ () -> compatConfig.addPackageOverrides(config, "com.some.package",
+ /* skipUnknownChangeIds */ true)
);
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isTrue();
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isFalse();
@@ -334,6 +342,38 @@
}
@Test
+ public void testCanAddOverridesForUnknownChangeIdOnDebugBuild() throws Exception {
+ final long disabledChangeId = 1234L;
+ final long unknownChangeId = 1235L;
+ // We make disabledChangeId2 non-overridable to make sure it is ignored.
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addDisabledChangeWithId(disabledChangeId)
+ .build();
+ ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
+ .withPackageName("com.some.package")
+ .build();
+ PackageManager packageManager = mock(PackageManager.class);
+ when(mContext.getPackageManager()).thenReturn(packageManager);
+ when(packageManager.getApplicationInfo(eq("com.some.package"), anyInt()))
+ .thenReturn(applicationInfo);
+
+ when(mBuildClassifier.isDebuggableBuild()).thenReturn(true);
+ Map<Long, PackageOverride> overrides = new HashMap<>();
+ overrides.put(disabledChangeId, new PackageOverride.Builder().setEnabled(true).build());
+ // Adding an unknown change ID to make sure it isn't skipped if skipUnknownChangeIds is
+ // false.
+ overrides.put(unknownChangeId, new PackageOverride.Builder().setEnabled(false).build());
+ CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
+
+ compatConfig.addPackageOverrides(config, "com.some.package", /* skipUnknownChangeIds */
+ false);
+ assertThat(compatConfig.isChangeEnabled(disabledChangeId, applicationInfo)).isTrue();
+ // Making sure the unknown change ID is now known and has an override.
+ assertThat(compatConfig.isKnownChangeId(unknownChangeId)).isTrue();
+ assertThat(compatConfig.isChangeEnabled(unknownChangeId, applicationInfo)).isFalse();
+ }
+
+ @Test
public void testApplyDeferredOverridesAfterInstallingApp() throws Exception {
ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
.withPackageName("com.notinstalled.foo")
@@ -377,7 +417,8 @@
.setMaxVersionCode(99L)
.setEnabled(true)
.build()));
- compatConfig.addOverrides(config, "com.installed.foo");
+ compatConfig.addPackageOverrides(config, "com.installed.foo", /* skipUnknownChangeIds */
+ true);
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
// Add override that does include the installed app version
@@ -388,7 +429,8 @@
.setMaxVersionCode(100L)
.setEnabled(true)
.build()));
- compatConfig.addOverrides(config, "com.installed.foo");
+ compatConfig.addPackageOverrides(config, "com.installed.foo", /* skipUnknownChangeIds */
+ true);
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
}
@@ -411,7 +453,8 @@
.setMaxVersionCode(99L)
.setEnabled(true)
.build()));
- compatConfig.addOverrides(config, "com.notinstalled.foo");
+ compatConfig.addPackageOverrides(config, "com.notinstalled.foo", /* skipUnknownChangeIds */
+ true);
assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
// Pretend the app is now installed.
@@ -557,6 +600,7 @@
final long disabledChangeId1 = 1234L;
final long disabledChangeId2 = 1235L;
final long enabledChangeId = 1236L;
+ final long unknownChangeId = 1237L;
// We make disabledChangeId2 non-overridable to make sure it is ignored.
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
.addDisabledOverridableChangeWithId(disabledChangeId1)
@@ -583,6 +627,8 @@
Set<Long> overridesToRemove = new HashSet<>();
overridesToRemove.add(disabledChangeId1);
overridesToRemove.add(enabledChangeId);
+ // Adding an unknown change ID to make sure it's skipped.
+ overridesToRemove.add(unknownChangeId);
CompatibilityOverridesToRemoveConfig config = new CompatibilityOverridesToRemoveConfig(
overridesToRemove);
@@ -590,6 +636,8 @@
assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isFalse();
assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isTrue();
assertThat(compatConfig.isChangeEnabled(enabledChangeId, applicationInfo)).isTrue();
+ // Making sure the unknown change ID is still unknown.
+ assertThat(compatConfig.isKnownChangeId(unknownChangeId)).isFalse();
}
@Test
@@ -797,18 +845,18 @@
.build());
when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt()))
.thenThrow(new NameNotFoundException());
- compatConfig.addOverrides(
+ compatConfig.addPackageOverrides(
new CompatibilityOverrideConfig(
Collections.singletonMap(
1L,
new PackageOverride.Builder().setEnabled(true).build())),
- "foo.bar");
- compatConfig.addOverrides(
+ "foo.bar", /* skipUnknownChangeIds */ true);
+ compatConfig.addPackageOverrides(
new CompatibilityOverrideConfig(
Collections.singletonMap(
2L,
new PackageOverride.Builder().setEnabled(false).build())),
- "bar.baz");
+ "bar.baz", /* skipUnknownChangeIds */ true);
assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<overrides>\n"
@@ -847,12 +895,12 @@
compatConfig.forceNonDebuggableFinalForTest(true);
compatConfig.initOverrides(overridesFile, new File(""));
- compatConfig.addOverrides(new CompatibilityOverrideConfig(Collections.singletonMap(1L,
- new PackageOverride.Builder()
+ compatConfig.addPackageOverrides(new CompatibilityOverrideConfig(
+ Collections.singletonMap(1L, new PackageOverride.Builder()
.setMinVersionCode(99L)
.setMaxVersionCode(101L)
.setEnabled(true)
- .build())), "foo.bar");
+ .build())), "foo.bar", /* skipUnknownChangeIds */ true);
assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<overrides>\n"
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
index 51f627a..11d5f3f 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
@@ -29,9 +29,6 @@
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import android.util.IndentingPrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-
class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
private ConfigurationChangeListener mConfigurationChangeListener;
@@ -44,7 +41,6 @@
private ManualTimeZoneSuggestion mLastManualSuggestion;
private TelephonyTimeZoneSuggestion mLastTelephonySuggestion;
private boolean mDumpCalled;
- private final List<Dumpable> mDumpables = new ArrayList<>();
@Override
public void addConfigChangeListener(@NonNull ConfigurationChangeListener listener) {
@@ -123,11 +119,6 @@
}
@Override
- public void addDumpable(Dumpable dumpable) {
- mDumpables.add(dumpable);
- }
-
- @Override
public void dump(IndentingPrintWriter pw, String[] args) {
mDumpCalled = true;
}
@@ -159,8 +150,4 @@
void verifyDumpCalled() {
assertTrue(mDumpCalled);
}
-
- void verifyHasDumpable(Dumpable expected) {
- assertTrue(mDumpables.contains(expected));
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java
index 5864620..45c5b6c 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java
@@ -78,16 +78,6 @@
}
@Test
- public void testAddDumpable() throws Exception {
- Dumpable stubbedDumpable = mock(Dumpable.class);
-
- mTimeZoneDetectorInternal.addDumpable(stubbedDumpable);
- mTestHandler.assertTotalMessagesEnqueued(0);
-
- mFakeTimeZoneDetectorStrategy.verifyHasDumpable(stubbedDumpable);
- }
-
- @Test
public void testAddConfigurationListener() throws Exception {
boolean[] changeCalled = new boolean[2];
mTimeZoneDetectorInternal.addConfigurationListener(() -> changeCalled[0] = true);
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
index 773abf8..1e55c7b 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
@@ -60,12 +60,12 @@
private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 1234L;
private Context mMockContext;
- private FakeTimeZoneDetectorStrategy mFakeTimeZoneDetectorStrategy;
private TimeZoneDetectorService mTimeZoneDetectorService;
private HandlerThread mHandlerThread;
private TestHandler mTestHandler;
private TestCallerIdentityInjector mTestCallerIdentityInjector;
+ private FakeTimeZoneDetectorStrategy mFakeTimeZoneDetectorStrategy;
@Before
@@ -349,11 +349,15 @@
when(mMockContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP))
.thenReturn(PackageManager.PERMISSION_GRANTED);
+ Dumpable dumpable = mock(Dumpable.class);
+ mTimeZoneDetectorService.addDumpable(dumpable);
+
PrintWriter pw = new PrintWriter(new StringWriter());
mTimeZoneDetectorService.dump(null, pw, null);
verify(mMockContext).checkCallingOrSelfPermission(eq(android.Manifest.permission.DUMP));
mFakeTimeZoneDetectorStrategy.verifyDumpCalled();
+ verify(dumpable).dump(any(), any());
}
private static TimeZoneConfiguration createTimeZoneConfiguration(boolean autoDetectionEnabled) {
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
index e2e8755..1826812 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
@@ -47,18 +47,15 @@
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion.MatchType;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion.Quality;
-import android.util.IndentingPrintWriter;
import com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.QualifiedTelephonyTimeZoneSuggestion;
import org.junit.Before;
import org.junit.Test;
-import java.io.StringWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
/**
@@ -66,8 +63,8 @@
*/
public class TimeZoneDetectorStrategyImplTest {
- /** A time zone used for initialization that does not occur elsewhere in tests. */
private static final @UserIdInt int USER_ID = 9876;
+ /** A time zone used for initialization that does not occur elsewhere in tests. */
private static final String ARBITRARY_TIME_ZONE_ID = "Etc/UTC";
private static final int SLOT_INDEX1 = 10000;
private static final int SLOT_INDEX2 = 20000;
@@ -790,7 +787,7 @@
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
script.simulateGeolocationTimeZoneSuggestion(suggestion)
- .verifyTimeZoneChangedAndReset("Europe/London");
+ .verifyTimeZoneChangedAndReset(suggestion);
// Assert internal service state.
assertEquals(suggestion, mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
@@ -815,7 +812,7 @@
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
script.simulateGeolocationTimeZoneSuggestion(londonOnlySuggestion)
- .verifyTimeZoneChangedAndReset("Europe/London");
+ .verifyTimeZoneChangedAndReset(londonOnlySuggestion);
assertEquals(londonOnlySuggestion,
mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
@@ -826,7 +823,7 @@
mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
script.simulateGeolocationTimeZoneSuggestion(parisOnlySuggestion)
- .verifyTimeZoneChangedAndReset("Europe/Paris");
+ .verifyTimeZoneChangedAndReset(parisOnlySuggestion);
assertEquals(parisOnlySuggestion,
mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
@@ -838,29 +835,6 @@
mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
}
- @Test
- public void testGeoSuggestion_togglingGeoDetectionClearsLastSuggestion() {
- GeolocationTimeZoneSuggestion suggestion =
- createCertainGeolocationSuggestion("Europe/London");
-
- Script script = new Script()
- .initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_ENABLED)
- .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
-
- script.simulateGeolocationTimeZoneSuggestion(suggestion)
- .verifyTimeZoneChangedAndReset("Europe/London");
-
- // Assert internal service state.
- assertEquals(suggestion, mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
-
- // Turn off geo detection and verify the latest suggestion is cleared.
- script.simulateUpdateConfiguration(USER_ID, CONFIG_GEO_DETECTION_DISABLED, true)
- .verifyConfigurationChangedAndReset(CONFIG_INT_AUTO_ENABLED_GEO_DISABLED);
-
- // Assert internal service state.
- assertNull(mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
- }
-
/**
* Confirms that changing the geolocation time zone detection enabled setting has the expected
* behavior, i.e. immediately recompute the detected time zone using different signals.
@@ -881,13 +855,12 @@
script.simulateGeolocationTimeZoneSuggestion(geolocationSuggestion)
.verifyTimeZoneNotChanged();
- // Geolocation suggestions are only stored when geolocation detection is enabled.
- assertNull(mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
+ assertEquals(geolocationSuggestion,
+ mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
script.simulateTelephonyTimeZoneSuggestion(telephonySuggestion)
.verifyTimeZoneNotChanged();
- // Telephony suggestions are always stored.
assertEquals(telephonySuggestion,
mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1).suggestion);
@@ -897,13 +870,11 @@
script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
.verifyTimeZoneChangedAndReset(telephonySuggestion);
- // Changing the detection to enable geo detection won't cause the device tz setting to
- // change because the geo suggestion is empty.
+ // Changing the detection to enable geo detection will cause the device tz setting to
+ // change to use the latest geolocation suggestion.
script.simulateUpdateConfiguration(
USER_ID, CONFIG_GEO_DETECTION_ENABLED, true /* expectedResult */)
- .verifyTimeZoneNotChanged()
- .simulateGeolocationTimeZoneSuggestion(geolocationSuggestion)
- .verifyTimeZoneChangedAndReset(geolocationSuggestion.getZoneIds().get(0));
+ .verifyTimeZoneChangedAndReset(geolocationSuggestion);
// Changing the detection to disable geo detection should cause the device tz setting to
// change to the telephony suggestion.
@@ -911,29 +882,8 @@
USER_ID, CONFIG_GEO_DETECTION_DISABLED, true /* expectedResult */)
.verifyTimeZoneChangedAndReset(telephonySuggestion);
- assertNull(mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
- }
-
- @Test
- public void testAddDumpable() {
- new Script()
- .initializeConfig(CONFIG_INT_AUTO_DISABLED_GEO_DISABLED)
- .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
-
- AtomicBoolean dumpCalled = new AtomicBoolean(false);
- class FakeDumpable implements Dumpable {
- @Override
- public void dump(IndentingPrintWriter pw, String[] args) {
- dumpCalled.set(true);
- }
- }
-
- mTimeZoneDetectorStrategy.addDumpable(new FakeDumpable());
- IndentingPrintWriter ipw = new IndentingPrintWriter(new StringWriter());
- String[] args = {"ArgOne", "ArgTwo"};
- mTimeZoneDetectorStrategy.dump(ipw, args);
-
- assertTrue(dumpCalled.get());
+ assertEquals(geolocationSuggestion,
+ mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
}
@Test
@@ -972,7 +922,7 @@
.verifyTimeZoneNotChanged();
assertMetricsState(expectedInternalConfig, expectedDeviceTimeZoneId,
- manualSuggestion, telephonySuggestion, null /* expectedGeoSuggestion */,
+ manualSuggestion, telephonySuggestion, geolocationTimeZoneSuggestion,
MetricsTimeZoneDetectorState.DETECTION_MODE_MANUAL);
// Update the config and confirm that the config metrics state updates also.
@@ -982,16 +932,9 @@
.setAutoDetectionEnabled(true)
.setGeoDetectionEnabled(true)
.build();
- script.simulateUpdateConfiguration(USER_ID, configUpdate, true /* expectedResult */)
- .verifyConfigurationChangedAndReset(expectedInternalConfig)
- .verifyTimeZoneNotChanged();
- assertMetricsState(expectedInternalConfig, expectedDeviceTimeZoneId,
- manualSuggestion, telephonySuggestion, null /* expectedGeoSuggestion */,
- MetricsTimeZoneDetectorState.DETECTION_MODE_GEO);
- // Now simulate a geo suggestion and confirm it is used and reported in the metrics too.
expectedDeviceTimeZoneId = geolocationTimeZoneSuggestion.getZoneIds().get(0);
- script.simulateGeolocationTimeZoneSuggestion(geolocationTimeZoneSuggestion)
+ script.simulateUpdateConfiguration(USER_ID, configUpdate, true /* expectedResult */)
.verifyTimeZoneChangedAndReset(expectedDeviceTimeZoneId);
assertMetricsState(expectedInternalConfig, expectedDeviceTimeZoneId,
manualSuggestion, telephonySuggestion, geolocationTimeZoneSuggestion,
@@ -1254,6 +1197,14 @@
return this;
}
+ Script verifyTimeZoneChangedAndReset(GeolocationTimeZoneSuggestion suggestion) {
+ assertEquals("Only use this method with unambiguous geo suggestions",
+ 1, suggestion.getZoneIds().size());
+ mFakeEnvironment.assertTimeZoneChangedTo(suggestion.getZoneIds().get(0));
+ mFakeEnvironment.commitAllChanges();
+ return this;
+ }
+
/**
* Verifies that the configuration has been changed to the expected value.
*/
diff --git a/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
index 1ff67240..00bc546 100644
--- a/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
@@ -150,11 +150,12 @@
}
- private void pressKey(long eventTime, int keyCode, long pressTime) {
- pressKey(eventTime, keyCode, pressTime, true /* interactive */);
+ private void pressKey(int keyCode, long pressTime) {
+ pressKey(keyCode, pressTime, true /* interactive */);
}
- private void pressKey(long eventTime, int keyCode, long pressTime, boolean interactive) {
+ private void pressKey(int keyCode, long pressTime, boolean interactive) {
+ long eventTime = SystemClock.uptimeMillis();
final KeyEvent keyDown = new KeyEvent(eventTime, eventTime, ACTION_DOWN,
keyCode, 0 /* repeat */, 0 /* metaState */);
mDetector.interceptKey(keyDown, interactive);
@@ -175,54 +176,48 @@
@Test
public void testShortPress() throws InterruptedException {
- final long eventTime = SystemClock.uptimeMillis();
- pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
+ pressKey(KEYCODE_POWER, 0 /* pressTime */);
assertTrue(mShortPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
}
@Test
public void testLongPress() throws InterruptedException {
- final long eventTime = SystemClock.uptimeMillis();
- pressKey(eventTime, KEYCODE_POWER, mLongPressTime);
+ pressKey(KEYCODE_POWER, mLongPressTime);
assertTrue(mLongPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
}
@Test
public void testVeryLongPress() throws InterruptedException {
- final long eventTime = SystemClock.uptimeMillis();
- pressKey(eventTime, KEYCODE_POWER, mVeryLongPressTime);
+ pressKey(KEYCODE_POWER, mVeryLongPressTime);
assertTrue(mVeryLongPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
}
@Test
public void testMultiPress() throws InterruptedException {
- final long eventTime = SystemClock.uptimeMillis();
// Double presses.
mExpectedMultiPressCount = 2;
- pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
- pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
+ pressKey(KEYCODE_POWER, 0 /* pressTime */);
+ pressKey(KEYCODE_POWER, 0 /* pressTime */);
assertTrue(mMultiPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
// Triple presses.
mExpectedMultiPressCount = 3;
mMultiPressed = new CountDownLatch(1);
- pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
- pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
- pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
+ pressKey(KEYCODE_POWER, 0 /* pressTime */);
+ pressKey(KEYCODE_POWER, 0 /* pressTime */);
+ pressKey(KEYCODE_POWER, 0 /* pressTime */);
assertTrue(mMultiPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
}
@Test
public void testNonInteractive() throws InterruptedException {
- long eventTime = SystemClock.uptimeMillis();
// Disallow short press behavior from non interactive.
mAllowNonInteractiveForPress = false;
- pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */, false /* interactive */);
+ pressKey(KEYCODE_POWER, 0 /* pressTime */, false /* interactive */);
assertFalse(mShortPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
// Allow long press behavior from non interactive.
- eventTime = SystemClock.uptimeMillis();
- pressKey(eventTime, KEYCODE_POWER, mLongPressTime, false /* interactive */);
+ pressKey(KEYCODE_POWER, mLongPressTime, false /* interactive */);
assertTrue(mLongPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
}
@@ -238,9 +233,8 @@
for (int i = 0; i < 100; i++) {
mShortPressed = new CountDownLatch(2);
newHandler.runWithScissors(() -> {
- final long eventTime = SystemClock.uptimeMillis();
- pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
- pressKey(eventTime, KEYCODE_BACK, 0 /* pressTime */);
+ pressKey(KEYCODE_POWER, 0 /* pressTime */);
+ pressKey(KEYCODE_BACK, 0 /* pressTime */);
}, mWaitTimeout);
assertTrue(mShortPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
}
@@ -261,15 +255,13 @@
mMultiPressed = new CountDownLatch(1);
mShortPressed = new CountDownLatch(1);
newHandler.runWithScissors(() -> {
- final long eventTime = SystemClock.uptimeMillis();
- pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
- pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
+ pressKey(KEYCODE_POWER, 0 /* pressTime */);
+ pressKey(KEYCODE_POWER, 0 /* pressTime */);
}, mWaitTimeout);
assertTrue(mMultiPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
newHandler.runWithScissors(() -> {
- final long eventTime = SystemClock.uptimeMillis();
- pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
+ pressKey(KEYCODE_POWER, 0 /* pressTime */);
}, mWaitTimeout);
assertTrue(mShortPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
index 589f913..74cff10 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
@@ -94,6 +94,20 @@
}
@Test
+ public void testAddWindow_assignsLayers() {
+ final TestWindowToken token1 = createTestWindowToken(0, mDisplayContent);
+ final TestWindowToken token2 = createTestWindowToken(0, mDisplayContent);
+ final WindowState window1 = createWindow(null, TYPE_STATUS_BAR, token1, "window1");
+ final WindowState window2 = createWindow(null, TYPE_STATUS_BAR, token2, "window2");
+
+ token1.addWindow(window1);
+ token2.addWindow(window2);
+
+ assertEquals(token1.getLastLayer(), 0);
+ assertEquals(token2.getLastLayer(), 1);
+ }
+
+ @Test
public void testChildRemoval() {
final DisplayContent dc = mDisplayContent;
final TestWindowToken token = createTestWindowToken(0, dc);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 2dfa9a45..f700d79 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -5984,7 +5984,7 @@
sDefaults.putString(KEY_CARRIER_PROVISIONING_APP_STRING, "");
sDefaults.putBoolean(KEY_DISPLAY_NO_DATA_NOTIFICATION_ON_PERMANENT_FAILURE_BOOL, false);
sDefaults.putBoolean(KEY_UNTHROTTLE_DATA_RETRY_WHEN_TAC_CHANGES_BOOL, false);
- sDefaults.putBoolean(KEY_VONR_SETTING_VISIBILITY_BOOL, false);
+ sDefaults.putBoolean(KEY_VONR_SETTING_VISIBILITY_BOOL, true);
sDefaults.putBoolean(KEY_VONR_ENABLED_BOOL, false);
}
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 63a7acf..d6d6775 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -222,6 +222,11 @@
private boolean mAreUiccApplicationsEnabled = true;
/**
+ * The port index of the Uicc card.
+ */
+ private final int mPortIndex;
+
+ /**
* Public copy constructor.
* @hide
*/
@@ -274,6 +279,22 @@
int carrierId, int profileClass, int subType, @Nullable String groupOwner,
@Nullable UiccAccessRule[] carrierConfigAccessRules,
boolean areUiccApplicationsEnabled) {
+ this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
+ roaming, icon, mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString,
+ cardId, isOpportunistic, groupUUID, isGroupDisabled, carrierId, profileClass,
+ subType, groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled, 0);
+ }
+ /**
+ * @hide
+ */
+ public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
+ CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
+ Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
+ @Nullable UiccAccessRule[] nativeAccessRules, String cardString, int cardId,
+ boolean isOpportunistic, @Nullable String groupUUID, boolean isGroupDisabled,
+ int carrierId, int profileClass, int subType, @Nullable String groupOwner,
+ @Nullable UiccAccessRule[] carrierConfigAccessRules,
+ boolean areUiccApplicationsEnabled, int portIndex) {
this.mId = id;
this.mIccId = iccId;
this.mSimSlotIndex = simSlotIndex;
@@ -300,8 +321,8 @@
this.mGroupOwner = groupOwner;
this.mCarrierConfigAccessRules = carrierConfigAccessRules;
this.mAreUiccApplicationsEnabled = areUiccApplicationsEnabled;
+ this.mPortIndex = portIndex;
}
-
/**
* @return the subscription ID.
*/
@@ -737,6 +758,14 @@
public int getCardId() {
return this.mCardId;
}
+ /**
+ * Returns the port index of the SIM card which contains the subscription.
+ *
+ * @return the portIndex
+ */
+ public int getPortIndex() {
+ return this.mPortIndex;
+ }
/**
* Set whether the subscription's group is disabled.
@@ -783,6 +812,7 @@
UiccAccessRule[] nativeAccessRules = source.createTypedArray(UiccAccessRule.CREATOR);
String cardString = source.readString();
int cardId = source.readInt();
+ int portId = source.readInt();
boolean isOpportunistic = source.readBoolean();
String groupUUID = source.readString();
boolean isGroupDisabled = source.readBoolean();
@@ -800,7 +830,7 @@
carrierName, nameSource, iconTint, number, dataRoaming, /* icon= */ null,
mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, cardId,
isOpportunistic, groupUUID, isGroupDisabled, carrierid, profileClass, subType,
- groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled);
+ groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled, portId);
info.setAssociatedPlmns(ehplmns, hplmns);
return info;
}
@@ -830,6 +860,7 @@
dest.writeTypedArray(mNativeAccessRules, flags);
dest.writeString(mCardString);
dest.writeInt(mCardId);
+ dest.writeInt(mPortIndex);
dest.writeBoolean(mIsOpportunistic);
dest.writeString(mGroupUUID == null ? null : mGroupUUID.toString());
dest.writeBoolean(mIsGroupDisabled);
@@ -876,6 +907,7 @@
+ " mnc=" + mMnc + " countryIso=" + mCountryIso + " isEmbedded=" + mIsEmbedded
+ " nativeAccessRules=" + Arrays.toString(mNativeAccessRules)
+ " cardString=" + cardStringToPrint + " cardId=" + mCardId
+ + " portIndex=" + mPortIndex
+ " isOpportunistic=" + mIsOpportunistic + " groupUUID=" + mGroupUUID
+ " isGroupDisabled=" + mIsGroupDisabled
+ " profileClass=" + mProfileClass
@@ -892,7 +924,7 @@
return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded,
mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc, mCountryIso, mCardString,
mCardId, mDisplayName, mCarrierName, mNativeAccessRules, mIsGroupDisabled,
- mCarrierId, mProfileClass, mGroupOwner, mAreUiccApplicationsEnabled);
+ mCarrierId, mProfileClass, mGroupOwner, mAreUiccApplicationsEnabled, mPortIndex);
}
@Override
@@ -925,6 +957,7 @@
&& Objects.equals(mCountryIso, toCompare.mCountryIso)
&& Objects.equals(mCardString, toCompare.mCardString)
&& Objects.equals(mCardId, toCompare.mCardId)
+ && mPortIndex == toCompare.mPortIndex
&& Objects.equals(mGroupOwner, toCompare.mGroupOwner)
&& TextUtils.equals(mDisplayName, toCompare.mDisplayName)
&& TextUtils.equals(mCarrierName, toCompare.mCarrierName)
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index d5315ac..1fab89e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1128,6 +1128,52 @@
*/
public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX";
+ /**
+ * A source of phone number: the EF-MSISDN (see 3GPP TS 31.102),
+ * or EF-MDN for CDMA (see 3GPP2 C.P0065-B), from UICC application.
+ *
+ * <p>The availability and a of the number depends on the carrier.
+ * The number may be updated by over-the-air update to UICC applications
+ * from the carrier, or by other means with physical access to the SIM.
+ */
+ public static final int PHONE_NUMBER_SOURCE_UICC = 1;
+
+ /**
+ * A source of phone number: provided by an app that has carrier privilege.
+ *
+ * <p>The number is intended to be set by a carrier app knowing the correct number
+ * which is, for example, different from the number in {@link #PHONE_NUMBER_SOURCE_UICC UICC}
+ * for some reason.
+ * The number is not available until a carrier app sets one via
+ * {@link #setCarrierPhoneNumber(int, String)}.
+ * The app can update the number with the same API should the number change.
+ */
+ public static final int PHONE_NUMBER_SOURCE_CARRIER = 2;
+
+ /**
+ * A source of phone number: provided by IMS (IP Multimedia Subsystem) implementation.
+ * When IMS service is registered (as indicated by
+ * {@link android.telephony.ims.RegistrationManager.RegistrationCallback#onRegistered(int)})
+ * the IMS implementation may return P-Associated-Uri SIP headers (RFC 3455). The URIs
+ * are the user’s public user identities known to the network (see 3GPP TS 24.229 5.4.1.2),
+ * and the phone number is typically one of them (see “global number” in 3GPP TS 23.003 13.4).
+ *
+ * <p>This source provides the phone number from the last IMS registration.
+ * IMS registration may happen on every device reboot or other network condition changes.
+ * The number will be updated should the associated URI change after an IMS registration.
+ */
+ public static final int PHONE_NUMBER_SOURCE_IMS = 3;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"PHONE_NUMBER_SOURCE"},
+ value = {
+ PHONE_NUMBER_SOURCE_UICC,
+ PHONE_NUMBER_SOURCE_CARRIER,
+ PHONE_NUMBER_SOURCE_IMS,
+ })
+ public @interface PhoneNumberSource {}
+
private final Context mContext;
// Cache of Resource that has been created in getResourcesForSubId. Key is a Pair containing
@@ -3763,4 +3809,132 @@
RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME,
null, bundle);
}
+
+ /**
+ * Returns the phone number for the given {@code subId} and {@code source},
+ * or an empty string if not available.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_NUMBERS READ_PHONE_NUMBERS}, or
+ * READ_PRIVILEGED_PHONE_STATE permission (can only be granted to apps preloaded on device),
+ * or that the calling app has carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}).
+ *
+ * @param subscriptionId the subscription ID, or {@link #DEFAULT_SUBSCRIPTION_ID}
+ * for the default one.
+ * @param source the source of the phone number, one of the PHONE_NUMBER_SOURCE_* constants.
+ * @return the phone number, or an empty string if not available.
+ * @throws IllegalArgumentException if {@code source} is invalid.
+ * @throws IllegalStateException if the telephony process is not currently available.
+ * @throws SecurityException if the caller doesn't have permissions required.
+ * @see #PHONE_NUMBER_SOURCE_UICC
+ * @see #PHONE_NUMBER_SOURCE_CARRIER
+ * @see #PHONE_NUMBER_SOURCE_IMS
+ */
+ @SuppressAutoDoc // No support for carrier privileges (b/72967236)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PHONE_NUMBERS,
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ })
+ @NonNull
+ public String getPhoneNumber(int subscriptionId, @PhoneNumberSource int source) {
+ if (subscriptionId == DEFAULT_SUBSCRIPTION_ID) {
+ subscriptionId = getDefaultSubscriptionId();
+ }
+ if (source != PHONE_NUMBER_SOURCE_UICC
+ && source != PHONE_NUMBER_SOURCE_CARRIER
+ && source != PHONE_NUMBER_SOURCE_IMS) {
+ throw new IllegalArgumentException("invalid source " + source);
+ }
+ try {
+ ISub iSub = TelephonyManager.getSubscriptionService();
+ if (iSub != null) {
+ return iSub.getPhoneNumber(subscriptionId, source,
+ mContext.getOpPackageName(), mContext.getAttributionTag());
+ } else {
+ throw new IllegalStateException("subscription service unavailable.");
+ }
+ } catch (RemoteException ex) {
+ throw ex.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Returns the phone number for the given {@code subId}, or an empty string if
+ * not available.
+ *
+ * <p>This API is built up on {@link #getPhoneNumber(int, int)}, but picks
+ * from available sources in the following order: {@link #PHONE_NUMBER_SOURCE_CARRIER}
+ * > {@link #PHONE_NUMBER_SOURCE_UICC} > {@link #PHONE_NUMBER_SOURCE_IMS}.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_NUMBERS READ_PHONE_NUMBERS}, or
+ * READ_PRIVILEGED_PHONE_STATE permission (can only be granted to apps preloaded on device),
+ * or that the calling app has carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}).
+ *
+ * @param subscriptionId the subscription ID, or {@link #DEFAULT_SUBSCRIPTION_ID}
+ * for the default one.
+ * @return the phone number, or an empty string if not available.
+ * @throws IllegalStateException if the telephony process is not currently available.
+ * @throws SecurityException if the caller doesn't have permissions required.
+ * @see #getPhoneNumber(int, int)
+ */
+ @SuppressAutoDoc // No support for carrier privileges (b/72967236)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PHONE_NUMBERS,
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ })
+ @NonNull
+ public String getPhoneNumber(int subscriptionId) {
+ if (subscriptionId == DEFAULT_SUBSCRIPTION_ID) {
+ subscriptionId = getDefaultSubscriptionId();
+ }
+ try {
+ ISub iSub = TelephonyManager.getSubscriptionService();
+ if (iSub != null) {
+ return iSub.getPhoneNumberFromFirstAvailableSource(subscriptionId,
+ mContext.getOpPackageName(), mContext.getAttributionTag());
+ } else {
+ throw new IllegalStateException("subscription service unavailable.");
+ }
+ } catch (RemoteException ex) {
+ throw ex.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Sets the phone number for the given {@code subId} for source
+ * {@link #PHONE_NUMBER_SOURCE_CARRIER carrier}.
+ * Sets an empty string to remove the previously set phone number.
+ *
+ * <p>Requires Permission: the calling app has carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}).
+ *
+ * @param subscriptionId the subscription ID, or {@link #DEFAULT_SUBSCRIPTION_ID}
+ * for the default one.
+ * @param number the phone number, or an empty string to remove the previously set number.
+ * @throws IllegalStateException if the telephony process is not currently available.
+ * @throws NullPointerException if {@code number} is {@code null}.
+ * @throws SecurityException if the caller doesn't have permissions required.
+ */
+ public void setCarrierPhoneNumber(int subscriptionId, @NonNull String number) {
+ if (subscriptionId == DEFAULT_SUBSCRIPTION_ID) {
+ subscriptionId = getDefaultSubscriptionId();
+ }
+ if (number == null) {
+ throw new NullPointerException("invalid number null");
+ }
+ try {
+ ISub iSub = TelephonyManager.getSubscriptionService();
+ if (iSub != null) {
+ iSub.setPhoneNumber(subscriptionId, PHONE_NUMBER_SOURCE_CARRIER, number,
+ mContext.getOpPackageName(), mContext.getAttributionTag());
+ } else {
+ throw new IllegalStateException("subscription service unavailable.");
+ }
+ } catch (RemoteException ex) {
+ throw ex.rethrowAsRuntimeException();
+ }
+ }
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 50f2abd..04e7b7c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -131,6 +131,8 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -144,6 +146,7 @@
import java.util.stream.Collectors;
import java.util.stream.IntStream;
+
/**
* Provides access to information about the telephony services on
* the device. Applications can use the methods in this class to
@@ -3931,8 +3934,8 @@
* <p>
* If the caller has carrier priviliges on any active subscription, then they have permission to
* get simple information like the card ID ({@link UiccCardInfo#getCardId()}), whether the card
- * is an eUICC ({@link UiccCardInfo#isEuicc()}), and the slot index where the card is inserted
- * ({@link UiccCardInfo#getSlotIndex()}).
+ * is an eUICC ({@link UiccCardInfo#isEuicc()}), and the physical slot index where the card is
+ * inserted ({@link UiccCardInfo#getPhysicalSlotIndex()}.
* <p>
* To get private information such as the EID ({@link UiccCardInfo#getEid()}) or ICCID
* ({@link UiccCardInfo#getIccId()}), the caller must have carrier priviliges on that specific
@@ -3976,7 +3979,7 @@
if (telephony == null) {
return null;
}
- return telephony.getUiccSlotsInfo();
+ return telephony.getUiccSlotsInfo(mContext.getOpPackageName());
} catch (RemoteException e) {
return null;
}
@@ -4009,8 +4012,13 @@
* size should be same as {@link #getUiccSlotsInfo()}.
* @return boolean Return true if the switch succeeds, false if the switch fails.
* @hide
+ * @deprecated {@link #setSimSlotMapping(Collection, Executor, Consumer)}
*/
+ // TODO: once integrating the HAL changes we can convert int[] to List<UiccSlotMapping> and
+ // converge API's in ITelephony.aidl and PhoneInterfaceManager
+
@SystemApi
+ @Deprecated
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean switchSlots(int[] physicalSlots) {
try {
@@ -4025,6 +4033,109 @@
}
/**
+ * @param slotMapping Logical to physical slot and port mapping.
+ * @return {@code true} if slotMapping is valid.
+ * @return {@code false} if slotMapping is invalid.
+ *
+ * slotMapping is invalid if there are different entries (physical slot + port) mapping to the
+ * same logical slot or if there are same {physical slot + port} mapping to the different
+ * logical slot
+ * @hide
+ */
+ private static boolean isSlotMappingValid(@NonNull Collection<UiccSlotMapping> slotMapping) {
+ // Grouping the collection by logicalSlotIndex, finding different entries mapping to the
+ // same logical slot
+ Map<Integer, List<UiccSlotMapping>> slotMappingInfo = slotMapping.stream().collect(
+ Collectors.groupingBy(UiccSlotMapping::getLogicalSlotIndex));
+ for (Map.Entry<Integer, List<UiccSlotMapping>> entry : slotMappingInfo.entrySet()) {
+ List<UiccSlotMapping> logicalSlotMap = entry.getValue();
+ if (logicalSlotMap.size() > 1) {
+ // duplicate logicalSlotIndex found
+ return false;
+ }
+ }
+
+ // Grouping the collection by physical slot and port, finding same entries mapping to the
+ // different logical slot
+ Map<List<Integer>, List<UiccSlotMapping>> slotMapInfos = slotMapping.stream().collect(
+ Collectors.groupingBy(
+ slot -> Arrays.asList(slot.getPhysicalSlotIndex(), slot.getPortIndex())));
+ for (Map.Entry<List<Integer>, List<UiccSlotMapping>> entry : slotMapInfos.entrySet()) {
+ List<UiccSlotMapping> portAndPhysicalSlotList = entry.getValue();
+ if (portAndPhysicalSlotList.size() > 1) {
+ // duplicate pair of portIndex and physicalSlotIndex found
+ return false;
+ }
+ }
+ return true;
+ }
+ /**
+ * Maps the logical slots to physical slots and ports. Mapping is specified from
+ * {@link UiccSlotMapping} which consist of both physical slot index and port index.
+ * Logical slot is the slot that is seen by modem. Physical slot is the actual physical slot.
+ * Port index is the index (enumerated value) for the associated port available on the SIM.
+ * Each physical slot can have multiple ports if multi-enabled profile(MEP) is supported.
+ *
+ * Example: no. of logical slots 1 and physical slots 2 do not support MEP, each physical slot
+ * has one port:
+ * The only logical slot (index 0) can be mapped to first physical slot (value 0), port(index
+ * 0) or
+ * second physical slot(value 1), port (index 0), while the other physical slot remains unmapped
+ * and inactive.
+ * slotMapping[0] = UiccSlotMapping{0 //logical slot, 0 //physical slot//, 0 //port//}
+ * slotMapping[0] = UiccSlotMapping{1 // logical slot, 1 //physical slot//, 0 //port//}
+ *
+ * Example no. of logical slots 2 and physical slots 2 supports MEP with 2 ports available:
+ * Each logical slot must be mapped to a port (physical slot and port combination).
+ * First logical slot (index 0) can be mapped to physical slot 1 and the second logical slot
+ * can be mapped to either port from physical slot 2.
+ *
+ * slotMapping[0] = UiccSlotMapping{0, 0, 0} and slotMapping[1] = UiccSlotMapping{1, 0, 0} or
+ * slotMapping[0] = UiccSlotMapping{0, 0, 0} and slotMapping[1] = UiccSlotMapping{1, 1, 1}
+ *
+ * or the other way around, the second logical slot(index 1) can be mapped to physical slot 1
+ * and the first logical slot can be mapped to either port from physical slot 2.
+ *
+ * slotMapping[1] = UiccSlotMapping{0, 0, 0} and slotMapping[0] = UiccSlotMapping{1, 0, 0} or
+ * slotMapping[1] = UiccSlotMapping{0, 0, 0} and slotMapping[0] = UiccSlotMapping{1, 1, 1}
+ *
+ * another possible mapping is each logical slot maps to each port of physical slot 2 and there
+ * is no active logical modem mapped to physical slot 1.
+ *
+ * slotMapping[0] = UiccSlotMapping{1, 0, 0} and slotMapping[1] = UiccSlotMapping{1, 1, 1} or
+ * slotMapping[0] = UiccSlotMapping{1, 1, 1} and slotMapping[1] = UiccSlotMapping{1, 0, 0}
+ *
+ * @param slotMapping Logical to physical slot and port mapping.
+ * @throws IllegalStateException if telephony service is null or slot mapping was sent when the
+ * radio in middle of a silent restart or other invalid states to handle the command
+ * @throws IllegalArgumentException if the caller passes in an invalid collection of
+ * UiccSlotMapping like duplicate data, etc
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public void setSimSlotMapping(@NonNull Collection<UiccSlotMapping> slotMapping) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ if (isSlotMappingValid(slotMapping)) {
+ boolean result = telephony.setSimSlotMapping(new ArrayList(slotMapping));
+ if (!result) {
+ throw new IllegalStateException("setSimSlotMapping has failed");
+ }
+ } else {
+ throw new IllegalArgumentException("Duplicate UiccSlotMapping data found");
+ }
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
* Get the mapping from logical slots to physical slots. The key of the map is the logical slot
* id and the value is the physical slots id mapped to this logical slot id.
*
@@ -4041,7 +4152,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- int[] slotMappingArray = telephony.getSlotsMapping();
+ int[] slotMappingArray = telephony.getSlotsMapping(mContext.getOpPackageName());
for (int i = 0; i < slotMappingArray.length; i++) {
slotMapping.put(i, slotMappingArray[i]);
}
diff --git a/telephony/java/android/telephony/UiccCardInfo.java b/telephony/java/android/telephony/UiccCardInfo.java
index b4389203..7dfe450 100644
--- a/telephony/java/android/telephony/UiccCardInfo.java
+++ b/telephony/java/android/telephony/UiccCardInfo.java
@@ -20,21 +20,27 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
import java.util.Objects;
/**
* The UiccCardInfo represents information about a currently inserted UICC or embedded eUICC.
*/
public final class UiccCardInfo implements Parcelable {
-
private final boolean mIsEuicc;
private final int mCardId;
private final String mEid;
private final String mIccId;
- private final int mSlotIndex;
+ private final int mPhysicalSlotIndex;
private final boolean mIsRemovable;
+ private final boolean mIsMultipleEnabledProfilesSupported;
+ private final List<UiccPortInfo> mPortList;
+ private boolean mIccIdAccessRestricted = false;
- public static final @android.annotation.NonNull Creator<UiccCardInfo> CREATOR = new Creator<UiccCardInfo>() {
+ public static final @NonNull Creator<UiccCardInfo> CREATOR = new Creator<UiccCardInfo>() {
@Override
public UiccCardInfo createFromParcel(Parcel in) {
return new UiccCardInfo(in);
@@ -47,22 +53,29 @@
};
private UiccCardInfo(Parcel in) {
- mIsEuicc = in.readByte() != 0;
+ mIsEuicc = in.readBoolean();
mCardId = in.readInt();
- mEid = in.readString();
- mIccId = in.readString();
- mSlotIndex = in.readInt();
- mIsRemovable = in.readByte() != 0;
+ mEid = in.readString8();
+ mIccId = in.readString8();
+ mPhysicalSlotIndex = in.readInt();
+ mIsRemovable = in.readBoolean();
+ mIsMultipleEnabledProfilesSupported = in.readBoolean();
+ mPortList = new ArrayList<UiccPortInfo>();
+ in.readTypedList(mPortList, UiccPortInfo.CREATOR);
+ mIccIdAccessRestricted = in.readBoolean();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeByte((byte) (mIsEuicc ? 1 : 0));
+ dest.writeBoolean(mIsEuicc);
dest.writeInt(mCardId);
- dest.writeString(mEid);
- dest.writeString(mIccId);
- dest.writeInt(mSlotIndex);
- dest.writeByte((byte) (mIsRemovable ? 1 : 0));
+ dest.writeString8(mEid);
+ dest.writeString8(mIccId);
+ dest.writeInt(mPhysicalSlotIndex);
+ dest.writeBoolean(mIsRemovable);
+ dest.writeBoolean(mIsMultipleEnabledProfilesSupported);
+ dest.writeTypedList(mPortList, flags);
+ dest.writeBoolean(mIccIdAccessRestricted);
}
@Override
@@ -71,20 +84,34 @@
}
/**
+ * Construct a UiccCardInfo.
+ *
+ * @param isEuicc is a flag to check is eUICC or not
+ * @param cardId is unique ID used to identify a UiccCard.
+ * @param eid is unique eUICC Identifier
+ * @param physicalSlotIndex is unique index referring to a physical SIM slot.
+ * @param isRemovable is a flag to check is removable or embedded
+ * @param isMultipleEnabledProfilesSupported is a flag to check is MEP enabled or not
+ * @param portList has the information regarding port, ICCID and its active status
+ *
* @hide
*/
- public UiccCardInfo(boolean isEuicc, int cardId, String eid, String iccId, int slotIndex,
- boolean isRemovable) {
+ public UiccCardInfo(boolean isEuicc, int cardId, String eid, int physicalSlotIndex,
+ boolean isRemovable, boolean isMultipleEnabledProfilesSupported,
+ @NonNull List<UiccPortInfo> portList) {
this.mIsEuicc = isEuicc;
this.mCardId = cardId;
this.mEid = eid;
- this.mIccId = iccId;
- this.mSlotIndex = slotIndex;
+ this.mIccId = null;
+ this.mPhysicalSlotIndex = physicalSlotIndex;
this.mIsRemovable = isRemovable;
+ this.mIsMultipleEnabledProfilesSupported = isMultipleEnabledProfilesSupported;
+ this.mPortList = portList;
}
/**
* Return whether the UICC is an eUICC.
+ *
* @return true if the UICC is an eUICC.
*/
public boolean isEuicc() {
@@ -119,40 +146,83 @@
* <p>
* Note that this field may be omitted if the caller does not have the correct permissions
* (see {@link TelephonyManager#getUiccCardsInfo()}).
+ *
+ * @deprecated with support for MEP(multiple enabled profile), a SIM card can have more than one
+ * ICCID active at the same time.Instead use {@link UiccPortInfo#getIccId()} to retrieve ICCID.
+ * To find {@link UiccPortInfo} use {@link UiccCardInfo#getPorts()}
+ *
+ * @throws UnsupportedOperationException if the calling app's target SDK is T and beyond.
*/
@Nullable
+ @Deprecated
public String getIccId() {
- return mIccId;
+ if (mIccIdAccessRestricted) {
+ throw new UnsupportedOperationException("getIccId from UiccPortInfo");
+ }
+ //always return ICCID from first port.
+ return getPorts().stream().findFirst().get().getIccId();
}
/**
* Gets the slot index for the slot that the UICC is currently inserted in.
+ *
+ * @deprecated use {@link #getPhysicalSlotIndex()}
*/
+ @Deprecated
public int getSlotIndex() {
- return mSlotIndex;
+ return mPhysicalSlotIndex;
}
/**
- * Returns a copy of the UiccCardinfo with the EID and ICCID set to null. These values are
- * generally private and require carrier privileges to view.
- *
- * @hide
+ * Gets the physical slot index for the slot that the UICC is currently inserted in.
*/
- @NonNull
- public UiccCardInfo getUnprivileged() {
- return new UiccCardInfo(mIsEuicc, mCardId, null, null, mSlotIndex, mIsRemovable);
+ public int getPhysicalSlotIndex() {
+ return mPhysicalSlotIndex;
}
/**
* Return whether the UICC or eUICC is removable.
* <p>
* UICCs are generally removable, but eUICCs may be removable or built in to the device.
+ *
* @return true if the UICC or eUICC is removable
*/
public boolean isRemovable() {
return mIsRemovable;
}
+ /*
+ * Whether the UICC card supports multiple enable profile(MEP)
+ * UICCs are generally MEP disabled, there can be only one active profile on the physical
+ * sim card.
+ *
+ * @return {@code true} if the eUICC is supporting multiple enabled profile(MEP).
+ */
+ public boolean isMultipleEnabledProfilesSupported() {
+ return mIsMultipleEnabledProfilesSupported;
+ }
+
+ /**
+ * Get information regarding port, ICCID and its active status.
+ *
+ * @return Collection of {@link UiccPortInfo}
+ */
+ public @NonNull Collection<UiccPortInfo> getPorts() {
+ return Collections.unmodifiableList(mPortList);
+ }
+
+ /**
+ * if the flag is set to {@code true} the calling app is not allowed to access deprecated
+ * {@link #getIccId()}
+ * @param iccIdAccessRestricted is the flag to check if app is allowed to access ICCID
+ *
+ * @hide
+ */
+ public void setIccIdAccessRestricted(boolean iccIdAccessRestricted) {
+ this.mIccIdAccessRestricted = iccIdAccessRestricted;
+ }
+
+
@Override
public boolean equals(Object obj) {
if (this == obj) {
@@ -167,13 +237,16 @@
&& (mCardId == that.mCardId)
&& (Objects.equals(mEid, that.mEid))
&& (Objects.equals(mIccId, that.mIccId))
- && (mSlotIndex == that.mSlotIndex)
- && (mIsRemovable == that.mIsRemovable));
+ && (mPhysicalSlotIndex == that.mPhysicalSlotIndex)
+ && (mIsRemovable == that.mIsRemovable)
+ && (mIsMultipleEnabledProfilesSupported == that.mIsMultipleEnabledProfilesSupported)
+ && (Objects.equals(mPortList, that.mPortList)));
}
@Override
public int hashCode() {
- return Objects.hash(mIsEuicc, mCardId, mEid, mIccId, mSlotIndex, mIsRemovable);
+ return Objects.hash(mIsEuicc, mCardId, mEid, mIccId, mPhysicalSlotIndex, mIsRemovable,
+ mIsMultipleEnabledProfilesSupported, mPortList);
}
@Override
@@ -185,11 +258,17 @@
+ ", mEid="
+ mEid
+ ", mIccId="
- + mIccId
- + ", mSlotIndex="
- + mSlotIndex
+ + SubscriptionInfo.givePrintableIccid(mIccId)
+ + ", mPhysicalSlotIndex="
+ + mPhysicalSlotIndex
+ ", mIsRemovable="
+ mIsRemovable
+ + ", mIsMultipleEnabledProfilesSupported="
+ + mIsMultipleEnabledProfilesSupported
+ + ", mPortList="
+ + mPortList
+ + ", mIccIdAccessRestricted="
+ + mIccIdAccessRestricted
+ ")";
}
-}
+}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/UiccPortInfo.aidl b/telephony/java/android/telephony/UiccPortInfo.aidl
new file mode 100644
index 0000000..7fff4ba
--- /dev/null
+++ b/telephony/java/android/telephony/UiccPortInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+parcelable UiccPortInfo;
diff --git a/telephony/java/android/telephony/UiccPortInfo.java b/telephony/java/android/telephony/UiccPortInfo.java
new file mode 100644
index 0000000..d1838c0
--- /dev/null
+++ b/telephony/java/android/telephony/UiccPortInfo.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * UiccPortInfo class represents information about a single port contained on {@link UiccCardInfo}.
+ * Per GSMA SGP.22 V3.0, a port is a logical entity to which an active UICC profile can be bound on
+ * a UICC card. If UICC supports 2 ports, then the port index is numbered 0,1.
+ * Each port index is unique within an UICC, but not necessarily unique across UICC’s.
+ * For UICC's does not support MEP(Multi-enabled profile), just return the default port index 0.
+ */
+public final class UiccPortInfo implements Parcelable{
+ private final String mIccId;
+ private final int mPortIndex;
+ private final int mLogicalSlotIndex;
+ private final boolean mIsActive;
+
+ /**
+ * A redacted String if caller does not have permission to read ICCID.
+ */
+ public static final String ICCID_REDACTED = "FFFFFFFFFFFFFFFFFFFF";
+
+ public static final @NonNull Creator<UiccPortInfo> CREATOR =
+ new Creator<UiccPortInfo>() {
+ @Override
+ public UiccPortInfo createFromParcel(Parcel in) {
+ return new UiccPortInfo(in);
+ }
+ @Override
+ public UiccPortInfo[] newArray(int size) {
+ return new UiccPortInfo[size];
+ }
+ };
+
+ private UiccPortInfo(Parcel in) {
+ mIccId = in.readString8();
+ mPortIndex = in.readInt();
+ mLogicalSlotIndex = in.readInt();
+ mIsActive = in.readBoolean();
+ }
+
+ @Override
+ public void writeToParcel(@Nullable Parcel dest, int flags) {
+ dest.writeString8(mIccId);
+ dest.writeInt(mPortIndex);
+ dest.writeInt(mLogicalSlotIndex);
+ dest.writeBoolean(mIsActive);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Construct a UiccPortInfo.
+ *
+ * @param iccId The ICCID of the profile.
+ * @param portIndex The port index is an enumeration of the ports available on the UICC.
+ * @param logicalSlotIndex is unique index referring to a logical SIM slot.
+ * @param isActive is flag to check if port was tied to a modem stack.
+ *
+ * @hide
+ */
+ public UiccPortInfo(String iccId, int portIndex, int logicalSlotIndex, boolean isActive) {
+ this.mIccId = iccId;
+ this.mPortIndex = portIndex;
+ this.mLogicalSlotIndex = logicalSlotIndex;
+ this.mIsActive = isActive;
+ }
+
+ /**
+ * Get the ICCID of the profile associated with this port.
+ * If this port is not {@link #isActive()}, returns {@code null}.
+ * If the caller does not have access to the ICCID for this port, it will be redacted and
+ * {@link #ICCID_REDACTED} will be returned.
+ */
+ public @Nullable String getIccId() {
+ return mIccId;
+ }
+
+ /**
+ * The port index is an enumeration of the ports available on the UICC.
+ * Example: if eUICC1 supports 2 ports, then the port index is numbered 0,1.
+ * Each port index is unique within an UICC, but not necessarily unique across UICC’s.
+ * For UICC's does not support MEP(Multi-enabled profile), just return the default port index 0.
+ */
+ @IntRange(from = 0)
+ public int getPortIndex() {
+ return mPortIndex;
+ }
+
+ /**
+ * @return {@code true} if port was tied to a modem stack.
+ */
+ public boolean isActive() {
+ return mIsActive;
+ }
+
+ /**
+ * Gets logical slot index for the slot that the UICC is currently attached.
+ * Logical slot index or ID: unique index referring to a logical SIM slot.
+ * Logical slot IDs start at 0 and go up depending on the number of supported active slots on
+ * a device.
+ * For example, a dual-SIM device typically has slot 0 and slot 1.
+ * If a device has multiple physical slots but only supports one active slot,
+ * it will have only the logical slot ID 0.
+ *
+ * @return the logical slot index for UICC port, if there is no logical slot index it returns
+ * {@link SubscriptionManager#INVALID_SIM_SLOT_INDEX}
+ */
+ @IntRange(from = 0)
+ public int getLogicalSlotIndex() {
+ return mLogicalSlotIndex;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ UiccPortInfo that = (UiccPortInfo) obj;
+ return (Objects.equals(mIccId, that.mIccId))
+ && (mPortIndex == that.mPortIndex)
+ && (mLogicalSlotIndex == that.mLogicalSlotIndex)
+ && (mIsActive == that.mIsActive);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mIccId, mPortIndex, mLogicalSlotIndex, mIsActive);
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return "UiccPortInfo (isActive="
+ + mIsActive
+ + ", iccId="
+ + SubscriptionInfo.givePrintableIccid(mIccId)
+ + ", portIndex="
+ + mPortIndex
+ + ", mLogicalSlotIndex="
+ + mLogicalSlotIndex
+ + ")";
+ }
+}
diff --git a/telephony/java/android/telephony/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java
index a0e949a..2b1c8c8 100644
--- a/telephony/java/android/telephony/UiccSlotInfo.java
+++ b/telephony/java/android/telephony/UiccSlotInfo.java
@@ -24,6 +24,10 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
import java.util.Objects;
/**
@@ -64,8 +68,10 @@
private final int mLogicalSlotIdx;
private final boolean mIsExtendedApduSupported;
private final boolean mIsRemovable;
+ private final List<UiccPortInfo> mPortList;
+ private boolean mLogicalSlotAccessRestricted = false;
- public static final @android.annotation.NonNull Creator<UiccSlotInfo> CREATOR = new Creator<UiccSlotInfo>() {
+ public static final @NonNull Creator<UiccSlotInfo> CREATOR = new Creator<UiccSlotInfo>() {
@Override
public UiccSlotInfo createFromParcel(Parcel in) {
return new UiccSlotInfo(in);
@@ -78,24 +84,29 @@
};
private UiccSlotInfo(Parcel in) {
- mIsActive = in.readByte() != 0;
- mIsEuicc = in.readByte() != 0;
- mCardId = in.readString();
+ mIsActive = in.readBoolean();
+ mIsEuicc = in.readBoolean();
+ mCardId = in.readString8();
mCardStateInfo = in.readInt();
mLogicalSlotIdx = in.readInt();
- mIsExtendedApduSupported = in.readByte() != 0;
- mIsRemovable = in.readByte() != 0;
+ mIsExtendedApduSupported = in.readBoolean();
+ mIsRemovable = in.readBoolean();
+ mPortList = new ArrayList<UiccPortInfo>();
+ in.readTypedList(mPortList, UiccPortInfo.CREATOR);
+ mLogicalSlotAccessRestricted = in.readBoolean();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeByte((byte) (mIsActive ? 1 : 0));
- dest.writeByte((byte) (mIsEuicc ? 1 : 0));
- dest.writeString(mCardId);
+ dest.writeBoolean(mIsActive);
+ dest.writeBoolean(mIsEuicc);
+ dest.writeString8(mCardId);
dest.writeInt(mCardStateInfo);
dest.writeInt(mLogicalSlotIdx);
- dest.writeByte((byte) (mIsExtendedApduSupported ? 1 : 0));
- dest.writeByte((byte) (mIsRemovable ? 1 : 0));
+ dest.writeBoolean(mIsExtendedApduSupported);
+ dest.writeBoolean(mIsRemovable);
+ dest.writeTypedList(mPortList, flags);
+ dest.writeBoolean(mLogicalSlotAccessRestricted);
}
@Override
@@ -117,25 +128,42 @@
this.mLogicalSlotIdx = logicalSlotIdx;
this.mIsExtendedApduSupported = isExtendedApduSupported;
this.mIsRemovable = false;
+ this.mPortList = null;
}
/**
+ * Construct a UiccSlotInfo.
* @hide
*/
- public UiccSlotInfo(boolean isActive, boolean isEuicc, String cardId,
- @CardStateInfo int cardStateInfo, int logicalSlotIdx, boolean isExtendedApduSupported,
- boolean isRemovable) {
- this.mIsActive = isActive;
+ public UiccSlotInfo(boolean isEuicc, String cardId,
+ @CardStateInfo int cardStateInfo, boolean isExtendedApduSupported,
+ boolean isRemovable, @NonNull List<UiccPortInfo> portList) {
+ this.mIsActive = portList.get(0).isActive();
this.mIsEuicc = isEuicc;
this.mCardId = cardId;
this.mCardStateInfo = cardStateInfo;
- this.mLogicalSlotIdx = logicalSlotIdx;
+ this.mLogicalSlotIdx = portList.get(0).getLogicalSlotIndex();
this.mIsExtendedApduSupported = isExtendedApduSupported;
this.mIsRemovable = isRemovable;
+ this.mPortList = portList;
}
+ /**
+ * @deprecated There is no longer isActive state for each slot because ports belonging
+ * to the physical slot could have different states
+ * we instead use {@link UiccPortInfo#isActive()}
+ * To get UiccPortInfo use {@link UiccSlotInfo#getPorts()}
+ *
+ * @return {@code true} if status is active.
+ * @throws UnsupportedOperationException if the calling app's target SDK is T and beyond.
+ */
+ @Deprecated
public boolean getIsActive() {
- return mIsActive;
+ if (mLogicalSlotAccessRestricted) {
+ throw new UnsupportedOperationException("get port status from UiccPortInfo");
+ }
+ //always return status from first port.
+ return getPorts().stream().findFirst().get().isActive();
}
public boolean getIsEuicc() {
@@ -159,8 +187,21 @@
return mCardStateInfo;
}
+ /**
+ * @deprecated There is no longer getLogicalSlotIndex
+ * There is no longer getLogicalSlotIdx as each port belonging to this physical slot could have
+ * different logical slot index. Use {@link UiccPortInfo#getLogicalSlotIndex()} instead
+ *
+ * @throws UnsupportedOperationException if the calling app's target SDK is T and beyond.
+ */
+ @Deprecated
public int getLogicalSlotIdx() {
- return mLogicalSlotIdx;
+ if (mLogicalSlotAccessRestricted) {
+ throw new UnsupportedOperationException("get logical slot index from UiccPortInfo");
+ }
+ //always return logical slot index from first port.
+ //portList always have at least one element.
+ return getPorts().stream().findFirst().get().getLogicalSlotIndex();
}
/**
@@ -170,16 +211,37 @@
return mIsExtendedApduSupported;
}
- /**
+ /**
* Return whether the UICC slot is for a removable UICC.
* <p>
* UICCs are generally removable, but eUICCs may be removable or built in to the device.
+ *
* @return true if the slot is for removable UICCs
*/
public boolean isRemovable() {
return mIsRemovable;
}
+ /**
+ * Get Information regarding port, iccid and its active status.
+ *
+ * @return Collection of {@link UiccPortInfo}
+ */
+ public @NonNull Collection<UiccPortInfo> getPorts() {
+ return Collections.unmodifiableList(mPortList);
+ }
+
+ /**
+ * Set the flag to check compatibility of the calling app's target SDK is T and beyond.
+ *
+ * @param logicalSlotAccessRestricted is the flag to check compatibility.
+ *
+ * @hide
+ */
+ public void setLogicalSlotAccessRestricted(boolean logicalSlotAccessRestricted) {
+ this.mLogicalSlotAccessRestricted = logicalSlotAccessRestricted;
+ }
+
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
@@ -196,20 +258,14 @@
&& (mCardStateInfo == that.mCardStateInfo)
&& (mLogicalSlotIdx == that.mLogicalSlotIdx)
&& (mIsExtendedApduSupported == that.mIsExtendedApduSupported)
- && (mIsRemovable == that.mIsRemovable);
+ && (mIsRemovable == that.mIsRemovable)
+ && (Objects.equals(mPortList, that.mPortList));
}
@Override
public int hashCode() {
- int result = 1;
- result = 31 * result + (mIsActive ? 1 : 0);
- result = 31 * result + (mIsEuicc ? 1 : 0);
- result = 31 * result + Objects.hashCode(mCardId);
- result = 31 * result + mCardStateInfo;
- result = 31 * result + mLogicalSlotIdx;
- result = 31 * result + (mIsExtendedApduSupported ? 1 : 0);
- result = 31 * result + (mIsRemovable ? 1 : 0);
- return result;
+ return Objects.hash(mIsActive, mIsEuicc, mCardId, mCardStateInfo, mLogicalSlotIdx,
+ mIsExtendedApduSupported, mIsRemovable, mPortList);
}
@NonNull
@@ -229,6 +285,10 @@
+ mIsExtendedApduSupported
+ ", mIsRemovable="
+ mIsRemovable
+ + ", mPortList="
+ + mPortList
+ + ", mLogicalSlotAccessRestricted="
+ + mLogicalSlotAccessRestricted
+ ")";
}
}
diff --git a/telephony/java/android/telephony/UiccSlotMapping.aidl b/telephony/java/android/telephony/UiccSlotMapping.aidl
new file mode 100644
index 0000000..3b19499
--- /dev/null
+++ b/telephony/java/android/telephony/UiccSlotMapping.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+parcelable UiccSlotMapping;
diff --git a/telephony/java/android/telephony/UiccSlotMapping.java b/telephony/java/android/telephony/UiccSlotMapping.java
new file mode 100644
index 0000000..87e7acd
--- /dev/null
+++ b/telephony/java/android/telephony/UiccSlotMapping.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * <p>Provides information for a SIM slot mapping, which establishes a unique mapping between a
+ * logical SIM slot and a physical SIM slot and port index. A logical SIM slot represents a
+ * potentially active SIM slot, where a physical SIM slot and port index represent a hardware SIM
+ * slot and port (capable of having an active profile) which can be mapped to a logical sim slot.
+ * <p>It contains the following parameters:
+ * <ul>
+ * <li>Port index: unique index referring to a port belonging to the physical SIM slot.
+ * If the SIM does not support multiple enabled profiles, the port index is default index 0.</li>
+ * <li>Physical slot index: unique index referring to a physical SIM slot. Physical slot IDs start
+ * at 0 and go up depending on the number of physical slots on the device.
+ * This differs from the number of logical slots a device has, which corresponds to the number of
+ * active slots a device is capable of using. For example, a device which switches between dual-SIM
+ * and single-SIM mode may always have two physical slots, but in single-SIM mode it will have only
+ * one logical slot.</li>
+ * <li>Logical slot index: unique index referring to a logical SIM slot, Logical slot IDs start at 0
+ * and go up depending on the number of supported active slots on a device.
+ * For example, a dual-SIM device typically has slot 0 and slot 1. If a device has multiple physical
+ * slots but only supports one active slot, it will have only the logical slot ID 0</li>
+ * </ul>
+ *
+ * <p> This configurations tells a specific logical slot is mapped to a port from an actual physical
+ * sim slot @see <a href="https://developer.android.com/guide/topics/connectivity/telecom/telephony-ids">the Android Developer Site</a>
+ * for more information.
+ * @hide
+ */
+@SystemApi
+public final class UiccSlotMapping implements Parcelable {
+ private final int mPortIndex;
+ private final int mPhysicalSlotIndex;
+ private final int mLogicalSlotIndex;
+
+ public static final @NonNull Creator<UiccSlotMapping> CREATOR =
+ new Creator<UiccSlotMapping>() {
+ @Override
+ public UiccSlotMapping createFromParcel(Parcel in) {
+ return new UiccSlotMapping(in);
+ }
+
+ @Override
+ public UiccSlotMapping[] newArray(int size) {
+ return new UiccSlotMapping[size];
+ }
+ };
+
+ private UiccSlotMapping(Parcel in) {
+ mPortIndex = in.readInt();
+ mPhysicalSlotIndex = in.readInt();
+ mLogicalSlotIndex = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(@Nullable Parcel dest, int flags) {
+ dest.writeInt(mPortIndex);
+ dest.writeInt(mPhysicalSlotIndex);
+ dest.writeInt(mLogicalSlotIndex);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ *
+ * @param portIndex The port index is an enumeration of the ports available on the UICC.
+ * @param physicalSlotIndex is unique index referring to a physical SIM slot.
+ * @param logicalSlotIndex is unique index referring to a logical SIM slot.
+ *
+ * @hide
+ */
+ public UiccSlotMapping(int portIndex, int physicalSlotIndex, int logicalSlotIndex) {
+ this.mPortIndex = portIndex;
+ this.mPhysicalSlotIndex = physicalSlotIndex;
+ this.mLogicalSlotIndex = logicalSlotIndex;
+ }
+
+ /**
+ * Port index is the unique index referring to a port belonging to the physical SIM slot.
+ * If the SIM does not support multiple enabled profiles, the port index is default index 0.
+ *
+ * @return port index.
+ */
+ @IntRange(from = 0)
+ public int getPortIndex() {
+ return mPortIndex;
+ }
+
+ /**
+ * Gets the physical slot index for the slot that the UICC is currently inserted in.
+ *
+ * @return physical slot index which is the index of actual physical UICC slot.
+ */
+ @IntRange(from = 0)
+ public int getPhysicalSlotIndex() {
+ return mPhysicalSlotIndex;
+ }
+
+ /**
+ * Gets logical slot index for the slot that the UICC is currently attached.
+ * Logical slot index is the unique index referring to a logical slot(logical modem stack).
+ *
+ * @return logical slot index;
+ */
+ @IntRange(from = 0)
+ public int getLogicalSlotIndex() {
+ return mLogicalSlotIndex;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ UiccSlotMapping that = (UiccSlotMapping) obj;
+ return (mPortIndex == that.mPortIndex)
+ && (mPhysicalSlotIndex == that.mPhysicalSlotIndex)
+ && (mLogicalSlotIndex == that.mLogicalSlotIndex);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPortIndex, mPhysicalSlotIndex, mLogicalSlotIndex);
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return "UiccSlotMapping (mPortIndex="
+ + mPortIndex
+ + ", mPhysicalSlotIndex="
+ + mPhysicalSlotIndex
+ + ", mLogicalSlotIndex="
+ + mLogicalSlotIndex
+ + ")";
+ }
+}
diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
index e1aec0a..ab35d77 100644
--- a/telephony/java/android/telephony/euicc/EuiccCardManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -17,6 +17,7 @@
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
@@ -24,6 +25,7 @@
import android.os.RemoteException;
import android.service.euicc.EuiccProfileInfo;
import android.telephony.TelephonyFrameworkInitializer;
+import android.telephony.TelephonyManager;
import android.util.Log;
import com.android.internal.telephony.euicc.IAuthenticateServerCallback;
@@ -122,7 +124,6 @@
/** Result code indicating the caller is not the active LPA. */
public static final int RESULT_CALLER_NOT_ALLOWED = -3;
-
/**
* Callback to receive the result of an eUICC card API.
*
@@ -220,12 +221,48 @@
* @param refresh Whether sending the REFRESH command to modem.
* @param executor The executor through which the callback should be invoked.
* @param callback The callback to get the result code.
+ *
+ * @deprecated instead use {@link #disableProfile(String, String, int, boolean, Executor,
+ * ResultCallback)}
*/
+ @Deprecated
public void disableProfile(String cardId, String iccid, boolean refresh,
@CallbackExecutor Executor executor, ResultCallback<Void> callback) {
try {
getIEuiccCardController().disableProfile(mContext.getOpPackageName(), cardId, iccid,
- refresh, new IDisableProfileCallback.Stub() {
+ TelephonyManager.DEFAULT_PORT_INDEX, refresh,
+ new IDisableProfileCallback.Stub() {
+ @Override
+ public void onComplete(int resultCode) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, null));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ });
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling disableProfile", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ /**
+ * Disables the profile of the given ICCID.
+ *
+ * @param cardId The Id of the eUICC.
+ * @param iccid The iccid of the profile.
+ * @param portIndex the Port index is the unique index referring to a port.
+ * @param refresh Whether sending the REFRESH command to modem.
+ * @param executor The executor through which the callback should be invoked.
+ * @param callback The callback to get the result code.
+ */
+ public void disableProfile(@Nullable String cardId, @Nullable String iccid, int portIndex,
+ boolean refresh, @NonNull @CallbackExecutor Executor executor,
+ @NonNull ResultCallback<Void> callback) {
+ try {
+ getIEuiccCardController().disableProfile(mContext.getOpPackageName(), cardId, iccid,
+ portIndex, refresh, new IDisableProfileCallback.Stub() {
@Override
public void onComplete(int resultCode) {
final long token = Binder.clearCallingIdentity();
@@ -251,12 +288,51 @@
* @param refresh Whether sending the REFRESH command to modem.
* @param executor The executor through which the callback should be invoked.
* @param callback The callback to get the result code and the EuiccProfileInfo enabled.
+ *
+ * @deprecated instead use {@link #switchToProfile(String, String, int, boolean, Executor,
+ * ResultCallback)}
*/
+ @Deprecated
public void switchToProfile(String cardId, String iccid, boolean refresh,
@CallbackExecutor Executor executor, ResultCallback<EuiccProfileInfo> callback) {
try {
getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), cardId, iccid,
- refresh, new ISwitchToProfileCallback.Stub() {
+ TelephonyManager.DEFAULT_PORT_INDEX, refresh,
+ new ISwitchToProfileCallback.Stub() {
+ @Override
+ public void onComplete(int resultCode, EuiccProfileInfo profile) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onComplete(resultCode, profile));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ });
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling switchToProfile", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Switches from the current profile to another profile. The current profile will be disabled
+ * and the specified profile will be enabled. Here portIndex specifies on which port the
+ * profile is to be enabled.
+ *
+ * @param cardId The Id of the eUICC.
+ * @param iccid The iccid of the profile to switch to.
+ * @param portIndex The Port index is the unique index referring to a port.
+ * @param refresh Whether sending the REFRESH command to modem.
+ * @param executor The executor through which the callback should be invoked.
+ * @param callback The callback to get the result code and the EuiccProfileInfo enabled.
+ */
+ public void switchToProfile(@Nullable String cardId, @Nullable String iccid, int portIndex,
+ boolean refresh, @NonNull @CallbackExecutor Executor executor,
+ @NonNull ResultCallback<EuiccProfileInfo> callback) {
+ try {
+ getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), cardId, iccid,
+ portIndex, refresh, new ISwitchToProfileCallback.Stub() {
@Override
public void onComplete(int resultCode, EuiccProfileInfo profile) {
final long token = Binder.clearCallingIdentity();
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index 2edb564c..45022a6 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -1418,4 +1418,22 @@
.getEuiccControllerService()
.get());
}
+
+ /**
+ * Returns whether the passing portIndex is available.
+ * A port is available if it has no profiles enabled on it or calling app has carrier privilege
+ * over the profile installed on the selected port.
+ * Always returns false if the cardId is a physical card.
+ *
+ * @param portIndex is an enumeration of the ports available on the UICC.
+ * @return {@code true} if port is available
+ */
+ public boolean isSimPortAvailable(int portIndex) {
+ try {
+ return getIEuiccController().isSimPortAvailable(mCardId, portIndex,
+ mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 6493772..a900c84 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -304,4 +304,13 @@
int setDeviceToDeviceStatusSharing(int sharing, int subId);
int setDeviceToDeviceStatusSharingContacts(String contacts, int subscriptionId);
+
+ String getPhoneNumber(int subId, int source,
+ String callingPackage, String callingFeatureId);
+
+ String getPhoneNumberFromFirstAvailableSource(int subId,
+ String callingPackage, String callingFeatureId);
+
+ void setPhoneNumber(int subId, int source, String number,
+ String callingPackage, String callingFeatureId);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 2e59fc7..dbc6cb6 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -77,6 +77,7 @@
import android.telephony.UiccCardInfo;
import android.telephony.UiccSlotInfo;
+import android.telephony.UiccSlotMapping;
/**
* Interface used to interact with the phone. Mostly this is used by the
@@ -1729,17 +1730,35 @@
* @return UiccSlotInfo array.
* @hide
*/
- UiccSlotInfo[] getUiccSlotsInfo();
+ UiccSlotInfo[] getUiccSlotsInfo(String callingPackage);
/**
* Map logicalSlot to physicalSlot, and activate the physicalSlot if it is inactive.
* @param physicalSlots Index i in the array representing physical slot for phone i. The array
* size should be same as getPhoneCount().
+ * @deprecated Use {@link #setSimSlotMapping(in List<UiccSlotMapping> slotMapping)} instead.
* @return boolean Return true if the switch succeeds, false if the switch fails.
*/
boolean switchSlots(in int[] physicalSlots);
/**
+ * Maps the logical slots to the SlotPortMapping which consist of both physical slot index and
+ * port index. Logical slot is the slot that is seen by modem. Physical slot is the actual
+ * physical slot. Port index is the index (enumerated value) for the associated port available
+ * on the SIM. Each physical slot can have multiple ports which enables multi-enabled profile
+ * (MEP). If eUICC physical slot supports 2 ports, then the port index is numbered 0,1 and if
+ * eUICC2 supports 4 ports then the port index is numbered 0,1,2,3. Each portId is unique within
+ * a UICC physical slot but not necessarily unique across UICC’s. SEP(Single enabled profile)
+ * eUICC and non-eUICC will only have port Index 0.
+ *
+ * Logical slots that are already mapped to the requested SlotPortMapping are not impacted.
+ * @param slotMapping Index i in the list representing slot mapping for phone i.
+ *
+ * @return {@code true} if the switch succeeds, {@code false} if the switch fails.
+ */
+ boolean setSimSlotMapping(in List<UiccSlotMapping> slotMapping);
+
+ /**
* Returns whether mobile data roaming is enabled on the subscription with id {@code subId}.
*
* @param subId the subscription id
@@ -2117,7 +2136,7 @@
/**
* Get the mapping from logical slots to physical slots.
*/
- int[] getSlotsMapping();
+ int[] getSlotsMapping(String callingPackage);
/**
* Get the IRadio HAL Version encoded as 100 * MAJOR_VERSION + MINOR_VERSION or -1 if unknown
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 3a99f0e0..f650246 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -171,6 +171,8 @@
public static final String SLOT_KEY = "slot";
+ public static final String PORT_KEY = "port";
+
// FIXME: This is used to pass a subId via intents, we need to look at its usage, which is
// FIXME: extensive, and see if this should be an array of all active subId's or ...?
/**
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
index e33f44c..c717c09 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
@@ -45,10 +45,10 @@
in IGetAllProfilesCallback callback);
oneway void getProfile(String callingPackage, String cardId, String iccid,
in IGetProfileCallback callback);
- oneway void disableProfile(String callingPackage, String cardId, String iccid, boolean refresh,
- in IDisableProfileCallback callback);
- oneway void switchToProfile(String callingPackage, String cardId, String iccid, boolean refresh,
- in ISwitchToProfileCallback callback);
+ oneway void disableProfile(String callingPackage, String cardId, String iccid, int portIndex,
+ boolean refresh, in IDisableProfileCallback callback);
+ oneway void switchToProfile(String callingPackage, String cardId, String iccid, int portIndex,
+ boolean refresh, in ISwitchToProfileCallback callback);
oneway void setNickname(String callingPackage, String cardId, String iccid, String nickname,
in ISetNicknameCallback callback);
oneway void deleteProfile(String callingPackage, String cardId, String iccid,
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index 35e8a12..944ce348 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -51,4 +51,5 @@
void setSupportedCountries(boolean isSupported, in List<String> countriesList);
List<String> getSupportedCountries(boolean isSupported);
boolean isSupportedCountry(String countryIso);
+ boolean isSimPortAvailable(int cardId, int portIndex, String callingPackage);
}
diff --git a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
index 5b44dba..21c3f76 100644
--- a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
+++ b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
@@ -23,6 +23,7 @@
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Build;
+import android.telephony.UiccPortInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.GsmAlphabet;
@@ -44,8 +45,7 @@
static final int FPLMN_BYTE_SIZE = 3;
// ICCID used for tests by some OEMs
- // TODO(b/159354974): Replace the constant here with UiccPortInfo.ICCID_REDACTED once ready
- private static final String TEST_ICCID = "FFFFFFFFFFFFFFFFFFFF";
+ public static final String TEST_ICCID = UiccPortInfo.ICCID_REDACTED;
// A table mapping from a number to a hex character for fast encoding hex strings.
private static final char[] HEX_CHARS = {
diff --git a/tests/FlickerTests/AndroidTest.xml b/tests/FlickerTests/AndroidTest.xml
index 896ec9a..566c725 100644
--- a/tests/FlickerTests/AndroidTest.xml
+++ b/tests/FlickerTests/AndroidTest.xml
@@ -16,10 +16,6 @@
<!-- restart launcher to activate TAPL -->
<option name="run-command" value="setprop ro.test_harness 1 ; am force-stop com.google.android.apps.nexuslauncher" />
</target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.DeviceCleaner">
- <!-- reboot the device to teardown any crashed tests -->
- <option name="cleanup-action" value="REBOOT" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true"/>
<option name="test-file-name" value="FlickerTests.apk"/>
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
index 209d1aa..7076a07 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
@@ -17,6 +17,7 @@
package com.android.server.wm.flicker.close
+import android.platform.test.annotations.Presubmit
import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -24,6 +25,8 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -79,6 +82,33 @@
@Test
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
+
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun launcherLayerReplacesApp() {
+ // This test doesn't work in shell transitions because of b/206086894
+ assumeFalse(isShellTransitionsEnabled)
+ super.launcherLayerReplacesApp()
+ }
+
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun entireScreenCovered() {
+ // This test doesn't work in shell transitions because of b/206086894
+ assumeFalse(isShellTransitionsEnabled)
+ super.entireScreenCovered()
+ }
+
companion object {
/**
* Creates the test configurations.
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
index ac557cf..b5d01ef 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
@@ -16,6 +16,7 @@
package com.android.server.wm.flicker.close
+import android.platform.test.annotations.Presubmit
import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -23,6 +24,8 @@
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -78,6 +81,33 @@
@Test
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
+
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun launcherLayerReplacesApp() {
+ // This test doesn't work in shell transitions because of b/206086894
+ assumeFalse(isShellTransitionsEnabled)
+ super.launcherLayerReplacesApp()
+ }
+
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun entireScreenCovered() {
+ // This test doesn't work in shell transitions because of b/206086894
+ assumeFalse(isShellTransitionsEnabled)
+ super.entireScreenCovered()
+ }
+
companion object {
/**
* Creates the test configurations.
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
index c7dfbf8..f12e4ae 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
@@ -30,6 +30,7 @@
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.entireScreenCovered
import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.navBarLayerIsVisible
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.navBarWindowIsVisible
@@ -37,6 +38,7 @@
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsVisible
import com.android.server.wm.traces.common.FlickerComponentName
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -154,7 +156,11 @@
@Presubmit
@Test
- fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
index 5315da1d..b1bdb31 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
@@ -34,10 +34,12 @@
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.navBarWindowIsVisible
import com.android.server.wm.flicker.entireScreenCovered
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.statusBarLayerIsVisible
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsVisible
import com.android.server.wm.traces.common.FlickerComponentName
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -115,7 +117,11 @@
@Presubmit
@Test
- fun entireScreenCovered() = testSpec.entireScreenCovered()
+ fun entireScreenCovered() {
+ // This test doesn't work in shell transitions because of b/206086894
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.entireScreenCovered()
+ }
@Presubmit
@Test
@@ -153,7 +159,11 @@
@Presubmit
@Test
- fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
index d063b69..d975cf4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
@@ -32,10 +32,12 @@
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.navBarWindowIsVisible
import com.android.server.wm.flicker.entireScreenCovered
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsVisible
import com.android.server.wm.traces.common.FlickerComponentName
-import org.junit.Assume
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -119,20 +121,24 @@
@Presubmit
@Test
fun navBarLayerRotatesAndScales() {
- Assume.assumeFalse(testSpec.isLandscapeOrSeascapeAtStart)
+ assumeFalse(testSpec.isLandscapeOrSeascapeAtStart)
testSpec.navBarLayerRotatesAndScales()
}
@FlakyTest
@Test
fun navBarLayerRotatesAndScales_Flaky() {
- Assume.assumeTrue(testSpec.isLandscapeOrSeascapeAtStart)
+ assumeTrue(testSpec.isLandscapeOrSeascapeAtStart)
testSpec.navBarLayerRotatesAndScales()
}
@Presubmit
@Test
- fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
index b589969..ac90752 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
@@ -34,9 +34,11 @@
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.navBarWindowIsVisible
import com.android.server.wm.flicker.entireScreenCovered
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsVisible
import com.android.server.wm.traces.common.FlickerComponentName
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -124,7 +126,11 @@
@Presubmit
@Test
- fun entireScreenCovered() = testSpec.entireScreenCovered()
+ fun entireScreenCovered() {
+ // This test doesn't work in shell transitions because of b/206086894
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.entireScreenCovered()
+ }
@Presubmit
@Test
@@ -146,7 +152,11 @@
@Presubmit
@Test
- fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
index 7bf0186..cc5d9d2 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
@@ -34,9 +34,11 @@
import com.android.server.wm.flicker.navBarWindowIsVisible
import com.android.server.wm.flicker.entireScreenCovered
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.statusBarLayerIsVisible
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsVisible
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -128,7 +130,11 @@
@Presubmit
@Test
- fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
index 5d8a382..84e78ec 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
@@ -17,10 +17,10 @@
package com.android.server.wm.flicker.ime
import android.app.Instrumentation
-import android.os.SystemProperties
import android.platform.test.annotations.Presubmit
import android.view.Surface
import android.view.WindowManagerPolicyConstants
+import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.wm.flicker.FlickerBuilderProvider
@@ -37,11 +37,13 @@
import com.android.server.wm.flicker.navBarWindowIsVisible
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.entireScreenCovered
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.statusBarLayerIsVisible
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsVisible
import com.android.server.wm.traces.common.FlickerComponentName
-import org.junit.Assume
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -60,8 +62,6 @@
class ReOpenImeWindowTest(private val testSpec: FlickerTestParameter) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val testApp = ImeAppAutoFocusHelper(instrumentation, testSpec.startRotation)
- private val isShellTransitionsEnabled =
- SystemProperties.getBoolean("persist.debug.shell_transit", false)
@FlickerBuilderProvider
fun buildFlicker(): FlickerBuilder {
@@ -101,6 +101,8 @@
@Presubmit
@Test
fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
+ // This test doesn't work in shell transitions because of b/204570898
+ assumeFalse(isShellTransitionsEnabled)
val component = FlickerComponentName("", "RecentTaskScreenshotSurface")
testSpec.assertWm {
this.visibleWindowsShownMoreThanOneConsecutiveEntry(
@@ -114,6 +116,8 @@
@Presubmit
@Test
fun launcherWindowBecomesInvisible() {
+ // This test doesn't work in shell transitions because of b/204574221
+ assumeFalse(isShellTransitionsEnabled)
testSpec.assertWm {
this.isAppWindowVisible(LAUNCHER_COMPONENT)
.then()
@@ -123,12 +127,16 @@
@Presubmit
@Test
- fun imeWindowIsAlwaysVisible() = testSpec.imeWindowIsAlwaysVisible(!isShellTransitionsEnabled)
+ fun imeWindowIsAlwaysVisible() {
+ // This test doesn't work in shell transitions because of b/204570898
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.imeWindowIsAlwaysVisible(!isShellTransitionsEnabled)
+ }
@Presubmit
@Test
fun imeAppWindowVisibilityLegacy() {
- Assume.assumeFalse(isShellTransitionsEnabled)
+ assumeFalse(isShellTransitionsEnabled)
// the app starts visible in live tile, and stays visible for the duration of entering
// and exiting overview. However, legacy transitions seem to have a bug which causes
// everything to restart during the test, so expect the app to disappear and come back.
@@ -143,10 +151,10 @@
}
}
- @Presubmit
+ @FlakyTest(bugId = 204570898)
@Test
fun imeAppWindowVisibility() {
- Assume.assumeTrue(isShellTransitionsEnabled)
+ assumeTrue(isShellTransitionsEnabled)
// the app starts visible in live tile, and stays visible for the duration of entering
// and exiting overview. Since we log 1x per frame, sometimes the activity visibility
// and the app visibility are updated together, sometimes not, thus ignore activity
@@ -172,7 +180,7 @@
@Presubmit
@Test
fun imeLayerIsBecomesVisibleLegacy() {
- Assume.assumeFalse(isShellTransitionsEnabled)
+ assumeFalse(isShellTransitionsEnabled)
testSpec.assertLayers {
this.isVisible(FlickerComponentName.IME)
.then()
@@ -182,10 +190,10 @@
}
}
- @Presubmit
+ @FlakyTest(bugId = 204570898)
@Test
fun imeLayerIsBecomesVisible() {
- Assume.assumeTrue(isShellTransitionsEnabled)
+ assumeTrue(isShellTransitionsEnabled)
testSpec.assertLayers {
this.isVisible(FlickerComponentName.IME)
}
@@ -194,6 +202,8 @@
@Presubmit
@Test
fun appLayerReplacesLauncher() {
+ // This test doesn't work in shell transitions because of b/204574221
+ assumeFalse(isShellTransitionsEnabled)
testSpec.assertLayers {
this.isVisible(LAUNCHER_COMPONENT)
.then()
@@ -209,7 +219,11 @@
@Presubmit
@Test
- fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
@Presubmit
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
index c4fec7f..fe434268f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
@@ -25,7 +25,9 @@
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -79,6 +81,15 @@
}
/** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
+
+ /** {@inheritDoc} */
@FlakyTest
@Test
override fun navBarLayerRotatesAndScales() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index c572e8b..53b5354 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -28,7 +28,9 @@
import com.android.server.wm.flicker.helpers.reopenAppFromOverview
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.traces.common.WindowManagerConditionsFactory
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -96,14 +98,54 @@
}
/** {@inheritDoc} */
- @FlakyTest
+ @Presubmit
@Test
- override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
/** {@inheritDoc} */
@Presubmit
@Test
- override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
+ override fun entireScreenCovered() {
+ // This test doesn't work in shell transitions because of b/204570898
+ assumeFalse(isShellTransitionsEnabled)
+ super.entireScreenCovered()
+ }
+
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun appWindowReplacesLauncherAsTopWindow() {
+ // This test doesn't work in shell transitions because of b/206085788
+ assumeFalse(isShellTransitionsEnabled)
+ super.appWindowReplacesLauncherAsTopWindow()
+ }
+
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun appLayerReplacesLauncher() {
+ // This test doesn't work in shell transitions because of b/206085788
+ assumeFalse(isShellTransitionsEnabled)
+ super.appLayerReplacesLauncher()
+ }
+
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
+ // This test doesn't work in shell transitions because of b/206090480
+ assumeFalse(isShellTransitionsEnabled)
+ super.visibleLayersShownMoreThanOneConsecutiveEntry()
+ }
+
+ /** {@inheritDoc} */
+ @FlakyTest
+ @Test
+ override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
/** {@inheritDoc} */
@Presubmit
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
index bd9d7d7..429841b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
@@ -28,9 +28,11 @@
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.traces.common.FlickerComponentName
import com.google.common.truth.Truth
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -188,15 +190,21 @@
/** {@inheritDoc} */
@FlakyTest(bugId = 202936526)
@Test
- override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
/** {@inheritDoc} */
@Presubmit
@Test
fun statusBarLayerPositionAtEnd() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
testSpec.assertLayersEnd {
val display = this.entry.displays.minByOrNull { it.id }
- ?: throw RuntimeException("There is no display!")
+ ?: error("There is no display!")
this.visibleRegion(FlickerComponentName.STATUS_BAR)
.coversExactly(WindowUtils.getStatusBarPosition(display))
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
index dc7df34..4db01bf 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
@@ -25,6 +25,8 @@
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -83,6 +85,33 @@
}
/** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ super.statusBarLayerRotatesScales()
+ }
+
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun appWindowReplacesLauncherAsTopWindow() {
+ // This test doesn't work in shell transitions because of b/206094140
+ assumeFalse(isShellTransitionsEnabled)
+ super.appWindowReplacesLauncherAsTopWindow()
+ }
+
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
+ // This test doesn't work in shell transitions because of b/206094140
+ assumeFalse(isShellTransitionsEnabled)
+ super.visibleLayersShownMoreThanOneConsecutiveEntry()
+ }
+
+ /** {@inheritDoc} */
@FlakyTest
@Test
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index 4a90404..a97a48e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -26,11 +26,13 @@
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.rules.WMFlickerServiceRuleForTestSpec
import com.android.server.wm.flicker.statusBarLayerIsVisible
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsVisible
import com.android.server.wm.traces.common.FlickerComponentName
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Rule
import org.junit.Test
@@ -161,7 +163,11 @@
*/
@Presubmit
@Test
- fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+ fun statusBarLayerRotatesScales() {
+ // This test doesn't work in shell transitions because of b/206753786
+ assumeFalse(isShellTransitionsEnabled)
+ testSpec.statusBarLayerRotatesScales()
+ }
/** {@inheritDoc} */
@FlakyTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index c55d7af..3ca60e3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -26,8 +26,10 @@
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.SeamlessRotationAppHelper
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.traces.common.FlickerComponentName
+import org.junit.Assume.assumeFalse
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -100,6 +102,8 @@
@Presubmit
@Test
fun appWindowFullScreen() {
+ // This test doesn't work in shell transitions because of b/206101151
+ assumeFalse(isShellTransitionsEnabled)
testSpec.assertWm {
this.invoke("isFullScreen") {
val appWindow = it.windowState(testApp.`package`)
@@ -135,17 +139,30 @@
@Presubmit
@Test
fun appLayerAlwaysVisible() {
+ // This test doesn't work in shell transitions because of b/206101151
+ assumeFalse(isShellTransitionsEnabled)
testSpec.assertLayers {
isVisible(testApp.component)
}
}
+ /** {@inheritDoc} */
+ @Presubmit
+ @Test
+ override fun focusDoesNotChange() {
+ // This test doesn't work in shell transitions because of b/206101151
+ assumeFalse(isShellTransitionsEnabled)
+ super.focusDoesNotChange()
+ }
+
/**
* Checks that [testApp] layer covers the entire screen during the whole transition
*/
@Presubmit
@Test
fun appLayerRotates() {
+ // This test doesn't work in shell transitions because of b/206101151
+ assumeFalse(isShellTransitionsEnabled)
testSpec.assertLayers {
this.invoke("entireScreenCovered") { entry ->
entry.entry.displays.map { display ->