diff options
127 files changed, 1981 insertions, 1084 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java index 18f63b7ad902..23056b5670b9 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java @@ -17,6 +17,7 @@ package com.android.server.job; import static com.android.server.job.JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; +import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX; import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock; import android.annotation.IntDef; @@ -32,9 +33,11 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.UserInfo; +import android.os.BatteryStats; import android.os.Handler; import android.os.PowerManager; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.UserHandle; import android.provider.DeviceConfig; import android.util.ArraySet; @@ -51,19 +54,24 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.app.IBatteryStats; import com.android.internal.app.procstats.ProcessStats; import com.android.internal.util.StatLogger; import com.android.server.JobSchedulerBackgroundThread; import com.android.server.LocalServices; import com.android.server.job.controllers.JobStatus; import com.android.server.job.controllers.StateController; +import com.android.server.job.restrictions.JobRestriction; import com.android.server.pm.UserManagerInternal; +import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.function.Consumer; +import java.util.function.Predicate; /** * This class decides, given the various configuration and the system status, which jobs can start @@ -278,6 +286,11 @@ class JobConcurrencyManager { String[] mRecycledShouldStopJobReason = new String[MAX_JOB_CONTEXTS_COUNT]; + /** + * Set of JobServiceContexts that we use to run jobs. + */ + final List<JobServiceContext> mActiveServices = new ArrayList<>(); + private final ArraySet<JobStatus> mRunningJobs = new ArraySet<>(); private final WorkCountTracker mWorkCountTracker = new WorkCountTracker(); @@ -358,6 +371,20 @@ class JobConcurrencyManager { onInteractiveStateChanged(mPowerManager.isInteractive()); } + /** + * Called when the boot phase reaches + * {@link com.android.server.SystemService#PHASE_THIRD_PARTY_APPS_CAN_START}. + */ + void onThirdPartyAppsCanStart() { + final IBatteryStats batteryStats = IBatteryStats.Stub.asInterface( + ServiceManager.getService(BatteryStats.SERVICE_NAME)); + for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) { + mActiveServices.add( + new JobServiceContext(mService, this, batteryStats, + mService.mJobPackageTracker, mContext.getMainLooper())); + } + } + @GuardedBy("mLock") void onAppRemovedLocked(String pkgName, int uid) { final PackageStats packageStats = mActivePkgStats.get(UserHandle.getUserId(uid), pkgName); @@ -390,6 +417,7 @@ class JobConcurrencyManager { case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED: if (mPowerManager != null && mPowerManager.isDeviceIdleMode()) { synchronized (mLock) { + stopUnexemptedJobsForDoze(); stopLongRunningJobsLocked("deep doze"); } } @@ -471,6 +499,11 @@ class JobConcurrencyManager { } @GuardedBy("mLock") + ArraySet<JobStatus> getRunningJobsLocked() { + return mRunningJobs; + } + + @GuardedBy("mLock") boolean isJobRunningLocked(JobStatus job) { return mRunningJobs.contains(job); } @@ -546,7 +579,7 @@ class JobConcurrencyManager { } final List<JobStatus> pendingJobs = mService.mPendingJobs; - final List<JobServiceContext> activeServices = mService.mActiveServices; + final List<JobServiceContext> activeServices = mActiveServices; // To avoid GC churn, we recycle the arrays. JobStatus[] contextIdToJobMap = mRecycledAssignContextIdToJobMap; @@ -719,9 +752,44 @@ class JobConcurrencyManager { } @GuardedBy("mLock") + boolean stopJobOnServiceContextLocked(JobStatus job, + @JobParameters.StopReason int reason, int internalReasonCode, String debugReason) { + if (!mRunningJobs.contains(job)) { + return false; + } + + for (int i = 0; i < mActiveServices.size(); i++) { + JobServiceContext jsc = mActiveServices.get(i); + final JobStatus executing = jsc.getRunningJobLocked(); + if (executing != null && executing.matches(job.getUid(), job.getJobId())) { + jsc.cancelExecutingJobLocked(reason, internalReasonCode, debugReason); + return true; + } + } + Slog.wtf(TAG, "Couldn't find running job on a context"); + mRunningJobs.remove(job); + return false; + } + + @GuardedBy("mLock") + private void stopUnexemptedJobsForDoze() { + // When becoming idle, make sure no jobs are actively running, + // except those using the idle exemption flag. + for (int i = 0; i < mActiveServices.size(); i++) { + JobServiceContext jsc = mActiveServices.get(i); + final JobStatus executing = jsc.getRunningJobLocked(); + if (executing != null && !executing.canRunInDoze()) { + jsc.cancelExecutingJobLocked(JobParameters.STOP_REASON_DEVICE_STATE, + JobParameters.INTERNAL_STOP_REASON_DEVICE_IDLE, + "cancelled due to doze"); + } + } + } + + @GuardedBy("mLock") private void stopLongRunningJobsLocked(@NonNull String debugReason) { for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; ++i) { - final JobServiceContext jsc = mService.mActiveServices.get(i); + final JobServiceContext jsc = mActiveServices.get(i); final JobStatus jobStatus = jsc.getRunningJobLocked(); if (jobStatus != null && !jsc.isWithinExecutionGuaranteeTime()) { @@ -731,6 +799,41 @@ class JobConcurrencyManager { } } + @GuardedBy("mLock") + void stopNonReadyActiveJobsLocked() { + for (int i = 0; i < mActiveServices.size(); i++) { + JobServiceContext serviceContext = mActiveServices.get(i); + final JobStatus running = serviceContext.getRunningJobLocked(); + if (running == null) { + continue; + } + if (!running.isReady()) { + if (running.getEffectiveStandbyBucket() == RESTRICTED_INDEX + && running.getStopReason() == JobParameters.STOP_REASON_APP_STANDBY) { + serviceContext.cancelExecutingJobLocked( + running.getStopReason(), + JobParameters.INTERNAL_STOP_REASON_RESTRICTED_BUCKET, + "cancelled due to restricted bucket"); + } else { + serviceContext.cancelExecutingJobLocked( + running.getStopReason(), + JobParameters.INTERNAL_STOP_REASON_CONSTRAINTS_NOT_SATISFIED, + "cancelled due to unsatisfied constraints"); + } + } else { + final JobRestriction restriction = mService.checkIfRestricted(running); + if (restriction != null) { + final int internalReasonCode = restriction.getInternalReason(); + serviceContext.cancelExecutingJobLocked(restriction.getReason(), + internalReasonCode, + "restricted due to " + + JobParameters.getInternalReasonCodeDescription( + internalReasonCode)); + } + } + } + } + private void noteConcurrency() { mService.mJobPackageTracker.noteConcurrency(mRunningJobs.size(), // TODO: log per type instead of only TOP @@ -1078,6 +1181,24 @@ class JobConcurrencyManager { } @GuardedBy("mLock") + boolean executeTimeoutCommandLocked(PrintWriter pw, String pkgName, int userId, + boolean hasJobId, int jobId) { + boolean foundSome = false; + for (int i = 0; i < mActiveServices.size(); i++) { + final JobServiceContext jc = mActiveServices.get(i); + final JobStatus js = jc.getRunningJobLocked(); + if (jc.timeoutIfExecutingLocked(pkgName, userId, hasJobId, jobId, "shell")) { + foundSome = true; + pw.print("Timing out: "); + js.printUniqueId(pw); + pw.print(" "); + pw.println(js.getServiceComponent().flattenToShortString()); + } + } + return foundSome; + } + + @GuardedBy("mLock") private String printPendingQueueLocked() { StringBuilder s = new StringBuilder("Pending queue: "); Iterator<JobStatus> it = mService.mPendingJobs.iterator(); @@ -1200,6 +1321,43 @@ class JobConcurrencyManager { } } + @GuardedBy("mLock") + void dumpActiveJobsLocked(IndentingPrintWriter pw, Predicate<JobStatus> predicate, + long nowElapsed, long nowUptime) { + pw.println("Active jobs:"); + pw.increaseIndent(); + for (int i = 0; i < mActiveServices.size(); i++) { + JobServiceContext jsc = mActiveServices.get(i); + final JobStatus job = jsc.getRunningJobLocked(); + + if (job != null && !predicate.test(job)) { + continue; + } + + pw.print("Slot #"); pw.print(i); pw.print(": "); + jsc.dumpLocked(pw, nowElapsed); + + if (job != null) { + pw.increaseIndent(); + + pw.increaseIndent(); + job.dump(pw, false, nowElapsed); + pw.decreaseIndent(); + + pw.print("Evaluated bias: "); + pw.println(JobInfo.getBiasString(job.lastEvaluatedBias)); + + pw.print("Active at "); + TimeUtils.formatDuration(job.madeActive - nowUptime, pw); + pw.print(", pending for "); + TimeUtils.formatDuration(job.madeActive - job.madePending, pw); + pw.decreaseIndent(); + pw.println(); + } + } + pw.decreaseIndent(); + } + public void dumpProtoLocked(ProtoOutputStream proto, long tag, long now, long nowRealtime) { final long token = proto.start(tag); 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 b9362789c6c6..3d74bc98ad32 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -57,7 +57,6 @@ import android.content.pm.ServiceInfo; import android.net.Uri; import android.os.BatteryManager; import android.os.BatteryManagerInternal; -import android.os.BatteryStats; import android.os.BatteryStatsInternal; import android.os.Binder; import android.os.Handler; @@ -67,7 +66,6 @@ import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.WorkSource; @@ -90,7 +88,6 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.app.IBatteryStats; import com.android.internal.os.SomeArgs; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; @@ -100,7 +97,6 @@ import com.android.server.AppStateTrackerImpl; import com.android.server.DeviceIdleInternal; import com.android.server.JobSchedulerBackgroundThread; import com.android.server.LocalServices; -import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob; import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob; import com.android.server.job.controllers.BackgroundJobsController; import com.android.server.job.controllers.BatteryController; @@ -243,12 +239,6 @@ public class JobSchedulerService extends com.android.server.SystemService static final int MSG_CHECK_CHANGED_JOB_LIST = 8; static final int MSG_CHECK_MEDIA_EXEMPTION = 9; - /** - * Track Services that have currently active or pending jobs. The index is provided by - * {@link JobStatus#getServiceToken()} - */ - final List<JobServiceContext> mActiveServices = new ArrayList<>(); - /** List of controllers that will notify this service of updates to jobs. */ final List<StateController> mControllers; /** @@ -307,7 +297,6 @@ public class JobSchedulerService extends com.android.server.SystemService PackageManagerInternal mLocalPM; ActivityManagerInternal mActivityManagerInternal; - IBatteryStats mBatteryStats; DeviceIdleInternal mLocalDeviceIdleController; @VisibleForTesting AppStateTrackerImpl mAppStateTracker; @@ -1578,7 +1567,8 @@ public class JobSchedulerService extends com.android.server.SystemService mJobPackageTracker.noteNonpending(cancelled); } // Cancel if running. - stopJobOnServiceContextLocked(cancelled, reason, internalReasonCode, debugReason); + mConcurrencyManager.stopJobOnServiceContextLocked( + cancelled, reason, internalReasonCode, debugReason); // If this is a replacement, bring in the new version of the job if (incomingJob != null) { if (DEBUG) Slog.i(TAG, "Tracking replacement job " + incomingJob.toShortString()); @@ -1627,19 +1617,7 @@ public class JobSchedulerService extends com.android.server.SystemService if (DEBUG) { Slog.d(TAG, "Doze state changed: " + deviceIdle); } - if (deviceIdle) { - // When becoming idle, make sure no jobs are actively running, - // except those using the idle exemption flag. - for (int i=0; i<mActiveServices.size(); i++) { - JobServiceContext jsc = mActiveServices.get(i); - final JobStatus executing = jsc.getRunningJobLocked(); - if (executing != null && !executing.canRunInDoze()) { - jsc.cancelExecutingJobLocked(JobParameters.STOP_REASON_DEVICE_STATE, - JobParameters.INTERNAL_STOP_REASON_DEVICE_IDLE, - "cancelled due to doze"); - } - } - } else { + if (!deviceIdle) { // When coming out of idle, allow thing to start back up. if (mReadyToRock) { if (mLocalDeviceIdleController != null) { @@ -1682,10 +1660,10 @@ public class JobSchedulerService extends com.android.server.SystemService // active is true if pending queue contains jobs OR some job is running. boolean active = mPendingJobs.size() > 0; if (mPendingJobs.size() <= 0) { - for (int i=0; i<mActiveServices.size(); i++) { - final JobServiceContext jsc = mActiveServices.get(i); - final JobStatus job = jsc.getRunningJobLocked(); - if (job != null && !job.canRunInDoze()) { + final ArraySet<JobStatus> runningJobs = mConcurrencyManager.getRunningJobsLocked(); + for (int i = runningJobs.size() - 1; i >= 0; --i) { + final JobStatus job = runningJobs.valueAt(i); + if (!job.canRunInDoze()) { // We will report active if we have a job running and it does not have an // exception that allows it to run in Doze. active = true; @@ -1895,16 +1873,9 @@ public class JobSchedulerService extends com.android.server.SystemService synchronized (mLock) { // Let's go! mReadyToRock = true; - mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( - BatteryStats.SERVICE_NAME)); mLocalDeviceIdleController = LocalServices.getService(DeviceIdleInternal.class); - // Create the "runners". - for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) { - mActiveServices.add( - new JobServiceContext(this, mConcurrencyManager, mBatteryStats, - mJobPackageTracker, getContext().getMainLooper())); - } + mConcurrencyManager.onThirdPartyAppsCanStart(); // Attach jobs to their controllers. mJobs.forEachJob((job) -> { for (int controller = 0; controller < mControllers.size(); controller++) { @@ -1961,19 +1932,6 @@ public class JobSchedulerService extends com.android.server.SystemService return removed; } - private boolean stopJobOnServiceContextLocked(JobStatus job, - @JobParameters.StopReason int reason, int internalReasonCode, String debugReason) { - for (int i = 0; i < mActiveServices.size(); i++) { - JobServiceContext jsc = mActiveServices.get(i); - final JobStatus executing = jsc.getRunningJobLocked(); - if (executing != null && executing.matches(job.getUid(), job.getJobId())) { - jsc.cancelExecutingJobLocked(reason, internalReasonCode, debugReason); - return true; - } - } - return false; - } - /** Return {@code true} if the specified job is currently executing. */ @GuardedBy("mLock") public boolean isCurrentlyRunningLocked(JobStatus job) { @@ -2383,7 +2341,8 @@ public class JobSchedulerService extends com.android.server.SystemService * - if passes all the restrictions or has {@link JobInfo#BIAS_FOREGROUND_SERVICE} bias * or higher. */ - private JobRestriction checkIfRestricted(JobStatus job) { + @GuardedBy("mLock") + JobRestriction checkIfRestricted(JobStatus job) { if (evaluateJobBiasLocked(job) >= JobInfo.BIAS_FOREGROUND_SERVICE) { // Jobs with BIAS_FOREGROUND_SERVICE or higher should not be restricted return null; @@ -2397,38 +2356,9 @@ public class JobSchedulerService extends com.android.server.SystemService return null; } + @GuardedBy("mLock") private void stopNonReadyActiveJobsLocked() { - for (int i=0; i<mActiveServices.size(); i++) { - JobServiceContext serviceContext = mActiveServices.get(i); - final JobStatus running = serviceContext.getRunningJobLocked(); - if (running == null) { - continue; - } - if (!running.isReady()) { - if (running.getEffectiveStandbyBucket() == RESTRICTED_INDEX - && running.getStopReason() == JobParameters.STOP_REASON_APP_STANDBY) { - serviceContext.cancelExecutingJobLocked( - running.getStopReason(), - JobParameters.INTERNAL_STOP_REASON_RESTRICTED_BUCKET, - "cancelled due to restricted bucket"); - } else { - serviceContext.cancelExecutingJobLocked( - running.getStopReason(), - JobParameters.INTERNAL_STOP_REASON_CONSTRAINTS_NOT_SATISFIED, - "cancelled due to unsatisfied constraints"); - } - } else { - final JobRestriction restriction = checkIfRestricted(running); - if (restriction != null) { - final int internalReasonCode = restriction.getInternalReason(); - serviceContext.cancelExecutingJobLocked(restriction.getReason(), - internalReasonCode, - "restricted due to " - + JobParameters.getInternalReasonCodeDescription( - internalReasonCode)); - } - } - } + mConcurrencyManager.stopNonReadyActiveJobsLocked(); } /** @@ -2598,7 +2528,7 @@ public class JobSchedulerService extends com.android.server.SystemService debugReason = "couldn't figure out why the job should stop running"; } } - stopJobOnServiceContextLocked(job, job.getStopReason(), + mConcurrencyManager.stopJobOnServiceContextLocked(job, job.getStopReason(), internalStopReason, debugReason); } else if (mPendingJobs.remove(job)) { noteJobNonPending(job); @@ -3516,9 +3446,11 @@ public class JobSchedulerService extends com.android.server.SystemService final ArrayList<JobInfo> runningJobs; synchronized (mLock) { - runningJobs = new ArrayList<>(mActiveServices.size()); - for (JobServiceContext jsc : mActiveServices) { - final JobStatus job = jsc.getRunningJobLocked(); + final ArraySet<JobStatus> runningJobStatuses = + mConcurrencyManager.getRunningJobsLocked(); + runningJobs = new ArrayList<>(runningJobStatuses.size()); + for (int i = runningJobStatuses.size() - 1; i >= 0; --i) { + final JobStatus job = runningJobStatuses.valueAt(i); if (job != null) { runningJobs.add(job.getJob()); } @@ -3599,18 +3531,8 @@ public class JobSchedulerService extends com.android.server.SystemService } synchronized (mLock) { - boolean foundSome = false; - for (int i = 0; i < mActiveServices.size(); i++) { - final JobServiceContext jc = mActiveServices.get(i); - final JobStatus js = jc.getRunningJobLocked(); - if (jc.timeoutIfExecutingLocked(pkgName, userId, hasJobId, jobId, "shell")) { - foundSome = true; - pw.print("Timing out: "); - js.printUniqueId(pw); - pw.print(" "); - pw.println(js.getServiceComponent().flattenToShortString()); - } - } + final boolean foundSome = mConcurrencyManager.executeTimeoutCommandLocked(pw, + pkgName, userId, hasJobId, jobId); if (!foundSome) { pw.println("No matching executing jobs found."); } @@ -4037,38 +3959,7 @@ public class JobSchedulerService extends com.android.server.SystemService pw.decreaseIndent(); pw.println(); - pw.println("Active jobs:"); - pw.increaseIndent(); - for (int i=0; i<mActiveServices.size(); i++) { - JobServiceContext jsc = mActiveServices.get(i); - final JobStatus job = jsc.getRunningJobLocked(); - - if (job != null && !predicate.test(job)) { - continue; - } - - pw.print("Slot #"); pw.print(i); pw.print(": "); - jsc.dumpLocked(pw, nowElapsed); - - if (job != null) { - pw.increaseIndent(); - - pw.increaseIndent(); - job.dump(pw, false, nowElapsed); - pw.decreaseIndent(); - - pw.print("Evaluated bias: "); - pw.println(JobInfo.getBiasString(job.lastEvaluatedBias)); - - pw.print("Active at "); - TimeUtils.formatDuration(job.madeActive - nowUptime, pw); - pw.print(", pending for "); - TimeUtils.formatDuration(job.madeActive - job.madePending, pw); - pw.decreaseIndent(); - pw.println(); - } - } - pw.decreaseIndent(); + mConcurrencyManager.dumpActiveJobsLocked(pw, predicate, nowElapsed, nowUptime); pw.println(); boolean recentPrinted = false; @@ -4228,45 +4119,6 @@ public class JobSchedulerService extends com.android.server.SystemService proto.end(pjToken); } - for (JobServiceContext jsc : mActiveServices) { - final long ajToken = proto.start(JobSchedulerServiceDumpProto.ACTIVE_JOBS); - final JobStatus job = jsc.getRunningJobLocked(); - - if (job == null) { - final long ijToken = proto.start(ActiveJob.INACTIVE); - - proto.write(ActiveJob.InactiveJob.TIME_SINCE_STOPPED_MS, - nowElapsed - jsc.mStoppedTime); - if (jsc.mStoppedReason != null) { - proto.write(ActiveJob.InactiveJob.STOPPED_REASON, - jsc.mStoppedReason); - } - - proto.end(ijToken); - } else { - final long rjToken = proto.start(ActiveJob.RUNNING); - - job.writeToShortProto(proto, ActiveJob.RunningJob.INFO); - - proto.write(ActiveJob.RunningJob.RUNNING_DURATION_MS, - nowElapsed - jsc.getExecutionStartTimeElapsed()); - proto.write(ActiveJob.RunningJob.TIME_UNTIL_TIMEOUT_MS, - jsc.getTimeoutElapsed() - nowElapsed); - - job.dump(proto, ActiveJob.RunningJob.DUMP, false, nowElapsed); - - proto.write(ActiveJob.RunningJob.EVALUATED_PRIORITY, - evaluateJobBiasLocked(job)); - - proto.write(ActiveJob.RunningJob.TIME_SINCE_MADE_ACTIVE_MS, - nowUptime - job.madeActive); - proto.write(ActiveJob.RunningJob.PENDING_DURATION_MS, - job.madeActive - job.madePending); - - proto.end(rjToken); - } - proto.end(ajToken); - } if (filterUid == -1) { proto.write(JobSchedulerServiceDumpProto.IS_READY_TO_ROCK, mReadyToRock); proto.write(JobSchedulerServiceDumpProto.REPORTED_ACTIVE, mReportedActive); diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java index efcf14f07ee9..30fdb1e9ad4e 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java @@ -441,11 +441,6 @@ public final class JobStatus { /** The reason a job most recently went from ready to not ready. */ private int mReasonReadyToUnready = JobParameters.STOP_REASON_UNDEFINED; - /** Provide a handle to the service that this job will be run on. */ - public int getServiceToken() { - return callingUid; - } - /** * Core constructor for JobStatus instances. All other ctors funnel down to this one. * diff --git a/core/api/current.txt b/core/api/current.txt index b5493a3fa8c7..02c30e3b1722 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -5630,6 +5630,7 @@ package android.app { method public boolean onException(Object, Throwable); method public void onStart(); method public void removeMonitor(android.app.Instrumentation.ActivityMonitor); + method public void resetInTouchMode(); method public void runOnMainSync(Runnable); method public void sendCharacterSync(int); method public void sendKeyDownUpSync(int); @@ -6644,6 +6645,15 @@ package android.app { public final class PictureInPictureParams implements android.os.Parcelable { method public int describeContents(); + method @NonNull public java.util.List<android.app.RemoteAction> getActions(); + method @Nullable public android.util.Rational getAspectRatio(); + method @Nullable public android.app.RemoteAction getCloseAction(); + method @Nullable public android.util.Rational getExpandedAspectRatio(); + method @Nullable public android.graphics.Rect getSourceRectHint(); + method @Nullable public CharSequence getSubtitle(); + method @Nullable public CharSequence getTitle(); + method public boolean isAutoEnterEnabled(); + method public boolean isSeamlessResizeEnabled(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.PictureInPictureParams> CREATOR; } @@ -10115,12 +10125,16 @@ package android.content { method @Nullable public long[] getLongArrayExtra(String); method public long getLongExtra(String, long); method @Nullable public String getPackage(); - method @Nullable public android.os.Parcelable[] getParcelableArrayExtra(String); - method @Nullable public <T extends android.os.Parcelable> java.util.ArrayList<T> getParcelableArrayListExtra(String); - method @Nullable public <T extends android.os.Parcelable> T getParcelableExtra(String); + method @Deprecated @Nullable public android.os.Parcelable[] getParcelableArrayExtra(String); + method @Nullable public <T> T[] getParcelableArrayExtra(@Nullable String, @NonNull Class<T>); + method @Deprecated @Nullable public <T extends android.os.Parcelable> java.util.ArrayList<T> getParcelableArrayListExtra(String); + method @Nullable public <T> java.util.ArrayList<T> getParcelableArrayListExtra(@Nullable String, @NonNull Class<? extends T>); + method @Deprecated @Nullable public <T extends android.os.Parcelable> T getParcelableExtra(String); + method @Nullable public <T> T getParcelableExtra(@Nullable String, @NonNull Class<T>); method @Nullable public String getScheme(); method @Nullable public android.content.Intent getSelector(); - method @Nullable public java.io.Serializable getSerializableExtra(String); + method @Deprecated @Nullable public java.io.Serializable getSerializableExtra(String); + method @Nullable public <T extends java.io.Serializable> T getSerializableExtra(@Nullable String, @NonNull Class<T>); method @Nullable public short[] getShortArrayExtra(String); method public short getShortExtra(String, short); method @Nullable public android.graphics.Rect getSourceBounds(); @@ -19477,26 +19491,26 @@ package android.location { method @NonNull public static String convert(@FloatRange double, int); method @FloatRange public static double convert(@NonNull String); method public int describeContents(); - method public static void distanceBetween(@FloatRange double, @FloatRange double, @FloatRange double, @FloatRange double, float[]); - method @FloatRange public float distanceTo(@NonNull android.location.Location); - method public void dump(@NonNull android.util.Printer, @Nullable String); - method @FloatRange public float getAccuracy(); + method public static void distanceBetween(@FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, @FloatRange(from=-90.0, to=90.0) double, @FloatRange(from=-180.0, to=180.0) double, float[]); + method @FloatRange(from=0.0) public float distanceTo(@NonNull android.location.Location); + method @Deprecated public void dump(@NonNull android.util.Printer, @Nullable String); + method @FloatRange(from=0.0) public float getAccuracy(); method @FloatRange public double getAltitude(); - method @FloatRange(from=0.0f, to=360.0f, toInclusive=false) public float getBearing(); - method @FloatRange public float getBearingAccuracyDegrees(); - method @IntRange public long getElapsedRealtimeAgeMillis(); - method @IntRange public long getElapsedRealtimeAgeMillis(@IntRange long); - method @IntRange public long getElapsedRealtimeMillis(); - method @IntRange public long getElapsedRealtimeNanos(); - method @FloatRange public double getElapsedRealtimeUncertaintyNanos(); + method @FloatRange(from=0.0, to=360.0, toInclusive=false) public float getBearing(); + method @FloatRange(from=0.0) public float getBearingAccuracyDegrees(); + method @IntRange(from=0) public long getElapsedRealtimeAgeMillis(); + method public long getElapsedRealtimeAgeMillis(@IntRange(from=0) long); + method @IntRange(from=0) public long getElapsedRealtimeMillis(); + method @IntRange(from=0) public long getElapsedRealtimeNanos(); + method @FloatRange(from=0.0) public double getElapsedRealtimeUncertaintyNanos(); method @Nullable public android.os.Bundle getExtras(); - method @FloatRange public double getLatitude(); - method @FloatRange public double getLongitude(); + method @FloatRange(from=-90.0, to=90.0) public double getLatitude(); + method @FloatRange(from=-180.0, to=180.0) public double getLongitude(); method @Nullable public String getProvider(); - method @FloatRange public float getSpeed(); - method @FloatRange public float getSpeedAccuracyMetersPerSecond(); - method @IntRange public long getTime(); - method @FloatRange public float getVerticalAccuracyMeters(); + method @FloatRange(from=0.0) public float getSpeed(); + method @FloatRange(from=0.0) public float getSpeedAccuracyMetersPerSecond(); + method @IntRange(from=0) public long getTime(); + method @FloatRange(from=0.0) public float getVerticalAccuracyMeters(); method public boolean hasAccuracy(); method public boolean hasAltitude(); method public boolean hasBearing(); @@ -19518,21 +19532,21 @@ package android.location { method public void removeVerticalAccuracy(); method public void reset(); method public void set(@NonNull android.location.Location); - method public void setAccuracy(@FloatRange float); + method public void setAccuracy(@FloatRange(from=0.0) float); method public void setAltitude(@FloatRange double); method public void setBearing(@FloatRange(fromInclusive=false, toInclusive=false) float); - method public void setBearingAccuracyDegrees(@FloatRange float); - method public void setElapsedRealtimeNanos(@IntRange long); - method public void setElapsedRealtimeUncertaintyNanos(@FloatRange double); + method public void setBearingAccuracyDegrees(@FloatRange(from=0.0) float); + method public void setElapsedRealtimeNanos(@IntRange(from=0) long); + method public void setElapsedRealtimeUncertaintyNanos(@FloatRange(from=0.0) double); method public void setExtras(@Nullable android.os.Bundle); - method public void setLatitude(@FloatRange double); - method public void setLongitude(@FloatRange double); + method public void setLatitude(@FloatRange(from=-90.0, to=90.0) double); + method public void setLongitude(@FloatRange(from=-180.0, to=180.0) double); method public void setMock(boolean); method public void setProvider(@Nullable String); - method public void setSpeed(@FloatRange float); - method public void setSpeedAccuracyMetersPerSecond(@FloatRange float); - method public void setTime(@IntRange long); - method public void setVerticalAccuracyMeters(@FloatRange float); + method public void setSpeed(@FloatRange(from=0.0) float); + method public void setSpeedAccuracyMetersPerSecond(@FloatRange(from=0.0) float); + method public void setTime(@IntRange(from=0) long); + method public void setVerticalAccuracyMeters(@FloatRange(from=0.0) float); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.location.Location> CREATOR; field public static final int FORMAT_DEGREES = 0; // 0x0 @@ -23538,17 +23552,24 @@ package android.media { } public class Spatializer { + method public void addOnHeadTrackerAvailableListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.Spatializer.OnHeadTrackerAvailableListener); method public void addOnSpatializerStateChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.Spatializer.OnSpatializerStateChangedListener); method public boolean canBeSpatialized(@NonNull android.media.AudioAttributes, @NonNull android.media.AudioFormat); method public int getImmersiveAudioLevel(); method public boolean isAvailable(); method public boolean isEnabled(); + method public boolean isHeadTrackerAvailable(); + method public void removeOnHeadTrackerAvailableListener(@NonNull android.media.Spatializer.OnHeadTrackerAvailableListener); method public void removeOnSpatializerStateChangedListener(@NonNull android.media.Spatializer.OnSpatializerStateChangedListener); field public static final int SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL = 1; // 0x1 field public static final int SPATIALIZER_IMMERSIVE_LEVEL_NONE = 0; // 0x0 field public static final int SPATIALIZER_IMMERSIVE_LEVEL_OTHER = -1; // 0xffffffff } + public static interface Spatializer.OnHeadTrackerAvailableListener { + method public void onHeadTrackerAvailableChanged(@NonNull android.media.Spatializer, boolean); + } + public static interface Spatializer.OnSpatializerStateChangedListener { method public void onSpatializerAvailableChanged(@NonNull android.media.Spatializer, boolean); method public void onSpatializerEnabledChanged(@NonNull android.media.Spatializer, boolean); @@ -25181,17 +25202,23 @@ package android.media.tv { } public final class CommandRequest extends android.media.tv.BroadcastInfoRequest implements android.os.Parcelable { - ctor public CommandRequest(int, int, @NonNull String, @NonNull String, @NonNull String); + ctor public CommandRequest(int, int, @NonNull String, @NonNull String, @NonNull String, @NonNull String); + method @NonNull public String getArgumentType(); method @NonNull public String getArguments(); method @NonNull public String getName(); - method @NonNull public String getNameSpace(); + method @NonNull public String getNamespace(); + field public static final String ARGUMENT_TYPE_JSON = "json"; + field public static final String ARGUMENT_TYPE_XML = "xml"; field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.CommandRequest> CREATOR; } public final class CommandResponse extends android.media.tv.BroadcastInfoResponse implements android.os.Parcelable { - ctor public CommandResponse(int, int, int, @Nullable String); + ctor public CommandResponse(int, int, int, @Nullable String, @NonNull String); method @Nullable public String getResponse(); + method @NonNull public String getResponseType(); field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.CommandResponse> CREATOR; + field public static final String RESPONSE_TYPE_JSON = "json"; + field public static final String RESPONSE_TYPE_XML = "xml"; } public final class DsmccRequest extends android.media.tv.BroadcastInfoRequest implements android.os.Parcelable { @@ -25256,7 +25283,7 @@ package android.media.tv { ctor public StreamEventResponse(int, int, int, int, long, @Nullable byte[]); method @Nullable public byte[] getData(); method public int getEventId(); - method public long getNpt(); + method public long getNptMillis(); field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.StreamEventResponse> CREATOR; } @@ -25286,7 +25313,7 @@ package android.media.tv { public final class TimelineResponse extends android.media.tv.BroadcastInfoResponse implements android.os.Parcelable { ctor public TimelineResponse(int, int, int, @Nullable String, int, int, long, long); - method @Nullable public String getSelector(); + method @Nullable public android.net.Uri getSelector(); method public long getTicks(); method public int getUnitsPerSecond(); method public int getUnitsPerTick(); @@ -26082,21 +26109,8 @@ package android.media.tv.interactive { method @NonNull public android.media.tv.interactive.AppLinkInfo.Builder setUriScheme(@NonNull String); } - public final class TvInteractiveAppInfo implements android.os.Parcelable { - ctor public TvInteractiveAppInfo(@NonNull android.content.Context, @NonNull android.content.ComponentName); - method public int describeContents(); - method @NonNull public String getId(); - method @Nullable public android.content.pm.ServiceInfo getServiceInfo(); - method @NonNull public int getSupportedTypes(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.interactive.TvInteractiveAppInfo> CREATOR; - field public static final int INTERACTIVE_APP_TYPE_ATSC = 2; // 0x2 - field public static final int INTERACTIVE_APP_TYPE_GINGA = 4; // 0x4 - field public static final int INTERACTIVE_APP_TYPE_HBBTV = 1; // 0x1 - } - public final class TvInteractiveAppManager { - method @NonNull public java.util.List<android.media.tv.interactive.TvInteractiveAppInfo> getTvInteractiveAppServiceList(); + method @NonNull public java.util.List<android.media.tv.interactive.TvInteractiveAppServiceInfo> getTvInteractiveAppServiceList(); method public void prepare(@NonNull String, int); method public void registerAppLinkInfo(@NonNull String, @NonNull android.media.tv.interactive.AppLinkInfo); method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.interactive.TvInteractiveAppManager.TvInteractiveAppCallback); @@ -26219,6 +26233,19 @@ package android.media.tv.interactive { method @CallSuper public void setVideoBounds(@NonNull android.graphics.Rect); } + public final class TvInteractiveAppServiceInfo implements android.os.Parcelable { + ctor public TvInteractiveAppServiceInfo(@NonNull android.content.Context, @NonNull android.content.ComponentName); + method public int describeContents(); + method @NonNull public String getId(); + method @Nullable public android.content.pm.ServiceInfo getServiceInfo(); + method @NonNull public int getSupportedTypes(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.interactive.TvInteractiveAppServiceInfo> CREATOR; + field public static final int INTERACTIVE_APP_TYPE_ATSC = 2; // 0x2 + field public static final int INTERACTIVE_APP_TYPE_GINGA = 4; // 0x4 + field public static final int INTERACTIVE_APP_TYPE_HBBTV = 1; // 0x1 + } + public class TvInteractiveAppView extends android.view.ViewGroup { ctor public TvInteractiveAppView(@NonNull android.content.Context); ctor public TvInteractiveAppView(@NonNull android.content.Context, @Nullable android.util.AttributeSet); @@ -43786,6 +43813,7 @@ package android.telephony.data { method public int getNetworkTypeBitmask(); method public String getOperatorNumeric(); method public String getPassword(); + method public int getProfileId(); method public int getProtocol(); method @Deprecated public java.net.InetAddress getProxyAddress(); method public String getProxyAddressAsString(); @@ -43793,6 +43821,7 @@ package android.telephony.data { method public int getRoamingProtocol(); method public String getUser(); method public boolean isEnabled(); + method public boolean isPersistent(); method public void writeToParcel(@NonNull android.os.Parcel, int); field public static final int AUTH_TYPE_CHAP = 2; // 0x2 field public static final int AUTH_TYPE_NONE = 0; // 0x0 diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 3d5232ba4f35..d2cc0f54d4b7 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -243,7 +243,8 @@ package android.net { method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public android.telephony.SubscriptionPlan getSubscriptionPlan(@NonNull android.net.NetworkTemplate); method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidNetworkingBlocked(int, boolean); method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidRestrictedOnMeteredNetworks(int); - method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyStatsProviderWarningOrLimitReached(); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyStatsProviderLimitReached(); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyStatsProviderWarningReached(); method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void registerNetworkPolicyCallback(@Nullable java.util.concurrent.Executor, @NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback); method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void unregisterNetworkPolicyCallback(@NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback); } diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 9f41f05534e5..5df988153752 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -1114,6 +1114,7 @@ package android.app.admin { method public void setSecondaryLockscreenEnabled(@NonNull android.content.ComponentName, boolean); method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES) public void setStrings(@NonNull java.util.Set<android.app.admin.DevicePolicyStringResource>); method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void setUserProvisioningState(int, @NonNull android.os.UserHandle); + method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public boolean shouldAllowBypassingDevicePolicyManagementRoleQualification(); field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_ALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_ALLOWED"; field public static final String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED"; field public static final String ACTION_BIND_SECONDARY_LOCKSCREEN_SERVICE = "android.app.action.BIND_SECONDARY_LOCKSCREEN_SERVICE"; diff --git a/core/api/test-current.txt b/core/api/test-current.txt index db95a1feec91..2e8bed32665c 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -356,14 +356,8 @@ package android.app { } public final class PictureInPictureParams implements android.os.Parcelable { - method public java.util.List<android.app.RemoteAction> getActions(); - method public float getAspectRatio(); - method @Nullable public android.app.RemoteAction getCloseAction(); - method public float getExpandedAspectRatio(); - method public android.graphics.Rect getSourceRectHint(); - method @Nullable public CharSequence getSubtitle(); - method @Nullable public CharSequence getTitle(); - method public boolean isSeamlessResizeEnabled(); + method public float getAspectRatioFloat(); + method public float getExpandedAspectRatioFloat(); } public final class PictureInPictureUiState implements android.os.Parcelable { diff --git a/core/java/android/app/GameManager.java b/core/java/android/app/GameManager.java index 6f49c9e647a4..a138fa1f6fd5 100644 --- a/core/java/android/app/GameManager.java +++ b/core/java/android/app/GameManager.java @@ -191,7 +191,7 @@ public final class GameManager { */ @TestApi @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE) - public @GameMode boolean isAngleEnabled(@NonNull String packageName) { + public boolean isAngleEnabled(@NonNull String packageName) { try { return mService.isAngleEnabled(packageName, mContext.getUserId()); } catch (RemoteException e) { diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index e0c69df0aa18..ac979c495cf3 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -393,6 +393,15 @@ public class Instrumentation { } /** + * Resets the {@link #setInTouchMode touch mode} to the device default. + */ + public void resetInTouchMode() { + final boolean defaultInTouchMode = getContext().getResources().getBoolean( + com.android.internal.R.bool.config_defaultInTouchMode); + setInTouchMode(defaultInTouchMode); + } + + /** * Schedule a callback for when the application's main thread goes idle * (has no more events to process). * diff --git a/core/java/android/app/PictureInPictureParams.java b/core/java/android/app/PictureInPictureParams.java index 2d2788ca91a3..3f1844e2ba8a 100644 --- a/core/java/android/app/PictureInPictureParams.java +++ b/core/java/android/app/PictureInPictureParams.java @@ -280,7 +280,7 @@ public final class PictureInPictureParams implements Parcelable { private Rational mAspectRatio; /** - * The expected aspect ratio of the vertically expanded picture-in-picture window. + * The expected aspect ratio of the expanded picture-in-picture window. */ @Nullable private Rational mExpandedAspectRatio; @@ -441,15 +441,21 @@ public final class PictureInPictureParams implements Parcelable { * @hide */ @TestApi - public float getAspectRatio() { + public float getAspectRatioFloat() { if (mAspectRatio != null) { return mAspectRatio.floatValue(); } return 0f; } - /** @hide */ - public Rational getAspectRatioRational() { + /** + * Returns the expected aspect ratio of the picture-in-picture window. + * + * @return aspect ratio as the desired width / height or {@code null} if not set. + * @see PictureInPictureParams.Builder#setAspectRatio(Rational) + */ + @Nullable + public Rational getAspectRatio() { return mAspectRatio; } @@ -466,7 +472,7 @@ public final class PictureInPictureParams implements Parcelable { * @hide */ @TestApi - public float getExpandedAspectRatio() { + public float getExpandedAspectRatioFloat() { if (mExpandedAspectRatio != null) { return mExpandedAspectRatio.floatValue(); } @@ -474,6 +480,17 @@ public final class PictureInPictureParams implements Parcelable { } /** + * Returns the desired aspect ratio of the expanded picture-in-picture window. + * + * @return aspect ratio as the desired width / height or {@code null} if not set. + * @see PictureInPictureParams.Builder#setExpandedAspectRatio(Rational) + */ + @Nullable + public Rational getExpandedAspectRatio() { + return mExpandedAspectRatio; + } + + /** * @return whether the expanded aspect ratio is set * @hide */ @@ -482,11 +499,17 @@ public final class PictureInPictureParams implements Parcelable { } /** - * @return the set of user actions. - * @hide + * Returns the list of user actions that are associated with the activity when in + * picture-in-picture mode. + * + * @return the user actions in a new list. + * @see PictureInPictureParams.Builder#setActions(List) */ - @TestApi + @NonNull public List<RemoteAction> getActions() { + if (mUserActions == null) { + return new ArrayList<>(); + } return mUserActions; } @@ -499,10 +522,11 @@ public final class PictureInPictureParams implements Parcelable { } /** - * @return the close action. - * @hide + * Returns the action that is to replace the system close action. + * + * @return the close action or {@code null} if not set. + * @see PictureInPictureParams.Builder#setCloseAction(RemoteAction) */ - @TestApi @Nullable public RemoteAction getCloseAction() { return mCloseAction; @@ -528,10 +552,12 @@ public final class PictureInPictureParams implements Parcelable { } /** - * @return the source rect hint - * @hide + * Returns the source rect hint. + * + * @return the source rect hint also known as launch bounds or {@code null} if not set. + * @see PictureInPictureParams.Builder#setSourceRectHint(Rect) */ - @TestApi + @Nullable public Rect getSourceRectHint() { return mSourceRectHint; } @@ -545,18 +571,23 @@ public final class PictureInPictureParams implements Parcelable { } /** - * @return whether auto pip is enabled. - * @hide + * Returns whether auto enter picture-in-picture is enabled. + * + * @return {@code true} if the system will automatically put the activity in + * picture-in-picture mode. + * @see PictureInPictureParams.Builder#setAutoEnterEnabled(boolean) */ public boolean isAutoEnterEnabled() { return mAutoEnterEnabled == null ? false : mAutoEnterEnabled; } /** - * @return whether seamless resize is enabled. - * @hide + * Returns whether seamless resize is enabled. + * + * @return true if the system can seamlessly resize the window while activity is in + * picture-in-picture mode. + * @see PictureInPictureParams.Builder#setSeamlessResizeEnabled(boolean) */ - @TestApi public boolean isSeamlessResizeEnabled() { return mSeamlessResizeEnabled == null ? true : mSeamlessResizeEnabled; } @@ -570,10 +601,11 @@ public final class PictureInPictureParams implements Parcelable { } /** - * @return title of the pip. - * @hide + * Returns the title of the picture-in-picture window that may be displayed to the user. + * + * @return title of the picture-in-picture window. + * @see PictureInPictureParams.Builder#setTitle(CharSequence) */ - @TestApi @Nullable public CharSequence getTitle() { return mTitle; @@ -588,10 +620,11 @@ public final class PictureInPictureParams implements Parcelable { } /** - * @return subtitle of the pip. - * @hide + * Returns the subtitle of the picture-in-picture window that may be displayed to the user. + * + * @return subtitle of the picture-in-picture window. + * @see PictureInPictureParams.Builder#setSubtitle(CharSequence) */ - @TestApi @Nullable public CharSequence getSubtitle() { return mSubtitle; @@ -716,7 +749,7 @@ public final class PictureInPictureParams implements Parcelable { @Override public String toString() { return "PictureInPictureParams(" - + " aspectRatio=" + getAspectRatioRational() + + " aspectRatio=" + getAspectRatio() + " expandedAspectRatio=" + mExpandedAspectRatio + " sourceRectHint=" + getSourceRectHint() + " hasSetActions=" + hasSetActions() diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index 150888ccb2d8..89854bbab3e8 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -24,9 +24,6 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; -import android.app.compat.CompatChanges; -import android.compat.annotation.ChangeId; -import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; @@ -42,7 +39,6 @@ import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.UserHandle; import android.util.Pair; import android.util.Slog; import android.view.View; @@ -524,27 +520,6 @@ public class StatusBarManager { private final Map<NearbyMediaDevicesProvider, NearbyMediaDevicesProviderWrapper> nearbyMediaDevicesProviderMap = new HashMap<>(); - /** - * Media controls based on {@link android.app.Notification.MediaStyle} notifications will have - * actions based on the media session's {@link android.media.session.PlaybackState}, rather than - * the notification's actions. - * - * These actions will be: - * - Play/Pause (depending on whether the current state is a playing state) - * - Previous (if declared), or a custom action if the slot is not reserved with - * {@code SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV} - * - Next (if declared), or a custom action if the slot is not reserved with - * {@code SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT} - * - Custom action - * - Custom action - * - * @see androidx.media.utils.MediaConstants#SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV - * @see androidx.media.utils.MediaConstants#SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT - */ - @ChangeId - @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) - private static final long MEDIA_CONTROL_SESSION_ACTIONS = 203800354L; - @UnsupportedAppUsage private Context mContext; private IStatusBarService mService; @@ -1152,20 +1127,6 @@ public class StatusBarManager { } } - /** - * Checks whether the given package should use session-based actions for its media controls. - * - * @param packageName App posting media controls - * @param userId Current user ID - * @return true if the app supports session actions - * - * @hide - */ - public static boolean useMediaSessionActionsForApp(String packageName, int userId) { - UserHandle handle = UserHandle.getUserHandleForUid(userId); - return CompatChanges.isChangeEnabled(MEDIA_CONTROL_SESSION_ACTIONS, packageName, handle); - } - /** @hide */ public static String windowStateToString(int state) { if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING"; diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 27fe312706ff..7269b0d91d02 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -15765,4 +15765,23 @@ public class DevicePolicyManager { } return deviceManagerConfig; } + + /** + * @return {@code true} if bypassing the device policy management role qualification is allowed + * with the current state of the device. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) + public boolean shouldAllowBypassingDevicePolicyManagementRoleQualification() { + if (mService != null) { + try { + return mService.shouldAllowBypassingDevicePolicyManagementRoleQualification(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return false; + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 77db14654592..fb1ca41ccc56 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -558,4 +558,6 @@ interface IDevicePolicyManager { void setStrings(in List<DevicePolicyStringResource> strings); void resetStrings(in String[] stringIds); ParcelableResource getString(String stringId); + + boolean shouldAllowBypassingDevicePolicyManagementRoleQualification(); } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 478befd9c26d..2c207bc90444 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -8903,8 +8903,12 @@ public class Intent implements Parcelable, Cloneable { * @return the value of an item previously added with putExtra(), * or null if no Parcelable value was found. * + * @deprecated Use the type-safer {@link #getParcelableExtra(String, Class)} starting from + * Android {@link Build.VERSION_CODES#TIRAMISU}. + * * @see #putExtra(String, Parcelable) */ + @Deprecated public @Nullable <T extends Parcelable> T getParcelableExtra(String name) { return mExtras == null ? null : mExtras.<T>getParcelable(name); } @@ -8913,12 +8917,31 @@ public class Intent implements Parcelable, Cloneable { * Retrieve extended data from the intent. * * @param name The name of the desired item. + * @param clazz The type of the object expected. + * + * @return the value of an item previously added with putExtra(), + * or null if no Parcelable value was found. + * + * @see #putExtra(String, Parcelable) + */ + public @Nullable <T> T getParcelableExtra(@Nullable String name, @NonNull Class<T> clazz) { + return mExtras == null ? null : mExtras.getParcelable(name, clazz); + } + + /** + * Retrieve extended data from the intent. + * + * @param name The name of the desired item. * * @return the value of an item previously added with putExtra(), * or null if no Parcelable[] value was found. * + * @deprecated Use the type-safer {@link #getParcelableArrayExtra(String, Class)} starting from + * Android {@link Build.VERSION_CODES#TIRAMISU}. + * * @see #putExtra(String, Parcelable[]) */ + @Deprecated public @Nullable Parcelable[] getParcelableArrayExtra(String name) { return mExtras == null ? null : mExtras.getParcelableArray(name); } @@ -8927,13 +8950,34 @@ public class Intent implements Parcelable, Cloneable { * Retrieve extended data from the intent. * * @param name The name of the desired item. + * @param clazz The type of the items inside the array. This is only verified when unparceling. + * + * @return the value of an item previously added with putExtra(), + * or null if no Parcelable[] value was found. + * + * @see #putExtra(String, Parcelable[]) + */ + @SuppressLint({"ArrayReturn", "NullableCollection"}) + public @Nullable <T> T[] getParcelableArrayExtra(@Nullable String name, + @NonNull Class<T> clazz) { + return mExtras == null ? null : mExtras.getParcelableArray(name, clazz); + } + + /** + * Retrieve extended data from the intent. + * + * @param name The name of the desired item. * * @return the value of an item previously added with * putParcelableArrayListExtra(), or null if no * ArrayList<Parcelable> value was found. * + * @deprecated Use the type-safer {@link #getParcelableArrayListExtra(String, Class)} starting + * from Android {@link Build.VERSION_CODES#TIRAMISU}. + * * @see #putParcelableArrayListExtra(String, ArrayList) */ + @Deprecated public @Nullable <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String name) { return mExtras == null ? null : mExtras.<T>getParcelableArrayList(name); } @@ -8942,10 +8986,32 @@ public class Intent implements Parcelable, Cloneable { * Retrieve extended data from the intent. * * @param name The name of the desired item. + * @param clazz The type of the items inside the array list. This is only verified when + * unparceling. + * + * @return the value of an item previously added with + * putParcelableArrayListExtra(), or null if no + * ArrayList<Parcelable> value was found. + * + * @see #putParcelableArrayListExtra(String, ArrayList) + */ + @SuppressLint({"ConcreteCollection", "NullableCollection"}) + public @Nullable <T> ArrayList<T> getParcelableArrayListExtra(@Nullable String name, + @NonNull Class<? extends T> clazz) { + return mExtras == null ? null : mExtras.<T>getParcelableArrayList(name, clazz); + } + + /** + * Retrieve extended data from the intent. + * + * @param name The name of the desired item. * * @return the value of an item previously added with putExtra(), * or null if no Serializable value was found. * + * @deprecated Use the type-safer {@link #getSerializableExtra(String, Class)} starting from + * Android {@link Build.VERSION_CODES#TIRAMISU}. + * * @see #putExtra(String, Serializable) */ public @Nullable Serializable getSerializableExtra(String name) { @@ -8956,6 +9022,22 @@ public class Intent implements Parcelable, Cloneable { * Retrieve extended data from the intent. * * @param name The name of the desired item. + * @param clazz The type of the object expected. + * + * @return the value of an item previously added with putExtra(), + * or null if no Serializable value was found. + * + * @see #putExtra(String, Serializable) + */ + public @Nullable <T extends Serializable> T getSerializableExtra(@Nullable String name, + @NonNull Class<T> clazz) { + return mExtras == null ? null : mExtras.getSerializable(name, clazz); + } + + /** + * Retrieve extended data from the intent. + * + * @param name The name of the desired item. * * @return the value of an item previously added with * putIntegerArrayListExtra(), or null if no diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index a05f5c927b29..c8bbb0c1994d 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -79,6 +79,13 @@ public final class AssetManager implements AutoCloseable { @GuardedBy("sSync") private static ArraySet<ApkAssets> sSystemApkAssetsSet; /** + * Cookie value to use when the actual cookie is unknown. This value tells the system to search + * all the ApkAssets for the asset. + * @hide + */ + public static final int COOKIE_UNKNOWN = -1; + + /** * Mode for {@link #open(String, int)}: no specific information about how * data will be accessed. */ diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index 18ec8f57ad3a..2c2a703b16e2 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -580,6 +580,24 @@ public class NetworkPolicyManager { } /** + * Notifies that the specified {@link NetworkStatsProvider} has reached its warning threshold + * which was set through {@link NetworkStatsProvider#onSetWarningAndLimit(String, long, long)}. + * + * @hide + */ + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public void notifyStatsProviderWarningReached() { + try { + mService.notifyStatsProviderWarningOrLimitReached(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Notifies that the specified {@link NetworkStatsProvider} has reached its quota * which was set through {@link NetworkStatsProvider#onSetLimit(String, long)} or * {@link NetworkStatsProvider#onSetWarningAndLimit(String, long, long)}. @@ -590,7 +608,7 @@ public class NetworkPolicyManager { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public void notifyStatsProviderWarningOrLimitReached() { + public void notifyStatsProviderLimitReached() { try { mService.notifyStatsProviderWarningOrLimitReached(); } catch (RemoteException e) { diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java index 190adbdfd5db..61098d60566f 100644 --- a/core/java/android/view/HandwritingInitiator.java +++ b/core/java/android/view/HandwritingInitiator.java @@ -55,10 +55,10 @@ public class HandwritingInitiator { */ private final int mTouchSlop; /** - * The timeout used to distinguish tap from handwriting. If the stylus doesn't move before this - * timeout, it's not considered as handwriting. + * The timeout used to distinguish tap or long click from handwriting. If the stylus doesn't + * move before this timeout, it's not considered as handwriting. */ - private final long mTapTimeoutInMillis; + private final long mHandwritingTimeoutInMillis; private State mState = new State(); private final HandwritingAreaTracker mHandwritingAreasTracker = new HandwritingAreaTracker(); @@ -90,7 +90,7 @@ public class HandwritingInitiator { public HandwritingInitiator(@NonNull ViewConfiguration viewConfiguration, @NonNull InputMethodManager inputMethodManager) { mTouchSlop = viewConfiguration.getScaledTouchSlop(); - mTapTimeoutInMillis = ViewConfiguration.getTapTimeout(); + mHandwritingTimeoutInMillis = ViewConfiguration.getLongPressTimeout(); mImm = inputMethodManager; } @@ -145,7 +145,7 @@ public class HandwritingInitiator { final long timeElapsed = motionEvent.getEventTime() - mState.mStylusDownTimeInMillis; - if (timeElapsed > mTapTimeoutInMillis) { + if (timeElapsed > mHandwritingTimeoutInMillis) { reset(); return; } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index cdbf8b44140a..b72725ad2c32 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3165,11 +3165,8 @@ public final class ViewRootImpl implements ViewParent, // possible that checking the most recent value is actually more // correct here. if (!mStopped || wasReportNextDraw) { - boolean focusChangedDueToTouchMode = ensureTouchModeLocally( - (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0); - if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth() - || mHeight != host.getMeasuredHeight() || dispatchApplyInsets || - updatedConfiguration) { + if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight() + || dispatchApplyInsets || updatedConfiguration) { int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width, lp.privateFlags); int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height, diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java index 2dc5fbd5439f..b0da877bfddd 100644 --- a/core/java/android/view/WindowManagerGlobal.java +++ b/core/java/android/view/WindowManagerGlobal.java @@ -60,47 +60,41 @@ public final class WindowManagerGlobal { private static boolean sUseBLASTAdapter = false; /** - * The user is navigating with keys (not the touch screen), so - * navigational focus should be shown. - */ - public static final int RELAYOUT_RES_IN_TOUCH_MODE = 0x1; - - /** * This is the first time the window is being drawn, * so the client must call drawingFinished() when done */ - public static final int RELAYOUT_RES_FIRST_TIME = 0x2; + public static final int RELAYOUT_RES_FIRST_TIME = 1; /** * The window manager has changed the surface from the last call. */ - public static final int RELAYOUT_RES_SURFACE_CHANGED = 0x4; + public static final int RELAYOUT_RES_SURFACE_CHANGED = 1 << 1; /** * The window is being resized by dragging on the docked divider. The client should render * at (0, 0) and extend its background to the background frame passed into * {@link IWindow#resized}. */ - public static final int RELAYOUT_RES_DRAG_RESIZING_DOCKED = 0x8; + public static final int RELAYOUT_RES_DRAG_RESIZING_DOCKED = 1 << 2; /** * The window is being resized by dragging one of the window corners, * in this case the surface would be fullscreen-sized. The client should * render to the actual frame location (instead of (0,curScrollY)). */ - public static final int RELAYOUT_RES_DRAG_RESIZING_FREEFORM = 0x10; + public static final int RELAYOUT_RES_DRAG_RESIZING_FREEFORM = 1 << 3; /** * The window manager has changed the size of the surface from the last call. */ - public static final int RELAYOUT_RES_SURFACE_RESIZED = 0x20; + public static final int RELAYOUT_RES_SURFACE_RESIZED = 1 << 4; /** * In multi-window we force show the system bars. Because we don't want that the surface size * changes in this mode, we instead have a flag whether the system bar sizes should always be * consumed, so the app is treated like there is no virtual system bars at all. */ - public static final int RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS = 0x40; + public static final int RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS = 1 << 5; /** * This flag indicates the client should not directly submit it's next frame, @@ -108,7 +102,7 @@ public final class WindowManagerGlobal { * {@link WindowManagerService#finishDrawing}. This is used by the WM * BLASTSyncEngine to synchronize rendering of multiple windows. */ - public static final int RELAYOUT_RES_BLAST_SYNC = 0x80; + public static final int RELAYOUT_RES_BLAST_SYNC = 1 << 6; /** * Flag for relayout: the client will be later giving diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index ad151df05579..06588b2cbb6d 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -332,8 +332,7 @@ public class WindowlessWindowManager implements IWindowSession { outInsetsState.set(mInsetsState); } - // Include whether the window is in touch mode. - return isInTouchMode() ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0; + return 0; } @Override diff --git a/core/proto/android/os/appbatterystats.proto b/core/proto/android/os/appbatterystats.proto new file mode 100644 index 000000000000..8769ebb74979 --- /dev/null +++ b/core/proto/android/os/appbatterystats.proto @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2022 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. + */ + +syntax = "proto2"; +package android.os; + +option java_multiple_files = true; + +message AppBatteryStatsProto { + message UidStats { + optional int32 uid = 1; + + message ProcessStateStats { + enum ProcessState { + UNSPECIFIED = 0; + FOREGROUND = 1; + BACKGROUND = 2; + FOREGROUND_SERVICE = 3; + CACHED = 4; + } + + optional ProcessState process_state = 1; + + // Time spent in this state in the past 24 hours + optional int64 duration_ms = 2; + // Estimated power consumed in this state in the past 24 hours + optional double power_mah = 3; + } + + repeated ProcessStateStats process_state_stats = 2; + } + + repeated UidStats uid_stats = 1; +} diff --git a/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java b/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java index 1ae9649dfe06..e303934c4aad 100644 --- a/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java +++ b/core/tests/coretests/src/android/view/stylus/HandwritingInitiatorTest.java @@ -60,7 +60,7 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class HandwritingInitiatorTest { private static final int TOUCH_SLOP = 8; - private static final long TAP_TIMEOUT = ViewConfiguration.getTapTimeout(); + private static final long TIMEOUT = ViewConfiguration.getLongPressTimeout(); private static final Rect sHwArea = new Rect(100, 200, 500, 500); private HandwritingInitiator mHandwritingInitiator; @@ -177,7 +177,7 @@ public class HandwritingInitiatorTest { } @Test - public void onTouchEvent_notStartHandwriting_when_stylusMove_afterTapTimeOut() { + public void onTouchEvent_notStartHandwriting_when_stylusMove_afterTimeOut() { mHandwritingInitiator.onInputConnectionCreated(mTestView); final int x1 = 10; final int y1 = 10; @@ -187,7 +187,7 @@ public class HandwritingInitiatorTest { final int x2 = x1 + TOUCH_SLOP * 2; final int y2 = y1; - final long time2 = time1 + TAP_TIMEOUT + 10L; + final long time2 = time1 + TIMEOUT + 10L; MotionEvent stylusEvent2 = createStylusEvent(ACTION_MOVE, x2, y2, time2); mHandwritingInitiator.onTouchEvent(stylusEvent2); diff --git a/data/etc/Android.bp b/data/etc/Android.bp index 2a82d8ecf5ee..df51871c57d9 100644 --- a/data/etc/Android.bp +++ b/data/etc/Android.bp @@ -71,14 +71,6 @@ prebuilt_etc { } prebuilt_etc { - name: "privapp_whitelist_com.android.cellbroadcastreceiver", - system_ext_specific: true, - sub_dir: "permissions", - src: "com.android.cellbroadcastreceiver.xml", - filename_from_src: true, -} - -prebuilt_etc { name: "privapp_whitelist_com.android.contacts", product_specific: true, sub_dir: "permissions", diff --git a/data/etc/com.android.cellbroadcastreceiver.xml b/data/etc/com.android.cellbroadcastreceiver.xml deleted file mode 100644 index bc62bbc845f3..000000000000 --- a/data/etc/com.android.cellbroadcastreceiver.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ~ 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 - --> -<permissions> - <privapp-permissions package="com.android.cellbroadcastreceiver"> - <permission name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS"/> - <permission name="android.permission.INTERACT_ACROSS_USERS"/> - <permission name="android.permission.MANAGE_USERS"/> - <permission name="android.permission.STATUS_BAR"/> - <permission name="android.permission.MODIFY_PHONE_STATE"/> - <permission name="android.permission.MODIFY_CELL_BROADCASTS"/> - <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/> - <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/> - <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/> - </privapp-permissions> -</permissions> diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml index 2d1db716b700..d1873a0f40cf 100644 --- a/data/etc/com.android.systemui.xml +++ b/data/etc/com.android.systemui.xml @@ -76,8 +76,5 @@ <permission name="android.permission.FORCE_STOP_PACKAGES" /> <permission name="android.permission.ACCESS_FPS_COUNTER" /> <permission name="android.permission.CHANGE_CONFIGURATION" /> - <permission name="android.permission.LOG_COMPAT_CHANGE" /> - <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> - <permission name="android.permission.READ_DEVICE_CONFIG" /> </privapp-permissions> </permissions> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 3e91eedf2dde..56285489a91d 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -38,24 +38,6 @@ applications that come with the platform <permission name="android.permission.CRYPT_KEEPER"/> </privapp-permissions> - <privapp-permissions package="com.android.cellbroadcastreceiver.module"> - <permission name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS"/> - <permission name="android.permission.INTERACT_ACROSS_USERS"/> - <permission name="android.permission.MANAGE_USERS"/> - <permission name="android.permission.STATUS_BAR"/> - <permission name="android.permission.MODIFY_PHONE_STATE"/> - <permission name="android.permission.MODIFY_CELL_BROADCASTS"/> - <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/> - <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/> - <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/> - </privapp-permissions> - - <privapp-permissions package="com.android.cellbroadcastservice"> - <permission name="android.permission.MODIFY_PHONE_STATE"/> - <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/> - <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/> - </privapp-permissions> - <privapp-permissions package="com.android.externalstorage"> <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <permission name="android.permission.WRITE_MEDIA_STORAGE"/> diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 61f7facf0916..a2f5301e353f 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -329,7 +329,7 @@ public class Typeface { FontFamily.Builder familyBuilder = null; for (final FontFileResourceEntry fontFile : filesEntry.getEntries()) { final Font.Builder fontBuilder = new Font.Builder(mgr, fontFile.getFileName(), - false /* isAsset */, 0 /* cookie */) + false /* isAsset */, AssetManager.COOKIE_UNKNOWN) .setTtcIndex(fontFile.getTtcIndex()) .setFontVariationSettings(fontFile.getVariationSettings()); if (fontFile.getWeight() != Typeface.RESOLVE_BY_FONT_TABLE) { diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java index cd7936d50dff..abd0be9c2872 100644 --- a/graphics/java/android/graphics/fonts/Font.java +++ b/graphics/java/android/graphics/fonts/Font.java @@ -179,7 +179,7 @@ public final class Font { */ public Builder(@NonNull AssetManager am, @NonNull String path) { try { - mBuffer = createBuffer(am, path, true /* is asset */, 0 /* cookie */); + mBuffer = createBuffer(am, path, true /* is asset */, AssetManager.COOKIE_UNKNOWN); } catch (IOException e) { mException = e; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java index c2d582354b13..7397e5273753 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java @@ -194,7 +194,7 @@ public class PipBoundsAlgorithm { public float getAspectRatioOrDefault( @android.annotation.Nullable PictureInPictureParams params) { return params != null && params.hasSetAspectRatio() - ? params.getAspectRatio() + ? params.getAspectRatioFloat() : getDefaultAspectRatio(); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index c1e78251da2b..5d6b041f9006 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -1071,13 +1071,13 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, */ private boolean applyPictureInPictureParams(@NonNull PictureInPictureParams params) { final Rational currentAspectRatio = - mPictureInPictureParams != null ? mPictureInPictureParams.getAspectRatioRational() + mPictureInPictureParams != null ? mPictureInPictureParams.getAspectRatio() : null; final boolean aspectRatioChanged = !Objects.equals(currentAspectRatio, - params.getAspectRatioRational()); + params.getAspectRatio()); mPictureInPictureParams = params; if (aspectRatioChanged) { - mPipBoundsState.setAspectRatio(params.getAspectRatio()); + mPipBoundsState.setAspectRatio(params.getAspectRatioFloat()); } return aspectRatioChanged; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java index d880f821ee73..986554853034 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipBoundsState.java @@ -75,7 +75,7 @@ public class TvPipBoundsState extends PipBoundsState { public void setBoundsStateForEntry(ComponentName componentName, ActivityInfo activityInfo, PictureInPictureParams params, PipBoundsAlgorithm pipBoundsAlgorithm) { super.setBoundsStateForEntry(componentName, activityInfo, params, pipBoundsAlgorithm); - setDesiredTvExpandedAspectRatio(params.getExpandedAspectRatio(), true); + setDesiredTvExpandedAspectRatio(params.getExpandedAspectRatioFloat(), true); } /** Resets the TV PiP state for a new activity. */ diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java index f1605f1ffe5d..033056cb2a69 100644 --- a/location/java/android/location/Location.java +++ b/location/java/android/location/Location.java @@ -132,31 +132,31 @@ public class Location implements Parcelable { } /** - * Construct a new Location object that is copied from an existing one. + * Constructs a new location copied from the given location. */ - public Location(@NonNull Location l) { - set(l); + public Location(@NonNull Location location) { + set(location); } /** * Turns this location into a copy of the given location. */ - public void set(@NonNull Location l) { - mFieldsMask = l.mFieldsMask; - mProvider = l.mProvider; - mTimeMs = l.mTimeMs; - mElapsedRealtimeNs = l.mElapsedRealtimeNs; - mElapsedRealtimeUncertaintyNs = l.mElapsedRealtimeUncertaintyNs; - mLatitudeDegrees = l.mLatitudeDegrees; - mLongitudeDegrees = l.mLongitudeDegrees; - mHorizontalAccuracyMeters = l.mHorizontalAccuracyMeters; - mAltitudeMeters = l.mAltitudeMeters; - mAltitudeAccuracyMeters = l.mAltitudeAccuracyMeters; - mSpeedMetersPerSecond = l.mSpeedMetersPerSecond; - mSpeedAccuracyMetersPerSecond = l.mSpeedAccuracyMetersPerSecond; - mBearingDegrees = l.mBearingDegrees; - mBearingAccuracyDegrees = l.mBearingAccuracyDegrees; - mExtras = (l.mExtras == null) ? null : new Bundle(l.mExtras); + public void set(@NonNull Location location) { + mFieldsMask = location.mFieldsMask; + mProvider = location.mProvider; + mTimeMs = location.mTimeMs; + mElapsedRealtimeNs = location.mElapsedRealtimeNs; + mElapsedRealtimeUncertaintyNs = location.mElapsedRealtimeUncertaintyNs; + mLatitudeDegrees = location.mLatitudeDegrees; + mLongitudeDegrees = location.mLongitudeDegrees; + mHorizontalAccuracyMeters = location.mHorizontalAccuracyMeters; + mAltitudeMeters = location.mAltitudeMeters; + mAltitudeAccuracyMeters = location.mAltitudeAccuracyMeters; + mSpeedMetersPerSecond = location.mSpeedMetersPerSecond; + mSpeedAccuracyMetersPerSecond = location.mSpeedAccuracyMetersPerSecond; + mBearingDegrees = location.mBearingDegrees; + mBearingAccuracyDegrees = location.mBearingAccuracyDegrees; + mExtras = (location.mExtras == null) ? null : new Bundle(location.mExtras); } /** @@ -182,14 +182,13 @@ public class Location implements Parcelable { } /** - * Returns the approximate distance in meters between this - * location and the given location. Distance is defined using - * the WGS84 ellipsoid. + * Returns the approximate distance in meters between this location and the given location. + * Distance is defined using the WGS84 ellipsoid. * * @param dest the destination location * @return the approximate distance in meters */ - public @FloatRange float distanceTo(@NonNull Location dest) { + public @FloatRange(from = 0.0) float distanceTo(@NonNull Location dest) { BearingDistanceCache cache = sBearingDistanceCache.get(); // See if we already have the result if (mLatitudeDegrees != cache.mLat1 || mLongitudeDegrees != cache.mLon1 @@ -201,11 +200,10 @@ public class Location implements Parcelable { } /** - * Returns the approximate initial bearing in degrees East of true - * North when traveling along the shortest path between this - * location and the given location. The shortest path is defined - * using the WGS84 ellipsoid. Locations that are (nearly) - * antipodal may produce meaningless results. + * Returns the approximate initial bearing in degrees east of true north when traveling along + * the shortest path between this location and the given location. The shortest path is defined + * using the WGS84 ellipsoid. Locations that are (nearly) antipodal may produce meaningless + * results. * * @param dest the destination location * @return the initial bearing in degrees @@ -254,7 +252,7 @@ public class Location implements Parcelable { * not be used to order or compare locations. Prefer {@link #getElapsedRealtimeNanos} for that * purpose, as the elapsed realtime clock is guaranteed to be monotonic. * - * <p>On the other hand, this method may be useful for presenting a human readable time to the + * <p>On the other hand, this method may be useful for presenting a human-readable time to the * user, or as a heuristic for comparing location fixes across reboot or across devices. * * <p>All locations generated by the {@link LocationManager} are guaranteed to have this time @@ -263,25 +261,24 @@ public class Location implements Parcelable { * * @return the Unix epoch time of this location */ - public @IntRange long getTime() { + public @IntRange(from = 0) long getTime() { return mTimeMs; } /** * Sets the Unix epoch time of this location fix, in milliseconds since the start of the Unix - * epoch (00:00:00 January 1, 1970 UTC). + * epoch (00:00:00 January 1 1970 UTC). * * @param timeMs the Unix epoch time of this location - * @see #getTime for more information about times / clocks */ - public void setTime(@IntRange long timeMs) { + public void setTime(@IntRange(from = 0) long timeMs) { mTimeMs = timeMs; } /** * Return the time of this fix in nanoseconds of elapsed realtime since system boot. * - * <p>This value can be compared with {@link android.os.SystemClock#elapsedRealtimeNanos}, to + * <p>This value can be compared with {@link android.os.SystemClock#elapsedRealtimeNanos} to * reliably order or compare locations. This is reliable because elapsed realtime is guaranteed * to be monotonic and continues to increment even when the system is in deep sleep (unlike * {@link #getTime}). However, since elapsed realtime is with reference to system boot, it does @@ -292,7 +289,7 @@ public class Location implements Parcelable { * * @return elapsed realtime of this location in nanoseconds */ - public @IntRange long getElapsedRealtimeNanos() { + public @IntRange(from = 0) long getElapsedRealtimeNanos() { return mElapsedRealtimeNs; } @@ -302,7 +299,7 @@ public class Location implements Parcelable { * @return elapsed realtime of this location in milliseconds * @see #getElapsedRealtimeNanos() */ - public @IntRange long getElapsedRealtimeMillis() { + public @IntRange(from = 0) long getElapsedRealtimeMillis() { return NANOSECONDS.toMillis(mElapsedRealtimeNs); } @@ -312,7 +309,7 @@ public class Location implements Parcelable { * * @return age of this location in milliseconds */ - public @IntRange long getElapsedRealtimeAgeMillis() { + public @IntRange(from = 0) long getElapsedRealtimeAgeMillis() { return getElapsedRealtimeAgeMillis(SystemClock.elapsedRealtime()); } @@ -323,7 +320,8 @@ public class Location implements Parcelable { * @param referenceRealtimeMs reference realtime in milliseconds * @return age of this location in milliseconds */ - public @IntRange long getElapsedRealtimeAgeMillis(@IntRange long referenceRealtimeMs) { + public long getElapsedRealtimeAgeMillis( + @IntRange(from = 0) long referenceRealtimeMs) { return referenceRealtimeMs - getElapsedRealtimeMillis(); } @@ -332,7 +330,7 @@ public class Location implements Parcelable { * * @param elapsedRealtimeNs elapsed realtime in nanoseconds */ - public void setElapsedRealtimeNanos(@IntRange long elapsedRealtimeNs) { + public void setElapsedRealtimeNanos(@IntRange(from = 0) long elapsedRealtimeNs) { mElapsedRealtimeNs = elapsedRealtimeNs; } @@ -346,7 +344,7 @@ public class Location implements Parcelable { * * @return uncertainty in nanoseconds of the elapsed realtime of this location */ - public @FloatRange double getElapsedRealtimeUncertaintyNanos() { + public @FloatRange(from = 0.0) double getElapsedRealtimeUncertaintyNanos() { return mElapsedRealtimeUncertaintyNs; } @@ -358,20 +356,20 @@ public class Location implements Parcelable { * this location */ public void setElapsedRealtimeUncertaintyNanos( - @FloatRange double elapsedRealtimeUncertaintyNs) { + @FloatRange(from = 0.0) double elapsedRealtimeUncertaintyNs) { mElapsedRealtimeUncertaintyNs = elapsedRealtimeUncertaintyNs; mFieldsMask |= HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK; } /** - * True if this location has a elapsed realtime uncertainty, false otherwise. + * True if this location has an elapsed realtime uncertainty, false otherwise. */ public boolean hasElapsedRealtimeUncertaintyNanos() { return (mFieldsMask & HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK) != 0; } /** - * Removes the elapsed realtime uncertainy from this location. + * Removes the elapsed realtime uncertainty from this location. */ public void removeElapsedRealtimeUncertaintyNanos() { mFieldsMask &= ~HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK; @@ -383,7 +381,7 @@ public class Location implements Parcelable { * * @return latitude of this location */ - public @FloatRange double getLatitude() { + public @FloatRange(from = -90.0, to = 90.0) double getLatitude() { return mLatitudeDegrees; } @@ -392,7 +390,7 @@ public class Location implements Parcelable { * * @param latitudeDegrees latitude in degrees */ - public void setLatitude(@FloatRange double latitudeDegrees) { + public void setLatitude(@FloatRange(from = -90.0, to = 90.0) double latitudeDegrees) { mLatitudeDegrees = latitudeDegrees; } @@ -402,7 +400,7 @@ public class Location implements Parcelable { * * @return longitude of this location */ - public @FloatRange double getLongitude() { + public @FloatRange(from = -180.0, to = 180.0) double getLongitude() { return mLongitudeDegrees; } @@ -411,7 +409,7 @@ public class Location implements Parcelable { * * @param longitudeDegrees longitude in degrees */ - public void setLongitude(@FloatRange double longitudeDegrees) { + public void setLongitude(@FloatRange(from = -180.0, to = 180.0) double longitudeDegrees) { mLongitudeDegrees = longitudeDegrees; } @@ -423,12 +421,12 @@ public class Location implements Parcelable { * reported location, there is a 68% chance that the true location falls within this circle. * This accuracy value is only valid for horizontal positioning, and not vertical positioning. * - * <p>This is only valid if {@link #hasSpeed()} is true. All locations generated by the + * <p>This is only valid if {@link #hasAccuracy()} is true. All locations generated by the * {@link LocationManager} include horizontal accuracy. * * @return horizontal accuracy of this location */ - public @FloatRange float getAccuracy() { + public @FloatRange(from = 0.0) float getAccuracy() { return mHorizontalAccuracyMeters; } @@ -437,7 +435,7 @@ public class Location implements Parcelable { * * @param horizontalAccuracyMeters horizontal altitude in meters */ - public void setAccuracy(@FloatRange float horizontalAccuracyMeters) { + public void setAccuracy(@FloatRange(from = 0.0) float horizontalAccuracyMeters) { mHorizontalAccuracyMeters = horizontalAccuracyMeters; mFieldsMask |= HAS_HORIZONTAL_ACCURACY_MASK; } @@ -500,7 +498,7 @@ public class Location implements Parcelable { * * @return vertical accuracy of this location */ - public @FloatRange float getVerticalAccuracyMeters() { + public @FloatRange(from = 0.0) float getVerticalAccuracyMeters() { return mAltitudeAccuracyMeters; } @@ -509,7 +507,7 @@ public class Location implements Parcelable { * * @param altitudeAccuracyMeters altitude accuracy in meters */ - public void setVerticalAccuracyMeters(@FloatRange float altitudeAccuracyMeters) { + public void setVerticalAccuracyMeters(@FloatRange(from = 0.0) float altitudeAccuracyMeters) { mAltitudeAccuracyMeters = altitudeAccuracyMeters; mFieldsMask |= HAS_ALTITUDE_ACCURACY_MASK; } @@ -538,17 +536,16 @@ public class Location implements Parcelable { * * @return speed at the time of this location */ - public @FloatRange float getSpeed() { + public @FloatRange(from = 0.0) float getSpeed() { return mSpeedMetersPerSecond; } /** - * Set the speed at the time of this location, in meters per second. Prefer not to set negative - * speeds. + * Set the speed at the time of this location, in meters per second. * * @param speedMetersPerSecond speed in meters per second */ - public void setSpeed(@FloatRange float speedMetersPerSecond) { + public void setSpeed(@FloatRange(from = 0.0) float speedMetersPerSecond) { mSpeedMetersPerSecond = speedMetersPerSecond; mFieldsMask |= HAS_SPEED_MASK; } @@ -576,7 +573,7 @@ public class Location implements Parcelable { * * @return vertical accuracy of this location */ - public @FloatRange float getSpeedAccuracyMetersPerSecond() { + public @FloatRange(from = 0.0) float getSpeedAccuracyMetersPerSecond() { return mSpeedAccuracyMetersPerSecond; } @@ -585,7 +582,8 @@ public class Location implements Parcelable { * * @param speedAccuracyMeterPerSecond speed accuracy in meters per second */ - public void setSpeedAccuracyMetersPerSecond(@FloatRange float speedAccuracyMeterPerSecond) { + public void setSpeedAccuracyMetersPerSecond( + @FloatRange(from = 0.0) float speedAccuracyMeterPerSecond) { mSpeedAccuracyMetersPerSecond = speedAccuracyMeterPerSecond; mFieldsMask |= HAS_SPEED_ACCURACY_MASK; } @@ -613,7 +611,7 @@ public class Location implements Parcelable { * * @return bearing at the time of this location */ - public @FloatRange(from = 0f, to = 360f, toInclusive = false) float getBearing() { + public @FloatRange(from = 0.0, to = 360.0, toInclusive = false) float getBearing() { return mBearingDegrees; } @@ -663,7 +661,7 @@ public class Location implements Parcelable { * * @return bearing accuracy in degrees of this location */ - public @FloatRange float getBearingAccuracyDegrees() { + public @FloatRange(from = 0.0) float getBearingAccuracyDegrees() { return mBearingAccuracyDegrees; } @@ -672,7 +670,7 @@ public class Location implements Parcelable { * * @param bearingAccuracyDegrees bearing accuracy in degrees */ - public void setBearingAccuracyDegrees(@FloatRange float bearingAccuracyDegrees) { + public void setBearingAccuracyDegrees(@FloatRange(from = 0.0) float bearingAccuracyDegrees) { mBearingAccuracyDegrees = bearingAccuracyDegrees; mFieldsMask |= HAS_BEARING_ACCURACY_MASK; } @@ -692,9 +690,11 @@ public class Location implements Parcelable { } /** - * Returns true if the Location came from a mock provider. + * Returns true if this is a mock location. If this location comes from the Android framework, + * this indicates that the location was provided by a test location provider, and thus may not + * be related to the actual location of the device. * - * @return true if this Location came from a mock provider, false otherwise + * @return true if this location came from a mock provider, false otherwise * @deprecated Prefer {@link #isMock()} instead. */ @Deprecated @@ -703,9 +703,9 @@ public class Location implements Parcelable { } /** - * Flag this Location as having come from a mock provider or not. + * Flag this location as having come from a mock provider or not. * - * @param isFromMockProvider true if this Location came from a mock provider, false otherwise + * @param isFromMockProvider true if this location came from a mock provider, false otherwise * @deprecated Prefer {@link #setMock(boolean)} instead. * @hide */ @@ -745,7 +745,7 @@ public class Location implements Parcelable { * will be present for any location. * * <ul> - * <li> satellites - the number of satellites used to derive the GNSS fix + * <li> satellites - the number of satellites used to derive a GNSS fix * </ul> */ public @Nullable Bundle getExtras() { @@ -899,7 +899,13 @@ public class Location implements Parcelable { return s.toString(); } - /** Dumps location. */ + /** + * Dumps location information to the given Printer. + * + * @deprecated Prefer to use {@link #toString()} along with whatever custom formatting is + * required instead of this method. It is not this class's job to manage print representations. + */ + @Deprecated public void dump(@NonNull Printer pw, @Nullable String prefix) { pw.println(prefix + this); } @@ -1209,10 +1215,10 @@ public class Location implements Parcelable { * @throws IllegalArgumentException if results is null or has length < 1 */ public static void distanceBetween( - @FloatRange double startLatitude, - @FloatRange double startLongitude, - @FloatRange double endLatitude, - @FloatRange double endLongitude, + @FloatRange(from = -90.0, to = 90.0) double startLatitude, + @FloatRange(from = -180.0, to = 180.0) double startLongitude, + @FloatRange(from = -90.0, to = 90.0) double endLatitude, + @FloatRange(from = -180.0, to = 180.0) double endLongitude, float[] results) { if (results == null || results.length < 1) { throw new IllegalArgumentException("results is null or has length < 1"); diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index bdbb740a849b..c186700a4326 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -39,6 +39,7 @@ import android.media.IRecordingConfigDispatcher; import android.media.IRingtonePlayer; import android.media.IStrategyPreferredDevicesDispatcher; import android.media.ISpatializerCallback; +import android.media.ISpatializerHeadTrackerAvailableCallback; import android.media.ISpatializerHeadTrackingModeCallback; import android.media.ISpatializerHeadToSoundStagePoseCallback; import android.media.ISpatializerOutputCallback; @@ -414,6 +415,11 @@ interface IAudioService { boolean isHeadTrackerEnabled(in AudioDeviceAttributes device); + boolean isHeadTrackerAvailable(); + + void registerSpatializerHeadTrackerAvailableCallback( + in ISpatializerHeadTrackerAvailableCallback cb, boolean register); + void setSpatializerEnabled(boolean enabled); boolean canBeSpatialized(in AudioAttributes aa, in AudioFormat af); diff --git a/media/java/android/media/ISpatializerHeadTrackerAvailableCallback.aidl b/media/java/android/media/ISpatializerHeadTrackerAvailableCallback.aidl new file mode 100644 index 000000000000..dc5ee1d4e985 --- /dev/null +++ b/media/java/android/media/ISpatializerHeadTrackerAvailableCallback.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2022 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; + +/** + * AIDL for the AudioService to signal whether audio device used by Spatializer has head tracker. + * + * {@hide} + */ +oneway interface ISpatializerHeadTrackerAvailableCallback { + + void dispatchSpatializerHeadTrackerAvailable(boolean available); +} diff --git a/media/java/android/media/Spatializer.java b/media/java/android/media/Spatializer.java index be0ef37345ed..8811e16b3317 100644 --- a/media/java/android/media/Spatializer.java +++ b/media/java/android/media/Spatializer.java @@ -185,6 +185,45 @@ public class Spatializer { return false; } + /** + * Returns whether a head tracker is currently available for the audio device used by the + * spatializer effect. + * @return true if a head tracker is available and the effect is enabled, false otherwise. + * @see OnHeadTrackerAvailableListener + * @see #addOnHeadTrackerAvailableListener(Executor, OnHeadTrackerAvailableListener) + */ + public boolean isHeadTrackerAvailable() { + try { + return mAm.getService().isHeadTrackerAvailable(); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + return false; + } + + /** + * Adds a listener to be notified of changes to the availability of a head tracker. + * @param executor the {@code Executor} handling the callback + * @param listener the listener to receive availability updates + * @see #removeOnHeadTrackerAvailableListener(OnHeadTrackerAvailableListener) + */ + public void addOnHeadTrackerAvailableListener(@NonNull @CallbackExecutor Executor executor, + @NonNull OnHeadTrackerAvailableListener listener) { + mHeadTrackerListenerMgr.addListener(executor, listener, + "addOnHeadTrackerAvailableListener", + () -> new SpatializerHeadTrackerAvailableDispatcherStub()); + } + + /** + * Removes a previously registered listener for the availability of a head tracker. + * @param listener the listener previously registered with + * {@link #addOnHeadTrackerAvailableListener(Executor, OnHeadTrackerAvailableListener)} + */ + public void removeOnHeadTrackerAvailableListener( + @NonNull OnHeadTrackerAvailableListener listener) { + mHeadTrackerListenerMgr.removeListener(listener, "removeOnHeadTrackerAvailableListener"); + } + /** @hide */ @IntDef(flag = false, value = { SPATIALIZER_IMMERSIVE_LEVEL_OTHER, @@ -401,6 +440,22 @@ public class Spatializer { @HeadTrackingModeSet int mode); } + /** + * Interface to be notified of changes to the availability of a head tracker on the audio + * device to be used by the spatializer effect. + */ + public interface OnHeadTrackerAvailableListener { + /** + * Called when the availability of the head tracker changed. + * @param spatializer the {@code Spatializer} instance for which the head tracker + * availability was updated + * @param available true if the audio device that would output audio processed by + * the {@code Spatializer} has a head tracker associated with it, false + * otherwise. + */ + void onHeadTrackerAvailableChanged(@NonNull Spatializer spatializer, + boolean available); + } /** * @hide @@ -935,6 +990,36 @@ public class Spatializer { } //----------------------------------------------------------------------------- + // head tracker availability callback management and stub + /** + * manages the OnHeadTrackerAvailableListener listeners and the + * SpatializerHeadTrackerAvailableDispatcherStub + */ + private final CallbackUtil.LazyListenerManager<OnHeadTrackerAvailableListener> + mHeadTrackerListenerMgr = new CallbackUtil.LazyListenerManager(); + + private final class SpatializerHeadTrackerAvailableDispatcherStub + extends ISpatializerHeadTrackerAvailableCallback.Stub + implements CallbackUtil.DispatcherStub { + @Override + public void register(boolean register) { + try { + mAm.getService().registerSpatializerHeadTrackerAvailableCallback(this, register); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + @Override + @SuppressLint("GuardedBy") // lock applied inside callListeners method + public void dispatchSpatializerHeadTrackerAvailable(boolean available) { + mHeadTrackerListenerMgr.callListeners( + (listener) -> listener.onHeadTrackerAvailableChanged( + Spatializer.this, available)); + } + } + + //----------------------------------------------------------------------------- // head pose callback management and stub private final Object mPoseListenerLock = new Object(); /** diff --git a/media/java/android/media/tv/AitInfo.java b/media/java/android/media/tv/AitInfo.java index 8e80a62be3de..c88a2b5048df 100644 --- a/media/java/android/media/tv/AitInfo.java +++ b/media/java/android/media/tv/AitInfo.java @@ -17,7 +17,7 @@ package android.media.tv; import android.annotation.NonNull; -import android.media.tv.interactive.TvInteractiveAppInfo; +import android.media.tv.interactive.TvInteractiveAppServiceInfo; import android.os.Parcel; import android.os.Parcelable; @@ -50,7 +50,7 @@ public final class AitInfo implements Parcelable { /** * Constructs AIT info. */ - public AitInfo(@TvInteractiveAppInfo.InteractiveAppType int type, int version) { + public AitInfo(@TvInteractiveAppServiceInfo.InteractiveAppType int type, int version) { mType = type; mVersion = version; } @@ -58,7 +58,7 @@ public final class AitInfo implements Parcelable { /** * Gets interactive app type. */ - @TvInteractiveAppInfo.InteractiveAppType + @TvInteractiveAppServiceInfo.InteractiveAppType public int getType() { return mType; } diff --git a/media/java/android/media/tv/CommandRequest.java b/media/java/android/media/tv/CommandRequest.java index ffb6e07bc485..3245fb504f85 100644 --- a/media/java/android/media/tv/CommandRequest.java +++ b/media/java/android/media/tv/CommandRequest.java @@ -24,6 +24,8 @@ import android.os.Parcelable; * A request for command from broadcast signal. */ public final class CommandRequest extends BroadcastInfoRequest implements Parcelable { + public static final String ARGUMENT_TYPE_XML = "xml"; + public static final String ARGUMENT_TYPE_JSON = "json"; private static final @TvInputManager.BroadcastInfoType int REQUEST_TYPE = TvInputManager.BROADCAST_INFO_TYPE_COMMAND; @@ -41,35 +43,38 @@ public final class CommandRequest extends BroadcastInfoRequest implements Parcel } }; - private final String mNameSpace; + private final String mNamespace; private final String mName; private final String mArguments; + private final String mArgumentType; static CommandRequest createFromParcelBody(Parcel in) { return new CommandRequest(in); } - public CommandRequest(int requestId, @RequestOption int option, @NonNull String nameSpace, - @NonNull String name, @NonNull String arguments) { + public CommandRequest(int requestId, @RequestOption int option, @NonNull String namespace, + @NonNull String name, @NonNull String arguments, @NonNull String argumentType) { super(REQUEST_TYPE, requestId, option); - mNameSpace = nameSpace; + mNamespace = namespace; mName = name; mArguments = arguments; + mArgumentType = argumentType; } CommandRequest(Parcel source) { super(REQUEST_TYPE, source); - mNameSpace = source.readString(); + mNamespace = source.readString(); mName = source.readString(); mArguments = source.readString(); + mArgumentType = source.readString(); } /** * Gets the namespace of the command. */ @NonNull - public String getNameSpace() { - return mNameSpace; + public String getNamespace() { + return mNamespace; } /** @@ -89,6 +94,15 @@ public final class CommandRequest extends BroadcastInfoRequest implements Parcel return mArguments; } + /** + * Gets the argument type of the command. + * It could be either JSON or XML. + */ + @NonNull + public String getArgumentType() { + return mArgumentType; + } + @Override public int describeContents() { return 0; @@ -97,8 +111,9 @@ public final class CommandRequest extends BroadcastInfoRequest implements Parcel @Override public void writeToParcel(@NonNull Parcel dest, int flags) { super.writeToParcel(dest, flags); - dest.writeString(mNameSpace); + dest.writeString(mNamespace); dest.writeString(mName); dest.writeString(mArguments); + dest.writeString(mArgumentType); } } diff --git a/media/java/android/media/tv/CommandResponse.java b/media/java/android/media/tv/CommandResponse.java index c8853f1d8373..8e448cdbd707 100644 --- a/media/java/android/media/tv/CommandResponse.java +++ b/media/java/android/media/tv/CommandResponse.java @@ -25,6 +25,8 @@ import android.os.Parcelable; * A response for command from broadcast signal. */ public final class CommandResponse extends BroadcastInfoResponse implements Parcelable { + public static final String RESPONSE_TYPE_XML = "xml"; + public static final String RESPONSE_TYPE_JSON = "json"; private static final @TvInputManager.BroadcastInfoType int RESPONSE_TYPE = TvInputManager.BROADCAST_INFO_TYPE_COMMAND; @@ -43,20 +45,23 @@ public final class CommandResponse extends BroadcastInfoResponse implements Parc }; private final String mResponse; + private final String mResponseType; static CommandResponse createFromParcelBody(Parcel in) { return new CommandResponse(in); } - public CommandResponse(int requestId, int sequence, - @ResponseResult int responseResult, @Nullable String response) { + public CommandResponse(int requestId, int sequence, @ResponseResult int responseResult, + @Nullable String response, @NonNull String responseType) { super(RESPONSE_TYPE, requestId, sequence, responseResult); mResponse = response; + mResponseType = responseType; } CommandResponse(Parcel source) { super(RESPONSE_TYPE, source); mResponse = source.readString(); + mResponseType = source.readString(); } /** @@ -68,6 +73,15 @@ public final class CommandResponse extends BroadcastInfoResponse implements Parc return mResponse; } + /** + * Gets the type of the command response. + * It could be either JSON or XML. + */ + @NonNull + public String getResponseType() { + return mResponseType; + } + @Override public int describeContents() { return 0; @@ -77,5 +91,6 @@ public final class CommandResponse extends BroadcastInfoResponse implements Parc public void writeToParcel(@NonNull Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeString(mResponse); + dest.writeString(mResponseType); } } diff --git a/media/java/android/media/tv/SectionRequest.java b/media/java/android/media/tv/SectionRequest.java index 5957528554dc..078e83222e4e 100644 --- a/media/java/android/media/tv/SectionRequest.java +++ b/media/java/android/media/tv/SectionRequest.java @@ -80,6 +80,11 @@ public final class SectionRequest extends BroadcastInfoRequest implements Parcel /** * Gets the version number of requested session. If it is null, value will be -1. + * <p>The consistency of version numbers between request and response depends on + * {@link BroadcastInfoRequest.RequestOption}. If the request has RequestOption value + * REQUEST_OPTION_AUTO_UPDATE, then the response may be set to the latest version which may be + * different from the version of the request. Otherwise, response with a different version from + * its request will be considered invalid. */ public int getVersion() { return mVersion; diff --git a/media/java/android/media/tv/SectionResponse.java b/media/java/android/media/tv/SectionResponse.java index 35836bed385f..f38ea9dfac99 100644 --- a/media/java/android/media/tv/SectionResponse.java +++ b/media/java/android/media/tv/SectionResponse.java @@ -74,14 +74,20 @@ public final class SectionResponse extends BroadcastInfoResponse implements Parc } /** - * Gets the Version number of requested session. + * Gets the Version number of requested session. If it is null, value will be -1. + * <p>The consistency of version numbers between request and response depends on + * {@link BroadcastInfoRequest.RequestOption}. If the request has RequestOption value + * REQUEST_OPTION_AUTO_UPDATE, then the response may be set to the latest version which may be + * different from the version of the request. Otherwise, response with a different version from + * its request will be considered invalid. */ public int getVersion() { return mVersion; } /** - * Gets the raw data of session. + * Gets the raw data of session. The sessionData field represents payload data of the session + * after session header, which includes version and sessionId. */ @NonNull public Bundle getSessionData() { diff --git a/media/java/android/media/tv/StreamEventResponse.java b/media/java/android/media/tv/StreamEventResponse.java index f952ce929842..28dff374d539 100644 --- a/media/java/android/media/tv/StreamEventResponse.java +++ b/media/java/android/media/tv/StreamEventResponse.java @@ -43,7 +43,7 @@ public final class StreamEventResponse extends BroadcastInfoResponse implements }; private final int mEventId; - private final long mNpt; + private final long mNptMillis; private final byte[] mData; static StreamEventResponse createFromParcelBody(Parcel in) { @@ -51,17 +51,17 @@ public final class StreamEventResponse extends BroadcastInfoResponse implements } public StreamEventResponse(int requestId, int sequence, @ResponseResult int responseResult, - int eventId, long npt, @Nullable byte[] data) { + int eventId, long nptMillis, @Nullable byte[] data) { super(RESPONSE_TYPE, requestId, sequence, responseResult); mEventId = eventId; - mNpt = npt; + mNptMillis = nptMillis; mData = data; } private StreamEventResponse(@NonNull Parcel source) { super(RESPONSE_TYPE, source); mEventId = source.readInt(); - mNpt = source.readLong(); + mNptMillis = source.readLong(); int dataLength = source.readInt(); mData = new byte[dataLength]; source.readByteArray(mData); @@ -76,9 +76,10 @@ public final class StreamEventResponse extends BroadcastInfoResponse implements /** * Returns the NPT(Normal Play Time) value when the event occurred or will occur. + * <p>The time unit of NPT is millisecond. */ - public long getNpt() { - return mNpt; + public long getNptMillis() { + return mNptMillis; } /** @@ -98,7 +99,7 @@ public final class StreamEventResponse extends BroadcastInfoResponse implements public void writeToParcel(@NonNull Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeInt(mEventId); - dest.writeLong(mNpt); + dest.writeLong(mNptMillis); dest.writeInt(mData.length); dest.writeByteArray(mData); } diff --git a/media/java/android/media/tv/TableRequest.java b/media/java/android/media/tv/TableRequest.java index 37df4eaf1ed0..a1a6b516859c 100644 --- a/media/java/android/media/tv/TableRequest.java +++ b/media/java/android/media/tv/TableRequest.java @@ -91,7 +91,12 @@ public final class TableRequest extends BroadcastInfoRequest implements Parcelab } /** - * Gets the version number of requested table. + * Gets the version number of requested table. If it is null, value will be -1. + * <p>The consistency of version numbers between request and response depends on + * {@link BroadcastInfoRequest.RequestOption}. If the request has RequestOption value + * REQUEST_OPTION_AUTO_UPDATE, then the response may be set to the latest version which may be + * different from the version of the request. Otherwise, response with a different version from + * its request will be considered invalid. */ public int getVersion() { return mVersion; diff --git a/media/java/android/media/tv/TableResponse.java b/media/java/android/media/tv/TableResponse.java index e9f1136875f5..afc9bee5fb85 100644 --- a/media/java/android/media/tv/TableResponse.java +++ b/media/java/android/media/tv/TableResponse.java @@ -76,7 +76,12 @@ public final class TableResponse extends BroadcastInfoResponse implements Parcel } /** - * Gets the Version number of table. + * Gets the version number of requested table. If it is null, value will be -1. + * <p>The consistency of version numbers between request and response depends on + * {@link BroadcastInfoRequest.RequestOption}. If the request has RequestOption value + * REQUEST_OPTION_AUTO_UPDATE, then the response may be set to the latest version which may be + * different from the version of the request. Otherwise, response with a different version from + * its request will be considered invalid. */ public int getVersion() { return mVersion; diff --git a/media/java/android/media/tv/TimelineResponse.java b/media/java/android/media/tv/TimelineResponse.java index fbeb0c4bf268..7de30f579a35 100644 --- a/media/java/android/media/tv/TimelineResponse.java +++ b/media/java/android/media/tv/TimelineResponse.java @@ -18,6 +18,7 @@ package android.media.tv; import android.annotation.NonNull; import android.annotation.Nullable; +import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; @@ -79,8 +80,8 @@ public final class TimelineResponse extends BroadcastInfoResponse implements Par * that conveys Time Values on it. */ @Nullable - public String getSelector() { - return mSelector; + public Uri getSelector() { + return Uri.parse(mSelector); } /** diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl index aaabe342d9f1..839118265732 100644 --- a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl +++ b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl @@ -23,7 +23,7 @@ import android.media.tv.TvTrackInfo; import android.media.tv.interactive.AppLinkInfo; import android.media.tv.interactive.ITvInteractiveAppClient; import android.media.tv.interactive.ITvInteractiveAppManagerCallback; -import android.media.tv.interactive.TvInteractiveAppInfo; +import android.media.tv.interactive.TvInteractiveAppServiceInfo; import android.net.Uri; import android.os.Bundle; import android.view.Surface; @@ -33,7 +33,7 @@ import android.view.Surface; * @hide */ interface ITvInteractiveAppManager { - List<TvInteractiveAppInfo> getTvInteractiveAppServiceList(int userId); + List<TvInteractiveAppServiceInfo> getTvInteractiveAppServiceList(int userId); void prepare(String tiasId, int type, int userId); void registerAppLinkInfo(String tiasId, in AppLinkInfo info, int userId); void unregisterAppLinkInfo(String tiasId, in AppLinkInfo info, int userId); diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppManagerCallback.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppManagerCallback.aidl index 23be4c64fcc4..f410c0fac488 100644 --- a/media/java/android/media/tv/interactive/ITvInteractiveAppManagerCallback.aidl +++ b/media/java/android/media/tv/interactive/ITvInteractiveAppManagerCallback.aidl @@ -16,7 +16,7 @@ package android.media.tv.interactive; -import android.media.tv.interactive.TvInteractiveAppInfo; +import android.media.tv.interactive.TvInteractiveAppServiceInfo; /** * Interface to receive callbacks from ITvInteractiveAppManager regardless of sessions. @@ -26,6 +26,6 @@ interface ITvInteractiveAppManagerCallback { void onInteractiveAppServiceAdded(in String iAppServiceId); void onInteractiveAppServiceRemoved(in String iAppServiceId); void onInteractiveAppServiceUpdated(in String iAppServiceId); - void onTvInteractiveAppInfoUpdated(in TvInteractiveAppInfo tvIAppInfo); + void onTvInteractiveAppServiceInfoUpdated(in TvInteractiveAppServiceInfo tvIAppInfo); void onStateChanged(in String iAppServiceId, int type, int state, int err); }
\ No newline at end of file diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java index 9eb4a6c393ab..83ff0f50f1a3 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java @@ -249,7 +249,7 @@ public final class TvInteractiveAppManager { * * @see #sendAppLinkCommand(String, Bundle) * @see #ACTION_APP_LINK_COMMAND - * @see android.media.tv.interactive.TvInteractiveAppInfo#getId() + * @see android.media.tv.interactive.TvInteractiveAppServiceInfo#getId() */ public static final String INTENT_KEY_INTERACTIVE_APP_SERVICE_ID = "interactive_app_id"; @@ -269,7 +269,7 @@ public final class TvInteractiveAppManager { * * @see #sendAppLinkCommand(String, Bundle) * @see #ACTION_APP_LINK_COMMAND - * @see android.media.tv.interactive.TvInteractiveAppInfo#getSupportedTypes() + * @see android.media.tv.interactive.TvInteractiveAppServiceInfo#getSupportedTypes() * @see android.media.tv.interactive.TvInteractiveAppView#createBiInteractiveApp(Uri, Bundle) */ public static final String INTENT_KEY_BI_INTERACTIVE_APP_TYPE = "bi_interactive_app_type"; @@ -543,11 +543,11 @@ public final class TvInteractiveAppManager { } @Override - public void onTvInteractiveAppInfoUpdated(TvInteractiveAppInfo iAppInfo) { + public void onTvInteractiveAppServiceInfoUpdated(TvInteractiveAppServiceInfo iAppInfo) { // TODO: add public API updateInteractiveAppInfo() synchronized (mLock) { for (TvInteractiveAppCallbackRecord record : mCallbackRecords) { - record.postTvInteractiveAppInfoUpdated(iAppInfo); + record.postTvInteractiveAppServiceInfoUpdated(iAppInfo); } } } @@ -611,16 +611,17 @@ public final class TvInteractiveAppManager { * This is called when the information about an existing TV Interactive App service has been * updated. * - * <p>Because the system automatically creates a <code>TvInteractiveAppInfo</code> object - * for each TV Interactive App service based on the information collected from the + * <p>Because the system automatically creates a <code>TvInteractiveAppServiceInfo</code> + * object for each TV Interactive App service based on the information collected from the * <code>AndroidManifest.xml</code>, this method is only called back when such information * has changed dynamically. * - * @param iAppInfo The <code>TvInteractiveAppInfo</code> object that contains new + * @param iAppInfo The <code>TvInteractiveAppServiceInfo</code> object that contains new * information. * @hide */ - public void onTvInteractiveAppInfoUpdated(@NonNull TvInteractiveAppInfo iAppInfo) { + public void onTvInteractiveAppServiceInfoUpdated( + @NonNull TvInteractiveAppServiceInfo iAppInfo) { } /** @@ -634,7 +635,7 @@ public final class TvInteractiveAppManager { */ public void onTvInteractiveAppServiceStateChanged( @NonNull String iAppServiceId, - @TvInteractiveAppInfo.InteractiveAppType int type, + @TvInteractiveAppServiceInfo.InteractiveAppType int type, @ServiceState int state, @ErrorCode int err) { } @@ -680,11 +681,12 @@ public final class TvInteractiveAppManager { }); } - public void postTvInteractiveAppInfoUpdated(final TvInteractiveAppInfo iAppInfo) { + public void postTvInteractiveAppServiceInfoUpdated( + final TvInteractiveAppServiceInfo iAppInfo) { mExecutor.execute(new Runnable() { @Override public void run() { - mCallback.onTvInteractiveAppInfoUpdated(iAppInfo); + mCallback.onTvInteractiveAppServiceInfoUpdated(iAppInfo); } }); } @@ -737,11 +739,11 @@ public final class TvInteractiveAppManager { /** * Returns the complete list of TV Interactive App service on the system. * - * @return List of {@link TvInteractiveAppInfo} for each TV Interactive App service that + * @return List of {@link TvInteractiveAppServiceInfo} for each TV Interactive App service that * describes its meta information. */ @NonNull - public List<TvInteractiveAppInfo> getTvInteractiveAppServiceList() { + public List<TvInteractiveAppServiceInfo> getTvInteractiveAppServiceList() { try { return mService.getTvInteractiveAppServiceList(mUserId); } catch (RemoteException e) { diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java index d22fd83872e1..316fbbab6d37 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java @@ -242,7 +242,7 @@ public abstract class TvInteractiveAppService extends Service { /** * Prepares TV Interactive App service for the given type. */ - public abstract void onPrepare(@TvInteractiveAppInfo.InteractiveAppType int type); + public abstract void onPrepare(@TvInteractiveAppServiceInfo.InteractiveAppType int type); /** * Called when a request to register an Android application link info record is received. @@ -277,7 +277,7 @@ public abstract class TvInteractiveAppService extends Service { @Nullable public abstract Session onCreateSession( @NonNull String iAppServiceId, - @TvInteractiveAppInfo.InteractiveAppType int type); + @TvInteractiveAppServiceInfo.InteractiveAppType int type); /** * Notifies the system when the state of the interactive app RTE has been changed. @@ -289,7 +289,7 @@ public abstract class TvInteractiveAppService extends Service { * {@link TvInteractiveAppManager#SERVICE_STATE_ERROR}. */ public final void notifyStateChanged( - @TvInteractiveAppInfo.InteractiveAppType int type, + @TvInteractiveAppServiceInfo.InteractiveAppType int type, @TvInteractiveAppManager.ServiceState int state, @TvInteractiveAppManager.ErrorCode int error) { SomeArgs args = SomeArgs.obtain(); diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl b/media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.aidl index 5e1501677b3b..49600a05cb7f 100644 --- a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.aidl +++ b/media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.aidl @@ -16,4 +16,4 @@ package android.media.tv.interactive; -parcelable TvInteractiveAppInfo;
\ No newline at end of file +parcelable TvInteractiveAppServiceInfo;
\ No newline at end of file diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.java b/media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.java index 6103db001b19..9c1b2425c013 100644 --- a/media/java/android/media/tv/interactive/TvInteractiveAppInfo.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.java @@ -45,9 +45,9 @@ import java.util.List; /** * This class is used to specify meta information of a TV interactive app. */ -public final class TvInteractiveAppInfo implements Parcelable { +public final class TvInteractiveAppServiceInfo implements Parcelable { private static final boolean DEBUG = false; - private static final String TAG = "TvInteractiveAppInfo"; + private static final String TAG = "TvInteractiveAppServiceInfo"; private static final String XML_START_TAG_NAME = "tv-interactive-app"; @@ -71,7 +71,7 @@ public final class TvInteractiveAppInfo implements Parcelable { private final String mId; private int mTypes; - public TvInteractiveAppInfo(@NonNull Context context, @NonNull ComponentName component) { + public TvInteractiveAppServiceInfo(@NonNull Context context, @NonNull ComponentName component) { if (context == null) { throw new IllegalArgumentException("context cannot be null."); } @@ -94,28 +94,28 @@ public final class TvInteractiveAppInfo implements Parcelable { mId = id; mTypes = toTypesFlag(types); } - private TvInteractiveAppInfo(ResolveInfo service, String id, int types) { + private TvInteractiveAppServiceInfo(ResolveInfo service, String id, int types) { mService = service; mId = id; mTypes = types; } - private TvInteractiveAppInfo(@NonNull Parcel in) { + private TvInteractiveAppServiceInfo(@NonNull Parcel in) { mService = ResolveInfo.CREATOR.createFromParcel(in); mId = in.readString(); mTypes = in.readInt(); } - public static final @NonNull Creator<TvInteractiveAppInfo> CREATOR = - new Creator<TvInteractiveAppInfo>() { + public static final @NonNull Creator<TvInteractiveAppServiceInfo> CREATOR = + new Creator<TvInteractiveAppServiceInfo>() { @Override - public TvInteractiveAppInfo createFromParcel(Parcel in) { - return new TvInteractiveAppInfo(in); + public TvInteractiveAppServiceInfo createFromParcel(Parcel in) { + return new TvInteractiveAppServiceInfo(in); } @Override - public TvInteractiveAppInfo[] newArray(int size) { - return new TvInteractiveAppInfo[size]; + public TvInteractiveAppServiceInfo[] newArray(int size) { + return new TvInteractiveAppServiceInfo[size]; } }; diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppView.java b/media/java/android/media/tv/interactive/TvInteractiveAppView.java index 773e54f30744..212051120e77 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppView.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppView.java @@ -148,12 +148,14 @@ public class TvInteractiveAppView extends ViewGroup { /** * Sets the callback to be invoked when an event is dispatched to this TvInteractiveAppView. * - * @param callback The callback to receive events. A value of {@code null} removes the existing - * callback. + * @param callback the callback to receive events. MUST NOT be {@code null}. + * + * @see #clearCallback() */ public void setCallback( @NonNull @CallbackExecutor Executor executor, @NonNull TvInteractiveAppCallback callback) { + com.android.internal.util.AnnotationValidations.validate(NonNull.class, null, callback); synchronized (mCallbackLock) { mCallbackExecutor = executor; mCallback = callback; @@ -162,6 +164,8 @@ public class TvInteractiveAppView extends ViewGroup { /** * Clears the callback. + * + * @see #setCallback(Executor, TvInteractiveAppCallback) */ public void clearCallback() { synchronized (mCallbackLock) { @@ -389,13 +393,13 @@ public class TvInteractiveAppView extends ViewGroup { * Prepares the interactive application. * * @param iAppServiceId the interactive app service ID, which can be found in - * {@link TvInteractiveAppInfo#getId()}. + * {@link TvInteractiveAppServiceInfo#getId()}. * * @see android.media.tv.interactive.TvInteractiveAppManager#getTvInteractiveAppServiceList() */ public void prepareInteractiveApp( @NonNull String iAppServiceId, - @TvInteractiveAppInfo.InteractiveAppType int type) { + @TvInteractiveAppServiceInfo.InteractiveAppType int type) { // TODO: document and handle the cases that this method is called multiple times. if (DEBUG) { Log.d(TAG, "prepareInteractiveApp"); diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl index 7eaa01e262fe..01ff02dfc5b3 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl @@ -26,6 +26,7 @@ import android.net.NetworkStats; oneway interface INetworkStatsProviderCallback { void notifyStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats); void notifyAlertReached(); - void notifyWarningOrLimitReached(); + void notifyWarningReached(); + void notifyLimitReached(); void unregister(); } diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java index 23fc06927ef9..d37a53dbf1e9 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java +++ b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java @@ -152,19 +152,19 @@ public abstract class NetworkStatsProvider { try { // Reuse the code path to notify warning reached with limit reached // since framework handles them in the same way. - getProviderCallbackBinderOrThrow().notifyWarningOrLimitReached(); + getProviderCallbackBinderOrThrow().notifyWarningReached(); } catch (RemoteException e) { e.rethrowAsRuntimeException(); } } /** - * Notify system that the quota set by {@link #onSetLimit} or limit set by + * Notify system that the limit set by {@link #onSetLimit} or limit set by * {@link #onSetWarningAndLimit} has been reached. */ public void notifyLimitReached() { try { - getProviderCallbackBinderOrThrow().notifyWarningOrLimitReached(); + getProviderCallbackBinderOrThrow().notifyLimitReached(); } catch (RemoteException e) { e.rethrowAsRuntimeException(); } diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java index 8c5207cbae4a..e3794e441a23 100644 --- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java @@ -2393,10 +2393,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void notifyWarningOrLimitReached() { - Log.d(TAG, mTag + ": notifyWarningOrLimitReached"); + public void notifyWarningReached() { + Log.d(TAG, mTag + ": notifyWarningReached"); BinderUtils.withCleanCallingIdentity(() -> - mNetworkPolicyManager.notifyStatsProviderWarningOrLimitReached()); + mNetworkPolicyManager.notifyStatsProviderWarningReached()); + } + + @Override + public void notifyLimitReached() { + Log.d(TAG, mTag + ": notifyLimitReached"); + BinderUtils.withCleanCallingIdentity(() -> + mNetworkPolicyManager.notifyStatsProviderLimitReached()); } @Override diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 3d91c5aceeed..7f300cafaa08 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -1117,7 +1117,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> final boolean isOnCall = Utils.isAudioModeOngoingCall(mContext); if ((mIsActiveDeviceHearingAid) || (mIsActiveDeviceHeadset && isOnCall) - || (mIsActiveDeviceA2dp && !isOnCall)) { + || (mIsActiveDeviceA2dp && !isOnCall) + || mIsActiveDeviceLeAudio) { if (isTwsBatteryAvailable(leftBattery, rightBattery) && !shortSummary) { stringRes = R.string.bluetooth_active_battery_level_untethered; } else if (batteryLevelPercentageString != null && !shortSummary) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java index e203cbaa3da5..19df1e9c0730 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java @@ -246,6 +246,13 @@ public class LeAudioProfile implements LocalBluetoothProfile { return R.drawable.ic_bt_le_audio; } + public int getAudioLocation(BluetoothDevice device) { + if (mService == null || device == null) { + return BluetoothLeAudio.AUDIO_LOCATION_INVALID; + } + return mService.getAudioLocation(device); + } + @RequiresApi(Build.VERSION_CODES.S) protected void finalize() { if (DEBUG) { diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 4b45cc338a6a..e24b2d6c6aa9 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -314,11 +314,6 @@ <!-- To change system captions state --> <uses-permission android:name="android.permission.SET_SYSTEM_AUDIO_CAPTION" /> - <!-- Compat framework --> - <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" /> - <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> - <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> - <protected-broadcast android:name="com.android.settingslib.action.REGISTER_SLICE_RECEIVER" /> <protected-broadcast android:name="com.android.settingslib.action.UNREGISTER_SLICE_RECEIVER" /> <protected-broadcast android:name="com.android.settings.flashlight.action.FLASHLIGHT_CHANGED" /> diff --git a/packages/SystemUI/res/drawable/ic_circular_unchecked.xml b/packages/SystemUI/res/drawable/ic_circular_unchecked.xml index 9b43cf64f116..779ab816d925 100644 --- a/packages/SystemUI/res/drawable/ic_circular_unchecked.xml +++ b/packages/SystemUI/res/drawable/ic_circular_unchecked.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> <path - android:fillColor="@color/media_dialog_inactive_item_main_content" + android:fillColor="@color/media_dialog_item_main_content" android:pathData="M12,22q-2.075,0 -3.9,-0.788 -1.825,-0.787 -3.175,-2.137 -1.35,-1.35 -2.137,-3.175Q2,14.075 2,12t0.788,-3.9q0.787,-1.825 2.137,-3.175 1.35,-1.35 3.175,-2.137Q9.925,2 12,2t3.9,0.788q1.825,0.787 3.175,2.137 1.35,1.35 2.137,3.175Q22,9.925 22,12t-0.788,3.9q-0.787,1.825 -2.137,3.175 -1.35,1.35 -3.175,2.137Q14.075,22 12,22zM12,12zM12,20q3.325,0 5.663,-2.337Q20,15.325 20,12t-2.337,-5.662Q15.325,4 12,4T6.338,6.338Q4,8.675 4,12q0,3.325 2.338,5.663Q8.675,20 12,20z"/> </vector> diff --git a/packages/SystemUI/res/drawable/media_output_status_check.xml b/packages/SystemUI/res/drawable/media_output_status_check.xml index 1b750f8959b9..5fbc42b245b8 100644 --- a/packages/SystemUI/res/drawable/media_output_status_check.xml +++ b/packages/SystemUI/res/drawable/media_output_status_check.xml @@ -21,6 +21,6 @@ android:viewportHeight="24" android:tint="?attr/colorControlNormal"> <path - android:fillColor="@color/media_dialog_item_status" + android:fillColor="@color/media_dialog_item_main_content" android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/> </vector> diff --git a/packages/SystemUI/res/drawable/media_output_status_failed.xml b/packages/SystemUI/res/drawable/media_output_status_failed.xml index 05c635833441..0599e239a9ee 100644 --- a/packages/SystemUI/res/drawable/media_output_status_failed.xml +++ b/packages/SystemUI/res/drawable/media_output_status_failed.xml @@ -21,6 +21,6 @@ android:viewportHeight="24" android:tint="?attr/colorControlNormal"> <path - android:fillColor="@color/media_dialog_inactive_item_main_content" + android:fillColor="@color/media_dialog_item_main_content" android:pathData="M11,7h2v2h-2zM11,11h2v6h-2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/> </vector> diff --git a/packages/SystemUI/res/layout/media_output_list_item.xml b/packages/SystemUI/res/layout/media_output_list_item.xml index eeb37c7b062d..20747fad021b 100644 --- a/packages/SystemUI/res/layout/media_output_list_item.xml +++ b/packages/SystemUI/res/layout/media_output_list_item.xml @@ -83,7 +83,7 @@ android:ellipsize="end" android:maxLines="1" android:fontFamily="@*android:string/config_headlineFontFamilyMedium" - android:textColor="@color/media_dialog_inactive_item_main_content" + android:textColor="@color/media_dialog_item_main_content" android:textSize="16sp"/> <TextView android:id="@+id/subtitle" @@ -91,7 +91,7 @@ android:layout_height="wrap_content" android:ellipsize="end" android:maxLines="1" - android:textColor="@color/media_dialog_inactive_item_main_content" + android:textColor="@color/media_dialog_item_main_content" android:textSize="14sp" android:fontFamily="@*android:string/config_bodyFontFamily" android:visibility="gone"/> diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml index ad2bc79a5c96..5aa608084510 100644 --- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml +++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml @@ -37,7 +37,5 @@ android:layout_gravity="center" android:minWidth="@dimen/ongoing_appops_chip_min_width" android:maxWidth="@dimen/ongoing_appops_chip_max_width" - android:clipChildren="false" - android:clipToPadding="false" /> </com.android.systemui.privacy.OngoingPrivacyChip>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml index 4b96d5d660ee..3a638b1e5098 100644 --- a/packages/SystemUI/res/values-night/colors.xml +++ b/packages/SystemUI/res/values-night/colors.xml @@ -67,10 +67,12 @@ <!-- media output dialog--> <color name="media_dialog_background">@color/material_dynamic_neutral10</color> - <color name="media_dialog_active_item_main_content">@color/material_dynamic_neutral10</color> - <color name="media_dialog_inactive_item_main_content">@color/material_dynamic_neutral10</color> - <color name="media_dialog_item_status">@color/material_dynamic_neutral10</color> - <color name="media_dialog_item_background">@color/material_dynamic_secondary95</color> + <color name="media_dialog_item_main_content">@color/material_dynamic_primary90</color> + <color name="media_dialog_item_background">@color/material_dynamic_neutral_variant20</color> + <color name="media_dialog_connected_item_background">@color/material_dynamic_secondary20</color> + <color name="media_dialog_seekbar_progress">@color/material_dynamic_secondary40</color> + <color name="media_dialog_button_background">@color/material_dynamic_primary70</color> + <color name="media_dialog_solid_button_text">@color/material_dynamic_secondary20</color> <!-- Biometric dialog colors --> <color name="biometric_dialog_gray">#ffcccccc</color> diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml index c56ba7b6b1ce..02a4070415dd 100644 --- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml @@ -37,6 +37,7 @@ <dimen name="controls_task_view_right_margin">8dp</dimen> <dimen name="split_shade_header_height">42dp</dimen> + <dimen name="status_bar_header_height_keyguard">42dp</dimen> <!-- Distance that the full shade transition takes in order to complete by tapping on a button like "expand". --> diff --git a/packages/SystemUI/res/values-sw720dp-land/dimens.xml b/packages/SystemUI/res/values-sw720dp-land/dimens.xml index f267088ea203..bdd704936594 100644 --- a/packages/SystemUI/res/values-sw720dp-land/dimens.xml +++ b/packages/SystemUI/res/values-sw720dp-land/dimens.xml @@ -24,6 +24,7 @@ <dimen name="keyguard_split_shade_top_margin">72dp</dimen> <dimen name="split_shade_header_height">56dp</dimen> + <dimen name="status_bar_header_height_keyguard">56dp</dimen> <dimen name="qs_media_session_height_expanded">184dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 1edaaadfb433..49fc8482712a 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -176,10 +176,12 @@ <!-- media output dialog--> <color name="media_dialog_background" android:lstar="98">@color/material_dynamic_neutral90</color> - <color name="media_dialog_active_item_main_content">@color/material_dynamic_primary10</color> - <color name="media_dialog_inactive_item_main_content">@color/material_dynamic_primary40</color> - <color name="media_dialog_item_status">@color/material_dynamic_primary10</color> + <color name="media_dialog_item_main_content">@color/material_dynamic_primary20</color> <color name="media_dialog_item_background">@color/material_dynamic_secondary95</color> + <color name="media_dialog_connected_item_background">@color/material_dynamic_primary90</color> + <color name="media_dialog_seekbar_progress">@color/material_dynamic_secondary40</color> + <color name="media_dialog_button_background">@color/material_dynamic_primary40</color> + <color name="media_dialog_solid_button_text">@color/material_dynamic_neutral95</color> <!-- controls --> <color name="control_primary_text">#E6FFFFFF</color> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index ffae6015c732..f73010e2a39a 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -941,6 +941,9 @@ <!-- Three privacy items. This value must not be exceeded --> <dimen name="ongoing_appops_chip_max_width">76dp</dimen> <dimen name="ongoing_appops_dot_diameter">6dp</dimen> + <dimen name="ongoing_appops_chip_min_animation_width">10dp</dimen> + <dimen name="ongoing_appops_chip_animation_in_status_bar_translation_x">15dp</dimen> + <dimen name="ongoing_appops_chip_animation_out_status_bar_translation_x">7dp</dimen> <!-- Total minimum padding to enforce to ensure that the dot can always show --> <dimen name="ongoing_appops_dot_min_padding">20dp</dimen> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 3ae21e08005d..f5c1382b9ae9 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -486,7 +486,7 @@ <style name="MediaOutputItemInactiveTitle"> <item name="android:textSize">16sp</item> - <item name="android:textColor">@color/media_dialog_inactive_item_main_content</item> + <item name="android:textColor">@color/media_dialog_item_main_content</item> </style> <style name="TunerSettings" parent="@android:style/Theme.DeviceDefault.Settings"> diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index 64c2d2e3858e..c100a0744b85 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -726,8 +726,8 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba boolean isCameraPrivacyEnabled = false; if (error == BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE - && mSensorPrivacyManager.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, - mCurrentDialogArgs.argi1 /* userId */)) { + && mSensorPrivacyManager.isSensorPrivacyEnabled( + SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE, SensorPrivacyManager.Sensors.CAMERA)) { isCameraPrivacyEnabled = true; } // TODO(b/141025588): Create separate methods for handling hard and soft errors. diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java index 61cfe925f640..2db3de173257 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java @@ -145,7 +145,7 @@ public class Flags { /***************************************/ // 900 - media public static final BooleanFlag MEDIA_TAP_TO_TRANSFER = new BooleanFlag(900, true); - public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, false); + public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, true); public static final BooleanFlag MEDIA_SESSION_LAYOUT = new BooleanFlag(902, true); public static final BooleanFlag MEDIA_NEARBY_DEVICES = new BooleanFlag(903, true); public static final BooleanFlag MEDIA_MUTE_AWAIT = new BooleanFlag(904, true); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 736e2e0e4035..acad30b4276f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -20,6 +20,7 @@ import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN; +import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_TRANSITION_FROM_AOD; import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_UNLOCK_ANIMATION; 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_DPM_LOCK_NOW; @@ -123,11 +124,11 @@ import com.android.systemui.statusbar.NotificationShadeDepthController; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.BiometricUnlockController; +import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.ScreenOffAnimationController; -import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.UserSwitcherController; @@ -1557,6 +1558,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, public void setOccluded(boolean isOccluded, boolean animate) { Trace.beginSection("KeyguardViewMediator#setOccluded"); if (DEBUG) Log.d(TAG, "setOccluded " + isOccluded); + mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_TRANSITION_FROM_AOD); mHandler.removeMessages(SET_OCCLUDED); Message msg = mHandler.obtainMessage(SET_OCCLUDED, isOccluded ? 1 : 0, animate ? 1 : 0); mHandler.sendMessage(msg); @@ -2805,6 +2807,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, IRemoteAnimationFinishedCallback finishedCallback) { Trace.beginSection("KeyguardViewMediator#startKeyguardExitAnimation"); + mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_TRANSITION_FROM_AOD); Message msg = mHandler.obtainMessage(START_KEYGUARD_EXIT_ANIM, new StartKeyguardExitAnimParams(transit, startTime, fadeoutDuration, apps, wallpapers, nonApps, finishedCallback)); diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index ffdd5376b12e..510d15bd7b73 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -137,6 +137,7 @@ public class MediaControlPanel { private MediaCarouselController mMediaCarouselController; private final MediaOutputDialogFactory mMediaOutputDialogFactory; private final FalsingManager mFalsingManager; + private final MediaFlags mMediaFlags; // Used for swipe-to-dismiss logging. protected boolean mIsImpressed = false; @@ -155,7 +156,7 @@ public class MediaControlPanel { Lazy<MediaDataManager> lazyMediaDataManager, MediaOutputDialogFactory mediaOutputDialogFactory, MediaCarouselController mediaCarouselController, - FalsingManager falsingManager, SystemClock systemClock) { + FalsingManager falsingManager, MediaFlags mediaFlags, SystemClock systemClock) { mContext = context; mBackgroundExecutor = backgroundExecutor; mActivityStarter = activityStarter; @@ -166,6 +167,7 @@ public class MediaControlPanel { mMediaOutputDialogFactory = mediaOutputDialogFactory; mMediaCarouselController = mediaCarouselController; mFalsingManager = falsingManager; + mMediaFlags = mediaFlags; mSystemClock = systemClock; loadDimens(); @@ -504,8 +506,9 @@ public class MediaControlPanel { List<MediaAction> actionIcons = data.getActions(); List<Integer> actionsWhenCollapsed = data.getActionsToShowInCompact(); - // If we got session actions, use those instead - if (data.getSemanticActions() != null) { + // If the session actions flag is enabled, but we're still using the regular layout, use + // the session actions anyways + if (mMediaFlags.areMediaSessionActionsEnabled() && data.getSemanticActions() != null) { MediaButton semanticActions = data.getSemanticActions(); actionIcons = new ArrayList<MediaAction>(); diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index ea92abd27e97..9e14fe91f21d 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -610,8 +610,7 @@ class MediaDataManager( var actionIcons: List<MediaAction> = emptyList() var actionsToShowCollapsed: List<Int> = emptyList() var semanticActions: MediaButton? = null - if (mediaFlags.areMediaSessionActionsEnabled(sbn.packageName, sbn.user.identifier) && - mediaController.playbackState != null) { + if (mediaFlags.areMediaSessionActionsEnabled() && mediaController.playbackState != null) { semanticActions = createActionsFromState(sbn.packageName, mediaController) } else { val actions = createActionsFromNotification(sbn) @@ -727,7 +726,7 @@ class MediaDataManager( } } - // Finally, assign the remaining button slots: play/pause A B C D + // Finally, assign the remaining button slots: C A play/pause B D // A = previous, else custom action (if not reserved) // B = next, else custom action (if not reserved) // C and D are always custom actions diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt index f5200f9c8c93..dd35a9a81399 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt @@ -16,7 +16,6 @@ package com.android.systemui.media -import android.app.StatusBarManager import com.android.systemui.dagger.SysUISingleton import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags @@ -27,17 +26,16 @@ class MediaFlags @Inject constructor(private val featureFlags: FeatureFlags) { /** * Check whether media control actions should be based on PlaybackState instead of notification */ - fun areMediaSessionActionsEnabled(packageName: String, userId: Int): Boolean { - val enabled = StatusBarManager.useMediaSessionActionsForApp(packageName, userId) - // Allow global override with flag - return enabled || featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS) + fun areMediaSessionActionsEnabled(): Boolean { + return featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS) } /** * Check whether media controls should use the new session-based layout */ fun useMediaSessionLayout(): Boolean { - return featureFlags.isEnabled(Flags.MEDIA_SESSION_LAYOUT) + return featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS) && + featureFlags.isEnabled(Flags.MEDIA_SESSION_LAYOUT) } /** diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java index 0b23ad50a726..a6464829623f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java @@ -119,7 +119,9 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { mCheckBox.setVisibility(View.GONE); mStatusIcon.setVisibility(View.GONE); mContainerLayout.setOnClickListener(null); - mTitleText.setTextColor(mController.getColorInactiveItem()); + mTitleText.setTextColor(mController.getColorItemContent()); + mSubTitleText.setTextColor(mController.getColorItemContent()); + mTwoLineTitleText.setTextColor(mController.getColorItemContent()); mSeekBar.getProgressDrawable().setColorFilter( new PorterDuffColorFilter(mController.getColorSeekbarProgress(), PorterDuff.Mode.SRC_IN)); @@ -140,7 +142,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { && !mController.hasAdjustVolumeUserRestriction()) { mProgressBar.getIndeterminateDrawable().setColorFilter( new PorterDuffColorFilter( - mController.getColorInactiveItem(), + mController.getColorItemContent(), PorterDuff.Mode.SRC_IN)); setSingleLineLayout(getItemTitle(device), true /* bFocused */, false /* showSeekBar*/, @@ -155,7 +157,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { mTitleIcon.setAlpha(DEVICE_CONNECTED_ALPHA); mStatusIcon.setImageDrawable( mContext.getDrawable(R.drawable.media_output_status_failed)); - mStatusIcon.setColorFilter(mController.getColorInactiveItem()); + mStatusIcon.setColorFilter(mController.getColorItemContent()); setTwoLineLayout(device, false /* bFocused */, false /* showSeekBar */, false /* showProgressBar */, true /* showSubtitle */, true /* showStatus */); @@ -163,7 +165,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { mContainerLayout.setOnClickListener(v -> onItemClick(v, device)); } else if (mController.getSelectedMediaDevice().size() > 1 && isDeviceIncluded(mController.getSelectedMediaDevice(), device)) { - mTitleText.setTextColor(mController.getColorActiveItem()); + mTitleText.setTextColor(mController.getColorItemContent()); setSingleLineLayout(getItemTitle(device), true /* bFocused */, true /* showSeekBar */, false /* showProgressBar */, false /* showStatus */); @@ -173,13 +175,13 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { mCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> { onCheckBoxClicked(false, device); }); - setCheckBoxColor(mCheckBox, mController.getColorActiveItem()); + setCheckBoxColor(mCheckBox, mController.getColorItemContent()); initSeekbar(device); } else if (!mController.hasAdjustVolumeUserRestriction() && currentlyConnected) { mStatusIcon.setImageDrawable( mContext.getDrawable(R.drawable.media_output_status_check)); - mStatusIcon.setColorFilter(mController.getColorActiveItem()); - mTitleText.setTextColor(mController.getColorActiveItem()); + mStatusIcon.setColorFilter(mController.getColorItemContent()); + mTitleText.setTextColor(mController.getColorItemContent()); setSingleLineLayout(getItemTitle(device), true /* bFocused */, true /* showSeekBar */, false /* showProgressBar */, true /* showStatus */); @@ -192,7 +194,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { mCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> { onCheckBoxClicked(true, device); }); - setCheckBoxColor(mCheckBox, mController.getColorInactiveItem()); + setCheckBoxColor(mCheckBox, mController.getColorItemContent()); setSingleLineLayout(getItemTitle(device), false /* bFocused */, false /* showSeekBar */, false /* showProgressBar */, false /* showStatus */); @@ -214,7 +216,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { @Override void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) { if (customizedItem == CUSTOMIZED_ITEM_PAIR_NEW) { - mTitleText.setTextColor(mController.getColorInactiveItem()); + mTitleText.setTextColor(mController.getColorItemContent()); mCheckBox.setVisibility(View.GONE); setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new), false /* bFocused */); diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java index 62d5c8e51005..df0c14b25c26 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java @@ -170,14 +170,16 @@ public abstract class MediaOutputBaseAdapter extends void setSingleLineLayout(CharSequence title, boolean bFocused, boolean showSeekBar, boolean showProgressBar, boolean showStatus) { mTwoLineLayout.setVisibility(View.GONE); + boolean isActive = showSeekBar || showProgressBar; final Drawable backgroundDrawable = - showSeekBar || showProgressBar + isActive ? mContext.getDrawable(R.drawable.media_output_item_background_active) .mutate() : mContext.getDrawable( R.drawable.media_output_item_background) .mutate(); backgroundDrawable.setColorFilter(new PorterDuffColorFilter( - mController.getColorItemBackground(), + isActive ? mController.getColorConnectedItemBackground() + : mController.getColorItemBackground(), PorterDuff.Mode.SRC_IN)); mItemLayout.setBackground(backgroundDrawable); mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE); @@ -366,7 +368,7 @@ public abstract class MediaOutputBaseAdapter extends .mutate(); drawable.setColorFilter( new PorterDuffColorFilter(Utils.getColorStateListDefaultColor(mContext, - R.color.media_dialog_active_item_main_content), + R.color.media_dialog_item_main_content), PorterDuff.Mode.SRC_IN)); return drawable; } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java index a8141c0e2fec..dcb1c7c4637c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java @@ -216,6 +216,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements PorterDuff.Mode.SRC_IN); mDoneButton.getBackground().setColorFilter(buttonColorFilter); mStopButton.getBackground().setColorFilter(buttonColorFilter); + mDoneButton.setTextColor(mAdapter.getController().getColorPositiveButtonText()); } mHeaderIcon.setVisibility(View.VISIBLE); mHeaderIcon.setImageIcon(icon); diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 0b6c68d17a4c..ea7f7f2bb646 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -110,11 +110,12 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, private MediaOutputMetricLogger mMetricLogger; - private int mColorActiveItem; - private int mColorInactiveItem; + private int mColorItemContent; private int mColorSeekbarProgress; private int mColorButtonBackground; private int mColorItemBackground; + private int mColorConnectedItemBackground; + private int mColorPositiveButtonText; @Inject public MediaOutputController(@NonNull Context context, String packageName, @@ -133,16 +134,18 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName); mDialogLaunchAnimator = dialogLaunchAnimator; mNearbyMediaDevicesManager = nearbyMediaDevicesManagerOptional.orElse(null); - mColorActiveItem = Utils.getColorStateListDefaultColor(mContext, - R.color.media_dialog_active_item_main_content); - mColorInactiveItem = Utils.getColorStateListDefaultColor(mContext, - R.color.media_dialog_inactive_item_main_content); + mColorItemContent = Utils.getColorStateListDefaultColor(mContext, + R.color.media_dialog_item_main_content); mColorSeekbarProgress = Utils.getColorStateListDefaultColor(mContext, - android.R.color.system_accent1_200); + R.color.media_dialog_seekbar_progress); mColorButtonBackground = Utils.getColorStateListDefaultColor(mContext, - R.color.media_dialog_item_background); + R.color.media_dialog_button_background); mColorItemBackground = Utils.getColorStateListDefaultColor(mContext, - android.R.color.system_accent2_50); + R.color.media_dialog_item_background); + mColorConnectedItemBackground = Utils.getColorStateListDefaultColor(mContext, + R.color.media_dialog_connected_item_background); + mColorPositiveButtonText = Utils.getColorStateListDefaultColor(mContext, + R.color.media_dialog_solid_button_text); } void start(@NonNull Callback cb) { @@ -322,8 +325,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, } void setColorFilter(Drawable drawable, boolean isActive) { - drawable.setColorFilter(new PorterDuffColorFilter(isActive - ? mColorActiveItem : mColorInactiveItem, + drawable.setColorFilter(new PorterDuffColorFilter(mColorItemContent, PorterDuff.Mode.SRC_IN)); } @@ -358,26 +360,32 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, ColorScheme mCurrentColorScheme = new ColorScheme(wallpaperColors, isDarkTheme); if (isDarkTheme) { - mColorActiveItem = mCurrentColorScheme.getNeutral1().get(10); - mColorInactiveItem = mCurrentColorScheme.getNeutral1().get(10); - mColorSeekbarProgress = mCurrentColorScheme.getAccent1().get(2); - mColorButtonBackground = mCurrentColorScheme.getAccent1().get(2); - mColorItemBackground = mCurrentColorScheme.getAccent2().get(0); + mColorItemContent = mCurrentColorScheme.getAccent1().get(2); // A1-100 + mColorSeekbarProgress = mCurrentColorScheme.getAccent2().get(7); // A2-600 + mColorButtonBackground = mCurrentColorScheme.getAccent1().get(4); // A1-300 + mColorItemBackground = mCurrentColorScheme.getNeutral2().get(9); // N2-800 + mColorConnectedItemBackground = mCurrentColorScheme.getAccent2().get(9); // A2-800 + mColorPositiveButtonText = mCurrentColorScheme.getAccent2().get(9); // A2-800 } else { - mColorActiveItem = mCurrentColorScheme.getNeutral1().get(10); - mColorInactiveItem = mCurrentColorScheme.getAccent1().get(7); - mColorSeekbarProgress = mCurrentColorScheme.getAccent1().get(3); - mColorButtonBackground = mCurrentColorScheme.getAccent1().get(3); - mColorItemBackground = mCurrentColorScheme.getAccent2().get(0); + mColorItemContent = mCurrentColorScheme.getAccent1().get(9); // A1-800 + mColorSeekbarProgress = mCurrentColorScheme.getAccent1().get(4); // A1-300 + mColorButtonBackground = mCurrentColorScheme.getAccent1().get(7); // A1-600 + mColorItemBackground = mCurrentColorScheme.getAccent2().get(1); // A2-50 + mColorConnectedItemBackground = mCurrentColorScheme.getAccent1().get(2); // A1-100 + mColorPositiveButtonText = mCurrentColorScheme.getNeutral1().get(1); // N1-50 } } - public int getColorActiveItem() { - return mColorActiveItem; + public int getColorConnectedItemBackground() { + return mColorConnectedItemBackground; + } + + public int getColorPositiveButtonText() { + return mColorPositiveButtonText; } - public int getColorInactiveItem() { - return mColorInactiveItem; + public int getColorItemContent() { + return mColorItemContent; } public int getColorSeekbarProgress() { diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt index 71cacac7f4df..3d5b3a3f70df 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt @@ -32,6 +32,7 @@ import android.view.View import android.view.ViewGroup import android.view.WindowManager import com.android.internal.widget.CachingIconView +import com.android.settingslib.Utils import com.android.systemui.R import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.gesture.TapGestureDetector @@ -150,40 +151,36 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( appNameOverride: CharSequence? = null, ) { val appIconView = currentChipView.requireViewById<CachingIconView>(R.id.app_icon) - appIconView.contentDescription = appNameOverride ?: getAppName(appPackageName) - - val appIcon = appIconDrawableOverride ?: getAppIcon(appPackageName) - val visibility = if (appIcon != null) { - View.VISIBLE - } else { - View.GONE - } - appIconView.setImageDrawable(appIcon) - appIconView.visibility = visibility - } - - /** Returns the icon of the app playing the media or null if we can't find it. */ - private fun getAppIcon(appPackageName: String?): Drawable? { - appPackageName ?: return null - return try { - context.packageManager.getApplicationIcon(appPackageName) - } catch (e: PackageManager.NameNotFoundException) { - Log.w(TAG, "Cannot find icon for package $appPackageName", e) - null - } + val appInfo = getAppInfo(appPackageName) + appIconView.contentDescription = appNameOverride ?: appInfo.appName + appIconView.setImageDrawable(appIconDrawableOverride ?: appInfo.appIcon) } - /** Returns the name of the app playing the media or null if we can't find it. */ - private fun getAppName(appPackageName: String?): String? { - appPackageName ?: return null - return try { - context.packageManager.getApplicationInfo( - appPackageName, PackageManager.ApplicationInfoFlags.of(0) - ).loadLabel(context.packageManager).toString() - } catch (e: PackageManager.NameNotFoundException) { - Log.w(TAG, "Cannot find name for package $appPackageName", e) - null + /** + * Returns the app name and icon of the app playing media, or a default name and icon if we + * can't find the app name/icon. + */ + private fun getAppInfo(appPackageName: String?): AppInfo { + if (appPackageName != null) { + try { + return AppInfo( + appName = context.packageManager.getApplicationInfo( + appPackageName, PackageManager.ApplicationInfoFlags.of(0) + ).loadLabel(context.packageManager).toString(), + appIcon = context.packageManager.getApplicationIcon(appPackageName) + ) + } catch (e: PackageManager.NameNotFoundException) { + Log.w(TAG, "Cannot find package $appPackageName", e) + } } + return AppInfo( + appName = context.getString(R.string.media_output_dialog_unknown_launch_app_name), + appIcon = context.resources.getDrawable(R.drawable.ic_cast).apply { + this.setTint( + Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary) + ) + } + ) } private fun onScreenTapped(e: MotionEvent) { @@ -205,3 +202,8 @@ object MediaTttRemovalReason { const val REASON_TIMEOUT = "TIMEOUT" const val REASON_SCREEN_TAP = "SCREEN_TAP" } + +private data class AppInfo( + val appName: String, + val appIcon: Drawable +) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index 3dd717d2f377..eaa66bbc15ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -226,10 +226,7 @@ public class NotificationShelf extends ActivatableNotificationView implements ? MathUtils.lerp(shortestWidth, getWidth(), fractionToShade) : getWidth(); ActivatableNotificationView anv = (ActivatableNotificationView) this; - NotificationBackgroundView bg = anv.getBackgroundNormal(); - if (bg != null) { - anv.getBackgroundNormal().setActualWidth((int) actualWidth); - } + anv.setBackgroundWidth((int) actualWidth); if (mShelfIcons != null) { mShelfIcons.setActualLayoutWidth((int) actualWidth); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java index 465ab93132f9..3013ad0070a0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java @@ -188,7 +188,7 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver, setContentDescription(state.contentDescription); int newVisibility = state.visible && !mForceHidden ? View.VISIBLE : View.GONE; - if (newVisibility != mMobileGroup.getVisibility()) { + if (newVisibility != mMobileGroup.getVisibility() && STATE_ICON == mVisibleState) { mMobileGroup.setVisibility(newVisibility); needsLayout = true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt index 9795dcf1fcd8..b74140da99d2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt @@ -16,9 +16,12 @@ package com.android.systemui.statusbar.events +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.animation.AnimatorSet import android.animation.ValueAnimator import android.content.Context -import android.graphics.Point +import android.graphics.Rect import android.view.Gravity import android.view.LayoutInflater import android.view.View @@ -30,6 +33,7 @@ import com.android.systemui.R import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider import com.android.systemui.statusbar.window.StatusBarWindowController import javax.inject.Inject +import kotlin.math.roundToInt /** * Controls the view for system event animations. @@ -38,7 +42,7 @@ class SystemEventChipAnimationController @Inject constructor( private val context: Context, private val statusBarWindowController: StatusBarWindowController, private val contentInsetsProvider: StatusBarContentInsetsProvider -) : SystemStatusChipAnimationCallback { +) : SystemStatusAnimationCallback { private lateinit var animationWindowView: FrameLayout @@ -49,90 +53,169 @@ class SystemEventChipAnimationController @Inject constructor( private var chipRight = 0 private var chipLeft = 0 private var chipWidth = 0 - private var dotCenter = Point(0, 0) + private var chipMinWidth = context.resources.getDimensionPixelSize( + R.dimen.ongoing_appops_chip_min_animation_width) private var dotSize = context.resources.getDimensionPixelSize( R.dimen.ongoing_appops_dot_diameter) - // If the chip animates away to a persistent dot, then we modify the CHIP_OUT animation - private var isAnimatingToDot = false + // Use during animation so that multiple animators can update the drawing rect + private var animRect = Rect() // TODO: move to dagger private var initialized = false - override fun onChipAnimationStart( - viewCreator: ViewCreator, - @SystemAnimationState state: Int - ) { - if (!initialized) init() - - if (state == ANIMATING_IN) { - animationDirection = if (animationWindowView.isLayoutRtl) RIGHT else LEFT - - // Initialize the animated view - val insets = contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation() - currentAnimatedView = viewCreator(context).also { - animationWindowView.addView( - it.view, - layoutParamsDefault( - if (animationWindowView.isLayoutRtl) insets.first - else insets.second)) - it.view.alpha = 0f - // For some reason, the window view's measured width is always 0 here, so use the - // parent (status bar) - it.view.measure( - View.MeasureSpec.makeMeasureSpec( - (animationWindowView.parent as View).width, AT_MOST), - View.MeasureSpec.makeMeasureSpec(animationWindowView.height, AT_MOST)) - chipWidth = it.chipWidth - } + /** + * Give the chip controller a chance to inflate and configure the chip view before we start + * animating + */ + fun prepareChipAnimation(viewCreator: ViewCreator) { + if (!initialized) { + init() + } + animationDirection = if (animationWindowView.isLayoutRtl) RIGHT else LEFT - // decide which direction we're animating from, and then set some screen coordinates - val contentRect = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation() - when (animationDirection) { - LEFT -> { - chipRight = contentRect.right - chipLeft = contentRect.right - chipWidth - } - else /* RIGHT */ -> { - chipLeft = contentRect.left - chipRight = contentRect.left + chipWidth - } - } + // Initialize the animated view + val insets = contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation() + currentAnimatedView = viewCreator(context).also { + animationWindowView.addView( + it.view, + layoutParamsDefault( + if (animationWindowView.isLayoutRtl) insets.first + else insets.second)) + it.view.alpha = 0f + // For some reason, the window view's measured width is always 0 here, so use the + // parent (status bar) + it.view.measure( + View.MeasureSpec.makeMeasureSpec( + (animationWindowView.parent as View).width, AT_MOST), + View.MeasureSpec.makeMeasureSpec(animationWindowView.height, AT_MOST)) + chipWidth = it.chipWidth + } - currentAnimatedView?.apply { - updateAnimatedViewBoundsForAmount(0.1f, this) + // decide which direction we're animating from, and then set some screen coordinates + val contentRect = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation() + when (animationDirection) { + LEFT -> { + chipRight = contentRect.right + chipLeft = contentRect.right - chipWidth } - } else { - // We are animating away - currentAnimatedView!!.view.apply { - alpha = 1f + else /* RIGHT */ -> { + chipLeft = contentRect.left + chipRight = contentRect.left + chipWidth } } } - override fun onChipAnimationEnd(@SystemAnimationState state: Int) { - if (state == ANIMATING_IN) { - // Finished animating in - currentAnimatedView?.apply { - updateAnimatedViewBoundsForAmount(1f, this) + override fun onSystemEventAnimationBegin(): Animator { + initializeAnimRect() + + val alphaIn = ValueAnimator.ofFloat(0f, 1f).apply { + startDelay = 117 + duration = 83 + interpolator = null + addUpdateListener { currentAnimatedView?.view?.alpha = animatedValue as Float } + } + val moveIn = ValueAnimator.ofInt(chipMinWidth, chipWidth).apply { + startDelay = 117 + duration = 383 + interpolator = STATUS_BAR_X_MOVE_IN + addUpdateListener { + updateAnimatedViewBoundsWidth(animatedValue as Int) } + } + val animSet = AnimatorSet() + animSet.playTogether(alphaIn, moveIn) + return animSet + } + + override fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator { + initializeAnimRect() + val finish = if (hasPersistentDot) { + createMoveOutAnimationForDot() } else { - // Finished animating away - currentAnimatedView!!.view.apply { - visibility = View.INVISIBLE + createMoveOutAnimationDefault() + } + + finish.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator?) { + animationWindowView.removeView(currentAnimatedView!!.view) + } + }) + + return finish + } + + private fun createMoveOutAnimationForDot(): Animator { + val width1 = ValueAnimator.ofInt(chipWidth, chipMinWidth).apply { + duration = 150 + interpolator = STATUS_CHIP_WIDTH_TO_DOT_KEYFRAME_1 + addUpdateListener { + updateAnimatedViewBoundsWidth(it.animatedValue as Int) + } + } + + val width2 = ValueAnimator.ofInt(chipMinWidth, dotSize).apply { + startDelay = 150 + duration = 333 + interpolator = STATUS_CHIP_WIDTH_TO_DOT_KEYFRAME_2 + addUpdateListener { + updateAnimatedViewBoundsWidth(it.animatedValue as Int) } - animationWindowView.removeView(currentAnimatedView!!.view) } + + val keyFrame1Height = dotSize * 2 + val v = currentAnimatedView!!.view + val chipVerticalCenter = v.top + v.measuredHeight / 2 + val height1 = ValueAnimator.ofInt( + currentAnimatedView!!.view.measuredHeight, keyFrame1Height).apply { + startDelay = 133 + duration = 100 + interpolator = STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_1 + addUpdateListener { + updateAnimatedViewBoundsHeight(it.animatedValue as Int, chipVerticalCenter) + } + } + + val height2 = ValueAnimator.ofInt(keyFrame1Height, dotSize).apply { + startDelay = 233 + duration = 250 + interpolator = STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_2 + addUpdateListener { + updateAnimatedViewBoundsHeight(it.animatedValue as Int, chipVerticalCenter) + } + } + + // Move the chip view to overlap exactly with the privacy dot. The chip displays by default + // exactly adjacent to the dot, so we can just move over by the diameter of the dot itself + val moveOut = ValueAnimator.ofInt(0, dotSize).apply { + startDelay = 50 + duration = 183 + interpolator = STATUS_CHIP_MOVE_TO_DOT + addUpdateListener { + // If RTL, we can just invert the move + val amt = if (animationDirection == LEFT) { + animatedValue as Int + } else { + -(animatedValue as Int) + } + updateAnimatedBoundsX(amt) + } + } + + val animSet = AnimatorSet() + animSet.playTogether(width1, width2, height1, height2, moveOut) + return animSet } - override fun onChipAnimationUpdate( - animator: ValueAnimator, - @SystemAnimationState state: Int - ) { - currentAnimatedView?.apply { - val amt = (animator.animatedValue as Float).amt() - view.alpha = (animator.animatedValue as Float) - updateAnimatedViewBoundsForAmount(amt, this) + private fun createMoveOutAnimationDefault(): Animator { + val moveOut = ValueAnimator.ofInt(chipWidth, chipMinWidth).apply { + duration = 383 + addUpdateListener { + currentAnimatedView?.apply { + updateAnimatedViewBoundsWidth(it.animatedValue as Int) + } + } } + return moveOut } private fun init() { @@ -144,7 +227,6 @@ class SystemEventChipAnimationController @Inject constructor( statusBarWindowController.addViewToWindow(animationWindowView, lp) animationWindowView.clipToPadding = false animationWindowView.clipChildren = false - animationWindowView.measureAllChildren = true } private fun layoutParamsDefault(marginEnd: Int): FrameLayout.LayoutParams = @@ -153,29 +235,55 @@ class SystemEventChipAnimationController @Inject constructor( it.marginEnd = marginEnd } - private fun updateAnimatedViewBoundsForAmount(amt: Float, chip: BackgroundAnimatableView) { + private fun initializeAnimRect() = animRect.set( + chipLeft, + currentAnimatedView!!.view.top, + chipRight, + currentAnimatedView!!.view.bottom) + + /** + * To be called during an animation, sets the width and updates the current animated chip view + */ + private fun updateAnimatedViewBoundsWidth(width: Int) { when (animationDirection) { LEFT -> { - chip.setBoundsForAnimation( - (chipRight - (chipWidth * amt)).toInt(), - chip.view.top, - chipRight, - chip.view.bottom) - } - else /* RIGHT */ -> { - chip.setBoundsForAnimation( - chipLeft, - chip.view.top, - (chipLeft + (chipWidth * amt)).toInt(), - chip.view.bottom) + animRect.set((chipRight - width), animRect.top, chipRight, animRect.bottom) + } else /* RIGHT */ -> { + animRect.set(chipLeft, animRect.top, (chipLeft + width), animRect.bottom) } } + + updateCurrentAnimatedView() } - private fun start() = if (animationWindowView.isLayoutRtl) right() else left() - private fun right() = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation().right - private fun left() = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation().left - private fun Float.amt() = 0.01f.coerceAtLeast(this) + /** + * To be called during an animation, updates the animation rect and sends the update to the chip + */ + private fun updateAnimatedViewBoundsHeight(height: Int, verticalCenter: Int) { + animRect.set( + animRect.left, + verticalCenter - (height.toFloat() / 2).roundToInt(), + animRect.right, + verticalCenter + (height.toFloat() / 2).roundToInt()) + + updateCurrentAnimatedView() + } + + /** + * To be called during an animation, updates the animation rect offset and updates the chip + */ + private fun updateAnimatedBoundsX(translation: Int) { + currentAnimatedView?.view?.translationX = translation.toFloat() + } + + /** + * To be called during an animation. Sets the chip rect to animRect + */ + private fun updateCurrentAnimatedView() { + currentAnimatedView?.setBoundsForAnimation( + animRect.left, animRect.top, animRect.right, animRect.bottom + ) + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt index 947f3eb2ee12..36233e4e3eab 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt @@ -19,14 +19,12 @@ package com.android.systemui.statusbar.events import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.animation.AnimatorSet -import android.animation.ValueAnimator import android.annotation.IntDef import android.os.Process import android.provider.DeviceConfig import android.util.Log +import android.view.animation.PathInterpolator import com.android.systemui.Dumpable -import com.android.systemui.animation.Interpolators.STANDARD_ACCELERATE -import com.android.systemui.animation.Interpolators.STANDARD_DECELERATE import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main @@ -38,6 +36,7 @@ import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.time.SystemClock import java.io.FileDescriptor import java.io.PrintWriter +import java.lang.IllegalStateException import javax.inject.Inject @@ -116,7 +115,10 @@ class SystemStatusAnimationScheduler @Inject constructor( scheduledEvent?.updateFromEvent(event) if (event.forceVisible) { hasPersistentDot = true - notifyTransitionToPersistentDot() + // If we missed the chance to show the persistent dot, do it now + if (animationState == IDLE) { + notifyTransitionToPersistentDot() + } } } else { if (DEBUG) { @@ -162,68 +164,90 @@ class SystemStatusAnimationScheduler @Inject constructor( return } - // Schedule the animation to start after a debounce period - cancelExecutionRunnable = executor.executeDelayed({ - cancelExecutionRunnable = null - animationState = ANIMATING_IN - statusBarWindowController.setForceStatusBarVisible(true) - - val entranceAnimator = ValueAnimator.ofFloat(1f, 0f) - entranceAnimator.duration = ENTRANCE_ANIM_LENGTH - entranceAnimator.addListener(systemAnimatorAdapter) - entranceAnimator.addUpdateListener(systemUpdateListener) - entranceAnimator.interpolator = STANDARD_ACCELERATE - - val chipAnimator = ValueAnimator.ofFloat(0f, 1f) - chipAnimator.duration = CHIP_ANIM_LENGTH - chipAnimator.addListener( - ChipAnimatorAdapter(RUNNING_CHIP_ANIM, scheduledEvent!!.viewCreator)) - chipAnimator.addUpdateListener(chipUpdateListener) - chipAnimator.interpolator = STANDARD_DECELERATE - - val aSet2 = AnimatorSet() - aSet2.playSequentially(entranceAnimator, chipAnimator) - aSet2.start() - - executor.executeDelayed({ - animationState = ANIMATING_OUT - - val systemAnimator = ValueAnimator.ofFloat(0f, 1f) - systemAnimator.duration = ENTRANCE_ANIM_LENGTH - systemAnimator.addListener(systemAnimatorAdapter) - systemAnimator.addUpdateListener(systemUpdateListener) - systemAnimator.interpolator = STANDARD_DECELERATE - systemAnimator.addListener(object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation: Animator?) { - statusBarWindowController.setForceStatusBarVisible(false) + chipAnimationController.prepareChipAnimation(scheduledEvent!!.viewCreator) + animationState = ANIMATION_QUEUED + executor.executeDelayed({ + runChipAnimation() + }, DEBOUNCE_DELAY) + } + + /** + * 1. Define a total budget for the chip animation (1500ms) + * 2. Send out callbacks to listeners so that they can generate animations locally + * 3. Update the scheduler state so that clients know where we are + * 4. Maybe: provide scaffolding such as: dot location, margins, etc + * 5. Maybe: define a maximum animation length and enforce it. Probably only doable if we + * collect all of the animators and run them together. + */ + private fun runChipAnimation() { + statusBarWindowController.setForceStatusBarVisible(true) + animationState = ANIMATING_IN + + val animSet = collectStartAnimations() + if (animSet.totalDuration > 500) { + throw IllegalStateException("System animation total length exceeds budget. " + + "Expected: 500, actual: ${animSet.totalDuration}") + } + animSet.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator?) { + animationState = RUNNING_CHIP_ANIM + } + }) + animSet.start() + + executor.executeDelayed({ + val animSet2 = collectFinishAnimations() + animationState = ANIMATING_OUT + animSet2.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator?) { + animationState = if (hasPersistentDot) { + SHOWING_PERSISTENT_DOT + } else { + IDLE } - }) - - val chipAnimator = ValueAnimator.ofFloat(1f, 0f) - chipAnimator.duration = CHIP_ANIM_LENGTH - val endState = if (hasPersistentDot) { - SHOWING_PERSISTENT_DOT - } else { - IDLE + + statusBarWindowController.setForceStatusBarVisible(false) } - chipAnimator.addListener( - ChipAnimatorAdapter(endState, scheduledEvent!!.viewCreator)) - chipAnimator.addUpdateListener(chipUpdateListener) - chipAnimator.interpolator = STANDARD_ACCELERATE + }) + animSet2.start() + scheduledEvent = null + }, DISPLAY_LENGTH) + } - val aSet2 = AnimatorSet() + private fun collectStartAnimations(): AnimatorSet { + val animators = mutableListOf<Animator>() + listeners.forEach { listener -> + listener.onSystemEventAnimationBegin()?.let { anim -> + animators.add(anim) + } + } + animators.add(chipAnimationController.onSystemEventAnimationBegin()) + val animSet = AnimatorSet().also { + it.playTogether(animators) + } - aSet2.play(chipAnimator).before(systemAnimator) - if (hasPersistentDot) { - val dotAnim = notifyTransitionToPersistentDot() - if (dotAnim != null) aSet2.playTogether(systemAnimator, dotAnim) - } + return animSet + } - aSet2.start() + private fun collectFinishAnimations(): AnimatorSet { + val animators = mutableListOf<Animator>() + listeners.forEach { listener -> + listener.onSystemEventAnimationFinish(hasPersistentDot)?.let { anim -> + animators.add(anim) + } + } + animators.add(chipAnimationController.onSystemEventAnimationFinish(hasPersistentDot)) + if (hasPersistentDot) { + val dotAnim = notifyTransitionToPersistentDot() + if (dotAnim != null) { + animators.add(dotAnim) + } + } + val animSet = AnimatorSet().also { + it.playTogether(animators) + } - scheduledEvent = null - }, DISPLAY_LENGTH) - }, DELAY) + return animSet } private fun notifyTransitionToPersistentDot(): Animator? { @@ -257,18 +281,6 @@ class SystemStatusAnimationScheduler @Inject constructor( return null } - private fun notifySystemStart() { - listeners.forEach { it.onSystemChromeAnimationStart() } - } - - private fun notifySystemFinish() { - listeners.forEach { it.onSystemChromeAnimationEnd() } - } - - private fun notifySystemAnimationUpdate(anim: ValueAnimator) { - listeners.forEach { it.onSystemChromeAnimationUpdate(anim) } - } - override fun addCallback(listener: SystemStatusAnimationCallback) { Assert.isMainThread() @@ -287,24 +299,6 @@ class SystemStatusAnimationScheduler @Inject constructor( } } - private val systemUpdateListener = ValueAnimator.AnimatorUpdateListener { - anim -> notifySystemAnimationUpdate(anim) - } - - private val systemAnimatorAdapter = object : AnimatorListenerAdapter() { - override fun onAnimationEnd(p0: Animator?) { - notifySystemFinish() - } - - override fun onAnimationStart(p0: Animator?) { - notifySystemStart() - } - } - - private val chipUpdateListener = ValueAnimator.AnimatorUpdateListener { - anim -> chipAnimationController.onChipAnimationUpdate(anim, animationState) - } - override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) { pw.println("Scheduled event: $scheduledEvent") pw.println("Has persistent privacy dot: $hasPersistentDot") @@ -318,24 +312,6 @@ class SystemStatusAnimationScheduler @Inject constructor( } } } - - inner class ChipAnimatorAdapter( - @SystemAnimationState val endState: Int, - val viewCreator: ViewCreator - ) : AnimatorListenerAdapter() { - override fun onAnimationEnd(p0: Animator?) { - chipAnimationController.onChipAnimationEnd(animationState) - animationState = if (endState == SHOWING_PERSISTENT_DOT && !hasPersistentDot) { - IDLE - } else { - endState - } - } - - override fun onAnimationStart(p0: Animator?) { - chipAnimationController.onChipAnimationStart(viewCreator, animationState) - } - } } /** @@ -344,16 +320,14 @@ class SystemStatusAnimationScheduler @Inject constructor( * create space for the chip animation to display. This means hiding the system elements in the * status bar and keyguard. * - * TODO: the chip animation really only has one client, we can probably remove it from this - * interface - * * The value animators themselves are simple animators from 0.0 to 1.0. Listeners can apply any * interpolation they choose but realistically these are most likely to be simple alpha transitions */ interface SystemStatusAnimationCallback { - @JvmDefault fun onSystemChromeAnimationUpdate(animator: ValueAnimator) {} - @JvmDefault fun onSystemChromeAnimationStart() {} - @JvmDefault fun onSystemChromeAnimationEnd() {} + /** Implement this method to return an [Animator] or [AnimatorSet] that presents the chip */ + fun onSystemEventAnimationBegin(): Animator? { return null } + /** Implement this method to return an [Animator] or [AnimatorSet] that hides the chip */ + fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator? { return null } // Best method name, change my mind @JvmDefault @@ -363,50 +337,61 @@ interface SystemStatusAnimationCallback { @JvmDefault fun onHidePersistentDot(): Animator? { return null } } -interface SystemStatusChipAnimationCallback { - fun onChipAnimationUpdate(animator: ValueAnimator, @SystemAnimationState state: Int) {} - - fun onChipAnimationStart( - viewCreator: ViewCreator, - @SystemAnimationState state: Int - ) {} - - fun onChipAnimationEnd(@SystemAnimationState state: Int) {} -} - /** + * Animation state IntDef */ @Retention(AnnotationRetention.SOURCE) @IntDef( value = [ - IDLE, ANIMATING_IN, RUNNING_CHIP_ANIM, ANIMATING_OUT, SHOWING_PERSISTENT_DOT + IDLE, + ANIMATION_QUEUED, + ANIMATING_IN, + RUNNING_CHIP_ANIM, + ANIMATING_OUT, + SHOWING_PERSISTENT_DOT ] ) annotation class SystemAnimationState /** No animation is in progress */ const val IDLE = 0 +/** An animation is queued, and awaiting the debounce period */ +const val ANIMATION_QUEUED = 1 /** System is animating out, and chip is animating in */ -const val ANIMATING_IN = 1 +const val ANIMATING_IN = 2 /** Chip has animated in and is awaiting exit animation, and optionally playing its own animation */ -const val RUNNING_CHIP_ANIM = 2 +const val RUNNING_CHIP_ANIM = 3 /** Chip is animating away and system is animating back */ -const val ANIMATING_OUT = 3 +const val ANIMATING_OUT = 4 /** Chip has animated away, and the persistent dot is showing */ -const val SHOWING_PERSISTENT_DOT = 4 +const val SHOWING_PERSISTENT_DOT = 5 + +/** Commonly-needed interpolators can go here */ +@JvmField val STATUS_BAR_X_MOVE_OUT = PathInterpolator(0.33f, 0f, 0f, 1f) +@JvmField val STATUS_BAR_X_MOVE_IN = PathInterpolator(0f, 0f, 0f, 1f) +/** + * Status chip animation to dot have multiple stages of motion, the _1 and _2 interpolators should + * be used in succession + */ +val STATUS_CHIP_WIDTH_TO_DOT_KEYFRAME_1 = PathInterpolator(0.44f, 0f, 0.25f, 1f) +val STATUS_CHIP_WIDTH_TO_DOT_KEYFRAME_2 = PathInterpolator(0.3f, 0f, 0.26f, 1f) +val STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_1 = PathInterpolator(0.4f, 0f, 0.17f, 1f) +val STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_2 = PathInterpolator(0.3f, 0f, 0f, 1f) +val STATUS_CHIP_MOVE_TO_DOT = PathInterpolator(0f, 0f, 0.05f, 1f) private const val TAG = "SystemStatusAnimationScheduler" -private const val DELAY = 0L +private const val DEBOUNCE_DELAY = 100L /** - * The total time spent animation should be 1500ms. The entrance animation is how much time - * we give to the system to animate system elements out of the way. Total chip animation length - * will be equivalent to 2*chip_anim_length + display_length + * The total time spent on the chip animation is 1500ms, broken up into 3 sections: + * - 500ms to animate the chip in (including animating system icons away) + * - 500ms holding the chip on screen + * - 500ms to animate the chip away (and system icons back) + * + * So DISPLAY_LENGTH should be the sum of the first 2 phases, while the final 500ms accounts for + * the actual animation */ -private const val ENTRANCE_ANIM_LENGTH = 250L -private const val CHIP_ANIM_LENGTH = 250L -// 1s + entrance time + chip anim_length -private const val DISPLAY_LENGTH = 1500L +private const val DISPLAY_LENGTH = 1000L private const val MIN_UPTIME: Long = 5 * 1000 diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java index fca2aa167e37..577d536262b2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java @@ -163,10 +163,13 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } /** - * @return The background of this view. + * @param width The actual width to apply to the background view. */ - public NotificationBackgroundView getBackgroundNormal() { - return mBackgroundNormal; + public void setBackgroundWidth(int width) { + if (mBackgroundNormal == null) { + return; + } + mBackgroundNormal.setActualWidth(width); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index c237e1deeae3..e479509247d3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -79,7 +79,6 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.ContrastColorUtil; import com.android.internal.widget.CachingIconView; import com.android.internal.widget.CallLayout; -import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.animation.Interpolators; import com.android.systemui.classifier.FalsingCollector; @@ -90,6 +89,7 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.RemoteInputController; +import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.notification.AboveShelfChangedListener; import com.android.systemui.statusbar.notification.ExpandAnimationParameters; @@ -111,10 +111,11 @@ import com.android.systemui.statusbar.notification.stack.ExpandableViewState; import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.notification.stack.SwipeableView; -import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.CentralSurfaces; +import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.InflatedSmartReplyState; +import com.android.systemui.statusbar.policy.SmartReplyConstants; import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent; import com.android.systemui.util.Compile; import com.android.systemui.util.DumpUtilsKt; @@ -169,6 +170,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private RowContentBindStage mRowContentBindStage; private PeopleNotificationIdentifier mPeopleNotificationIdentifier; private Optional<BubblesManager> mBubblesManagerOptional; + private MetricsLogger mMetricsLogger; private int mIconTransformContentShift; private int mMaxHeadsUpHeightBeforeN; private int mMaxHeadsUpHeightBeforeP; @@ -304,8 +306,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView final boolean wasExpanded = mGroupExpansionManager.isGroupExpanded(mEntry); boolean nowExpanded = mGroupExpansionManager.toggleGroupExpansion(mEntry); mOnExpandClickListener.onExpandClicked(mEntry, v, nowExpanded); - MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER, - nowExpanded); + mMetricsLogger.action(MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER, nowExpanded); onExpansionChanged(true /* userAction */, wasExpanded); } else if (mEnableNonGroupedNotificationExpand) { if (v.isAccessibilityFocused()) { @@ -327,8 +328,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } notifyHeightChanged(true); mOnExpandClickListener.onExpandClicked(mEntry, v, nowExpanded); - MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_EXPANDER, - nowExpanded); + mMetricsLogger.action(MetricsEvent.ACTION_NOTIFICATION_EXPANDER, nowExpanded); } } }; @@ -1271,7 +1271,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView addView(mMenuRow.getMenuView(), menuIndex); } for (NotificationContentView l : mLayouts) { - l.initView(); + l.reinflate(); l.reInflateViews(); } mEntry.getSbn().clearPackageContext(); @@ -1464,7 +1464,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView * @param fromAccessibility whether this dismiss is coming from an accessibility action */ public void performDismiss(boolean fromAccessibility) { - Dependency.get(MetricsLogger.class).count(NotificationCounters.NOTIFICATION_DISMISSED, 1); + mMetricsLogger.count(NotificationCounters.NOTIFICATION_DISMISSED, 1); dismiss(fromAccessibility); if (mEntry.isDismissable()) { if (mOnUserInteractionCallback != null) { @@ -1600,7 +1600,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView PeopleNotificationIdentifier peopleNotificationIdentifier, OnUserInteractionCallback onUserInteractionCallback, Optional<BubblesManager> bubblesManagerOptional, - NotificationGutsManager gutsManager) { + NotificationGutsManager gutsManager, + MetricsLogger metricsLogger, + SmartReplyConstants smartReplyConstants, + SmartReplyController smartReplyController) { mEntry = entry; mAppName = appName; if (mMenuRow == null) { @@ -1623,15 +1626,18 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mFalsingManager = falsingManager; mFalsingCollector = falsingCollector; mStatusBarStateController = statusBarStateController; - mPeopleNotificationIdentifier = peopleNotificationIdentifier; for (NotificationContentView l : mLayouts) { - l.setPeopleNotificationIdentifier(mPeopleNotificationIdentifier); - l.setRemoteInputViewSubcomponentFactory(rivSubcomponentFactory); + l.initialize( + mPeopleNotificationIdentifier, + rivSubcomponentFactory, + smartReplyConstants, + smartReplyController); } mOnUserInteractionCallback = onUserInteractionCallback; mBubblesManagerOptional = bubblesManagerOptional; mNotificationGutsManager = gutsManager; + mMetricsLogger = metricsLogger; cacheIsSystemNotification(); } @@ -3127,7 +3133,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView if (mGroupMembershipManager.isGroupSummary(mEntry)) { event = MetricsEvent.ACTION_NOTIFICATION_GROUP_GESTURE_EXPANDER; } - MetricsLogger.action(mContext, event, userExpanded); + mMetricsLogger.action(event, userExpanded); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java index c4beb5bf4d7b..599039d46556 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java @@ -27,6 +27,7 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.android.internal.logging.MetricsLogger; import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; @@ -35,6 +36,7 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.statusbar.NotificationMediaManager; +import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.FeedbackIcon; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; @@ -49,6 +51,7 @@ import com.android.systemui.statusbar.notification.row.dagger.NotificationRowSco import com.android.systemui.statusbar.notification.stack.NotificationListContainer; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.HeadsUpManager; +import com.android.systemui.statusbar.policy.SmartReplyConstants; import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent; import com.android.systemui.util.time.SystemClock; import com.android.systemui.wmshell.BubblesManager; @@ -82,6 +85,7 @@ public class ExpandableNotificationRowController implements NotifViewController private final HeadsUpManager mHeadsUpManager; private final ExpandableNotificationRow.OnExpandClickListener mOnExpandClickListener; private final StatusBarStateController mStatusBarStateController; + private final MetricsLogger mMetricsLogger; private final ExpandableNotificationRow.ExpansionLogger mExpansionLogger = this::logNotificationExpansion; @@ -94,16 +98,21 @@ public class ExpandableNotificationRowController implements NotifViewController private final boolean mAllowLongPress; private final PeopleNotificationIdentifier mPeopleNotificationIdentifier; private final Optional<BubblesManager> mBubblesManagerOptional; + private final SmartReplyConstants mSmartReplyConstants; + private final SmartReplyController mSmartReplyController; private final ExpandableNotificationRowDragController mDragController; @Inject public ExpandableNotificationRowController( ExpandableNotificationRow view, - NotificationListContainer listContainer, - RemoteInputViewSubcomponent.Factory rivSubcomponentFactory, ActivatableNotificationViewController activatableNotificationViewController, + RemoteInputViewSubcomponent.Factory rivSubcomponentFactory, + MetricsLogger metricsLogger, + NotificationListContainer listContainer, NotificationMediaManager mediaManager, + SmartReplyConstants smartReplyConstants, + SmartReplyController smartReplyController, PluginManager pluginManager, SystemClock clock, @AppName String appName, @@ -152,6 +161,9 @@ public class ExpandableNotificationRowController implements NotifViewController mPeopleNotificationIdentifier = peopleNotificationIdentifier; mBubblesManagerOptional = bubblesManagerOptional; mDragController = dragController; + mMetricsLogger = metricsLogger; + mSmartReplyConstants = smartReplyConstants; + mSmartReplyController = smartReplyController; } /** @@ -179,7 +191,10 @@ public class ExpandableNotificationRowController implements NotifViewController mPeopleNotificationIdentifier, mOnUserInteractionCallback, mBubblesManagerOptional, - mNotificationGutsManager + mNotificationGutsManager, + mMetricsLogger, + mSmartReplyConstants, + mSmartReplyController ); mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); if (mAllowLongPress) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index adb4ce68c031..b9c7113206df 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -39,7 +39,6 @@ import android.widget.ImageView; import android.widget.LinearLayout; import com.android.internal.annotations.VisibleForTesting; -import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.RemoteInputController; @@ -94,7 +93,6 @@ public class NotificationContentView extends FrameLayout implements Notification private final Rect mClipBounds = new Rect(); private int mMinContractedHeight; - private int mNotificationContentMarginEnd; private View mContractedChild; private View mExpandedChild; private View mHeadsUpChild; @@ -116,7 +114,7 @@ public class NotificationContentView extends FrameLayout implements Notification private NotificationViewWrapper mContractedWrapper; private NotificationViewWrapper mExpandedWrapper; private NotificationViewWrapper mHeadsUpWrapper; - private HybridGroupManager mHybridGroupManager; + private final HybridGroupManager mHybridGroupManager; private int mClipTopAmount; private int mContentHeight; private int mVisibleType = VISIBLE_TYPE_NONE; @@ -128,7 +126,6 @@ public class NotificationContentView extends FrameLayout implements Notification private int mHeadsUpHeight; private int mNotificationMaxHeight; private NotificationEntry mNotificationEntry; - private GroupMembershipManager mGroupMembershipManager; private RemoteInputController mRemoteInputController; private Runnable mExpandedVisibleListener; private PeopleNotificationIdentifier mPeopleIdentifier; @@ -184,7 +181,6 @@ public class NotificationContentView extends FrameLayout implements Notification private boolean mFocusOnVisibilityChange; private boolean mHeadsUpAnimatingAway; private int mClipBottomAmount; - private boolean mIsLowPriority; private boolean mIsContentExpandable; private boolean mRemoteInputVisible; private int mUnrestrictedContentHeight; @@ -192,16 +188,23 @@ public class NotificationContentView extends FrameLayout implements Notification public NotificationContentView(Context context, AttributeSet attrs) { super(context, attrs); mHybridGroupManager = new HybridGroupManager(getContext()); - mSmartReplyConstants = Dependency.get(SmartReplyConstants.class); - mSmartReplyController = Dependency.get(SmartReplyController.class); - initView(); + reinflate(); } - public void initView() { + public void initialize( + PeopleNotificationIdentifier peopleNotificationIdentifier, + RemoteInputViewSubcomponent.Factory rivSubcomponentFactory, + SmartReplyConstants smartReplyConstants, + SmartReplyController smartReplyController) { + mPeopleIdentifier = peopleNotificationIdentifier; + mRemoteInputSubcomponentFactory = rivSubcomponentFactory; + mSmartReplyConstants = smartReplyConstants; + mSmartReplyController = smartReplyController; + } + + public void reinflate() { mMinContractedHeight = getResources().getDimensionPixelSize( R.dimen.min_notification_layout_height); - mNotificationContentMarginEnd = getResources().getDimensionPixelSize( - com.android.internal.R.dimen.notification_content_margin_end); } public void setHeights(int smallHeight, int headsUpMaxHeight, int maxHeight) { @@ -1606,7 +1609,6 @@ public class NotificationContentView extends FrameLayout implements Notification } public void setGroupMembershipManager(GroupMembershipManager groupMembershipManager) { - mGroupMembershipManager = groupMembershipManager; } public void setRemoteInputController(RemoteInputController r) { @@ -1694,10 +1696,6 @@ public class NotificationContentView extends FrameLayout implements Notification mContainingNotification = containingNotification; } - public void setPeopleNotificationIdentifier(PeopleNotificationIdentifier peopleIdentifier) { - mPeopleIdentifier = peopleIdentifier; - } - public void requestSelectLayout(boolean needsAnimation) { selectLayout(needsAnimation, false); } @@ -1865,7 +1863,6 @@ public class NotificationContentView extends FrameLayout implements Notification } public void setIsLowPriority(boolean isLowPriority) { - mIsLowPriority = isLowPriority; } public boolean isDimmable() { @@ -2090,10 +2087,6 @@ public class NotificationContentView extends FrameLayout implements Notification return false; } - public void setRemoteInputViewSubcomponentFactory(RemoteInputViewSubcomponent.Factory factory) { - mRemoteInputSubcomponentFactory = factory; - } - private static class RemoteInputViewData { @Nullable RemoteInputView mView; @Nullable RemoteInputViewController mController; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 27cc326fda19..ade95a8cbfe7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -782,6 +782,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable y = (int) (mAmbientState.getStackY() + mAmbientState.getStackHeight()); drawDebugInfo(canvas, y, Color.BLUE, /* label= */ "mAmbientState.getStackY() + mAmbientState.getStackHeight() = "+y); + + y = (int) mAmbientState.getStackY() + mContentHeight; + drawDebugInfo(canvas, y, Color.MAGENTA, + /* label= */ "mAmbientState.getStackY() + mContentHeight = " + y); + + y = (int) mAmbientState.getStackY() + mIntrinsicContentHeight; + drawDebugInfo(canvas, y, Color.YELLOW, + /* label= */ "mAmbientState.getStackY() + mIntrinsicContentHeight = " + y); } private void drawDebugInfo(Canvas canvas, int y, int color, String label) { @@ -1293,14 +1301,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mOnStackYChanged.accept(listenerNeedsAnimation); } if (mQsExpansionFraction <= 0 && !shouldSkipHeightUpdate()) { - final float endHeight = updateStackEndHeight( - getHeight(), getEmptyBottomMargin(), mTopPadding); + final float endHeight = updateStackEndHeight(); updateStackHeight(endHeight, fraction); } } - public float updateStackEndHeight(float height, float bottomMargin, float topPadding) { - final float stackEndHeight = Math.max(0f, height - bottomMargin - topPadding); + private float updateStackEndHeight() { + final float stackEndHeight = Math.max(0f, mIntrinsicContentHeight); mAmbientState.setStackEndHeight(stackEndHeight); return stackEndHeight; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java index 65173a230871..cb332bdf59b1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java @@ -174,7 +174,7 @@ public class KeyguardStatusBarView extends RelativeLayout { } private void updateKeyguardStatusBarHeight() { - MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams(); + MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams(); lp.height = getStatusBarHeaderHeightKeyguard(mContext); setLayoutParams(lp); } @@ -510,28 +510,6 @@ public class KeyguardStatusBarView extends RelativeLayout { } } - void onSystemChromeAnimationStart(boolean isAnimatingOut) { - if (isAnimatingOut) { - mSystemIconsContainer.setVisibility(View.VISIBLE); - mSystemIconsContainer.setAlpha(0f); - } - } - - void onSystemChromeAnimationEnd(boolean isAnimatingIn) { - // Make sure the system icons are out of the way - if (isAnimatingIn) { - mSystemIconsContainer.setVisibility(View.INVISIBLE); - mSystemIconsContainer.setAlpha(0f); - } else { - mSystemIconsContainer.setAlpha(1f); - mSystemIconsContainer.setVisibility(View.VISIBLE); - } - } - - void onSystemChromeAnimationUpdate(float animatedValue) { - mSystemIconsContainer.setAlpha(animatedValue); - } - @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java index 1df1aff38593..af4fb8e2cf49 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java @@ -17,8 +17,6 @@ package com.android.systemui.statusbar.phone; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; -import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_IN; -import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_OUT; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -47,6 +45,7 @@ import com.android.systemui.statusbar.notification.AnimatableProperty; import com.android.systemui.statusbar.notification.PropertyAnimator; import com.android.systemui.statusbar.notification.stack.AnimationProperties; import com.android.systemui.statusbar.notification.stack.StackStateAnimator; +import com.android.systemui.statusbar.phone.fragment.StatusBarSystemEventAnimator; import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserInfoTracker; import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherController; import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherFeatureController; @@ -107,6 +106,8 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat @Override public void onDensityOrFontScaleChanged() { mView.loadDimens(); + // The animator is dependent on resources for offsets + mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, getResources()); } @Override @@ -123,21 +124,16 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat private final SystemStatusAnimationCallback mAnimationCallback = new SystemStatusAnimationCallback() { + @NonNull @Override - public void onSystemChromeAnimationStart() { - mView.onSystemChromeAnimationStart( - mAnimationScheduler.getAnimationState() == ANIMATING_OUT); + public Animator onSystemEventAnimationFinish(boolean hasPersistentDot) { + return mSystemEventAnimator.onSystemEventAnimationFinish(hasPersistentDot); } + @NonNull @Override - public void onSystemChromeAnimationEnd() { - mView.onSystemChromeAnimationEnd( - mAnimationScheduler.getAnimationState() == ANIMATING_IN); - } - - @Override - public void onSystemChromeAnimationUpdate(@NonNull ValueAnimator anim) { - mView.onSystemChromeAnimationUpdate((float) anim.getAnimatedValue()); + public Animator onSystemEventAnimationBegin() { + return mSystemEventAnimator.onSystemEventAnimationBegin(); } }; @@ -232,6 +228,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat private int mStatusBarState; private boolean mDozing; private boolean mShowingKeyguardHeadsUp; + private StatusBarSystemEventAnimator mSystemEventAnimator; @Inject public KeyguardStatusBarViewController( @@ -302,6 +299,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat mView.setKeyguardUserAvatarEnabled( !mFeatureController.isStatusBarUserSwitcherFeatureEnabled()); mFeatureController.addCallback(enabled -> mView.setKeyguardUserAvatarEnabled(!enabled)); + mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, r); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index 24f5ff86a794..78edc07c8544 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -445,7 +445,7 @@ public abstract class PanelViewController { mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_UNLOCK); } @Classifier.InteractionType int interactionType = vel == 0 ? GENERIC - : vel > 0 ? QUICK_SETTINGS + : y - mInitialTouchY > 0 ? QUICK_SETTINGS : (mKeyguardStateController.canDismissLockScreen() ? UNLOCK : BOUNCER_UNLOCK); @@ -532,7 +532,7 @@ public abstract class PanelViewController { return true; } - @Classifier.InteractionType int interactionType = vel > 0 + @Classifier.InteractionType int interactionType = y - mInitialTouchY > 0 ? QUICK_SETTINGS : ( mKeyguardStateController.canDismissLockScreen() ? UNLOCK : BOUNCER_UNLOCK); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java index 2c84219dbfd0..33bc40119745 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java @@ -20,12 +20,10 @@ import static android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS; import static android.app.StatusBarManager.DISABLE_ONGOING_CALL_CHIP; import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO; -import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_IN; -import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.ANIMATING_OUT; import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.IDLE; import static com.android.systemui.statusbar.events.SystemStatusAnimationSchedulerKt.SHOWING_PERSISTENT_DOT; -import android.animation.ValueAnimator; +import android.animation.Animator; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; @@ -136,6 +134,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue } }; private OperatorNameViewController mOperatorNameViewController; + private StatusBarSystemEventAnimator mSystemEventAnimator; @SuppressLint("ValidFragment") public CollapsedStatusBarFragment( @@ -210,7 +209,8 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue initEmergencyCryptkeeperText(); initOperatorName(); initNotificationIconArea(); - mAnimationScheduler.addCallback(this); + mSystemEventAnimator = + new StatusBarSystemEventAnimator(mSystemIconArea, getResources()); } @VisibleForTesting @@ -245,6 +245,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mCommandQueue.addCallback(this); mStatusBarStateController.addCallback(this); initOngoingCallChip(); + mAnimationScheduler.addCallback(this); mSecureSettings.registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON), @@ -258,6 +259,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mCommandQueue.removeCallback(this); mStatusBarStateController.removeCallback(this); mOngoingCallController.removeCallback(mOngoingCallListener); + mAnimationScheduler.removeCallback(this); mSecureSettings.unregisterContentObserver(mVolumeSettingObserver); } @@ -265,7 +267,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue public void onDestroyView() { super.onDestroyView(); mStatusBarIconController.removeIconGroup(mDarkIconManager); - mAnimationScheduler.removeCallback(this); if (mNetworkController.hasEmergencyCryptKeeperText()) { mNetworkController.removeCallback(mSignalCallback); } @@ -576,35 +577,16 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue disable(getContext().getDisplayId(), mDisabled1, mDisabled2, false /* animate */); } + @Nullable @Override - public void onSystemChromeAnimationStart() { - if (mAnimationScheduler.getAnimationState() == ANIMATING_OUT - && !isSystemIconAreaDisabled()) { - mSystemIconArea.setVisibility(View.VISIBLE); - mSystemIconArea.setAlpha(0f); - } - } - - @Override - public void onSystemChromeAnimationEnd() { - // Make sure the system icons are out of the way - if (mAnimationScheduler.getAnimationState() == ANIMATING_IN) { - mSystemIconArea.setVisibility(View.INVISIBLE); - mSystemIconArea.setAlpha(0f); - } else { - if (isSystemIconAreaDisabled()) { - // don't unhide - return; - } - - mSystemIconArea.setAlpha(1f); - mSystemIconArea.setVisibility(View.VISIBLE); - } + public Animator onSystemEventAnimationBegin() { + return mSystemEventAnimator.onSystemEventAnimationBegin(); } + @Nullable @Override - public void onSystemChromeAnimationUpdate(@NonNull ValueAnimator animator) { - mSystemIconArea.setAlpha((float) animator.getAnimatedValue()); + public Animator onSystemEventAnimationFinish(boolean hasPersistentDot) { + return mSystemEventAnimator.onSystemEventAnimationFinish(hasPersistentDot); } private boolean isSystemIconAreaDisabled() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt new file mode 100644 index 000000000000..f530ec83aec5 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2022 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 + +import android.animation.Animator +import android.animation.AnimatorSet +import android.animation.ValueAnimator +import android.content.res.Resources +import android.view.View +import com.android.systemui.R +import com.android.systemui.statusbar.events.STATUS_BAR_X_MOVE_IN +import com.android.systemui.statusbar.events.STATUS_BAR_X_MOVE_OUT +import com.android.systemui.statusbar.events.SystemStatusAnimationCallback + +/** + * Tied directly to [SystemStatusAnimationScheduler]. Any StatusBar-like thing (keyguard, collapsed + * status bar fragment), can just feed this an animatable view to get the default system status + * animation. + * + * This animator relies on resources, and should be recreated whenever resources are updated. While + * this class could be used directly as the animation callback, it's probably best to forward calls + * to it so that it can be recreated at any moment without needing to remove/add callback. + */ +class StatusBarSystemEventAnimator( + val animatedView: View, + resources: Resources +) : SystemStatusAnimationCallback { + private val translationXIn: Int = resources.getDimensionPixelSize( + R.dimen.ongoing_appops_chip_animation_in_status_bar_translation_x) + private val translationXOut: Int = resources.getDimensionPixelSize( + R.dimen.ongoing_appops_chip_animation_out_status_bar_translation_x) + + override fun onSystemEventAnimationBegin(): Animator { + val moveOut = ValueAnimator.ofFloat(0f, 1f).setDuration(383) + moveOut.interpolator = STATUS_BAR_X_MOVE_OUT + moveOut.addUpdateListener { animation: ValueAnimator -> + animatedView.translationX = -(translationXIn * animation.animatedValue as Float) + } + val alphaOut = ValueAnimator.ofFloat(1f, 0f).setDuration(133) + alphaOut.interpolator = null + alphaOut.addUpdateListener { animation: ValueAnimator -> + animatedView.alpha = animation.animatedValue as Float + } + + val animSet = AnimatorSet() + animSet.playTogether(moveOut, alphaOut) + return animSet + } + + override fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator { + animatedView.translationX = translationXOut.toFloat() + val moveIn = ValueAnimator.ofFloat(1f, 0f).setDuration(467) + moveIn.startDelay = 33 + moveIn.interpolator = STATUS_BAR_X_MOVE_IN + moveIn.addUpdateListener { animation: ValueAnimator -> + animatedView.translationX = translationXOut * animation.animatedValue as Float + } + val alphaIn = ValueAnimator.ofFloat(0f, 1f).setDuration(167) + alphaIn.startDelay = 67 + alphaIn.interpolator = null + alphaIn.addUpdateListener { animation: ValueAnimator -> + animatedView.alpha = animation.animatedValue as Float + } + + val animatorSet = AnimatorSet() + animatorSet.playTogether(moveIn, alphaIn) + + return animatorSet + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt index bd878750dfe1..f8451017b367 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt @@ -299,10 +299,7 @@ class RemoteInputViewControllerImpl @Inject constructor( view.clearAttachment() entry.remoteInputUri = null entry.remoteInputMimeType = null - val resultSource = entry.editedSuggestionInfo - ?.let { RemoteInput.SOURCE_FREE_FORM_INPUT } - ?: RemoteInput.SOURCE_CHOICE - RemoteInput.setResultsSource(fillInIntent, resultSource) + RemoteInput.setResultsSource(fillInIntent, remoteInputResultsSource) return fillInIntent } @@ -332,10 +329,12 @@ class RemoteInputViewControllerImpl @Inject constructor( entry.remoteInputText = fullText // mirror prepareRemoteInputFromText for text input - val resultSource = entry.editedSuggestionInfo - ?.let { RemoteInput.SOURCE_FREE_FORM_INPUT } - ?: RemoteInput.SOURCE_CHOICE - RemoteInput.setResultsSource(fillInIntent, resultSource) + RemoteInput.setResultsSource(fillInIntent, remoteInputResultsSource) return fillInIntent } + + private val remoteInputResultsSource + get() = entry.editedSuggestionInfo + ?.let { RemoteInput.SOURCE_CHOICE } + ?: RemoteInput.SOURCE_FREE_FORM_INPUT } diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/AnimationUtil.kt b/packages/SystemUI/src/com/android/systemui/util/animation/AnimationUtil.kt new file mode 100644 index 000000000000..c0538c110426 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/animation/AnimationUtil.kt @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 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.util.animation + +import kotlin.math.roundToLong + +/** A generic util class for animations in SysUI. */ +class AnimationUtil { + companion object { + /** + * Returns the number of milliseconds there are in [numFrames] for a 60 fps device. + * + * Note that this method can be used on any device, not just 60 fps devices. Animation + * lengths are typically specified in terms of number of frames for a 60 fps device, and + * the value "5 frames" is often more meaningful than "83ms". This method allows us to + * write animation code in terms of the more meaningful "5" number. + * + * @param numFrames must be >= 0. + */ + fun getMsForFrames(numFrames: Int): Long { + if (numFrames < 0) { + throw IllegalArgumentException("numFrames must be >= 0") + } + return (numFrames * 1000f / 60f).roundToLong() + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt index daf81bdc6e82..dcbe0ab96dac 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt @@ -37,6 +37,7 @@ import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.MockitoAnnotations import javax.inject.Provider +import org.mockito.Mockito.`when` as whenever private val DATA = MediaData( userId = -1, @@ -82,6 +83,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { @Before fun setup() { MockitoAnnotations.initMocks(this) + whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) mediaCarouselController = MediaCarouselController( context, mediaControlPanelFactory, diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt index 90eff1ae9804..cb68d81287df 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt @@ -101,6 +101,7 @@ public class MediaControlPanelTest : SysuiTestCase() { @Mock private lateinit var mediaOutputDialogFactory: MediaOutputDialogFactory @Mock private lateinit var mediaCarouselController: MediaCarouselController @Mock private lateinit var falsingManager: FalsingManager + @Mock private lateinit var mediaFlags: MediaFlags private lateinit var appIcon: ImageView private lateinit var albumView: ImageView private lateinit var titleText: TextView @@ -146,7 +147,7 @@ public class MediaControlPanelTest : SysuiTestCase() { player = MediaControlPanel(context, bgExecutor, activityStarter, broadcastSender, mediaViewController, seekBarViewModel, Lazy { mediaDataManager }, - mediaOutputDialogFactory, mediaCarouselController, falsingManager, clock) + mediaOutputDialogFactory, mediaCarouselController, falsingManager, mediaFlags, clock) whenever(seekBarViewModel.progress).thenReturn(seekBarData) // Set up mock views for the players @@ -214,6 +215,9 @@ public class MediaControlPanelTest : SysuiTestCase() { device = device, active = true, resumeAction = null) + + whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(false) + whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false) } /** @@ -291,6 +295,9 @@ public class MediaControlPanelTest : SysuiTestCase() { @Test fun bindSemanticActionsOldLayout() { + whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) + whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false) + val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play) val semanticActions = MediaButton( playOrPause = MediaAction(icon, Runnable {}, "play"), @@ -325,6 +332,9 @@ public class MediaControlPanelTest : SysuiTestCase() { @Test fun bindSemanticActionsNewLayout() { + whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) + whenever(mediaFlags.useMediaSessionLayout()).thenReturn(true) + val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play) val semanticActions = MediaButton( playOrPause = MediaAction(icon, Runnable {}, "play"), @@ -371,6 +381,9 @@ public class MediaControlPanelTest : SysuiTestCase() { @Test fun bindNotificationActionsNewLayout() { + whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) + whenever(mediaFlags.useMediaSessionLayout()).thenReturn(true) + val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play) val actions = listOf( MediaAction(icon, Runnable {}, "previous"), diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt index be2450d11c08..925ae30e8773 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt @@ -26,7 +26,6 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.SbnBuilder import com.android.systemui.tuner.TunerService import com.android.systemui.util.concurrency.FakeExecutor -import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock @@ -38,7 +37,6 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.anyBoolean -import org.mockito.ArgumentMatchers.anyInt import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito @@ -169,7 +167,7 @@ class MediaDataManagerTest : SysuiTestCase() { whenever(mediaSmartspaceTarget.featureType).thenReturn(SmartspaceTarget.FEATURE_MEDIA) whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf(mediaRecommendationItem)) whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(1234L) - whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(false) + whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(false) } @After @@ -596,7 +594,7 @@ class MediaDataManagerTest : SysuiTestCase() { @Test fun testPlaybackActions_noState_usesNotification() { val desc = "Notification Action" - whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(true) + whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) whenever(controller.playbackState).thenReturn(null) val notifWithAction = SbnBuilder().run { @@ -623,7 +621,7 @@ class MediaDataManagerTest : SysuiTestCase() { @Test fun testPlaybackActions_hasPrevNext() { val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4") - whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(true) + whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) val stateActions = PlaybackState.ACTION_PLAY or PlaybackState.ACTION_SKIP_TO_PREVIOUS or PlaybackState.ACTION_SKIP_TO_NEXT @@ -671,7 +669,7 @@ class MediaDataManagerTest : SysuiTestCase() { @Test fun testPlaybackActions_noPrevNext_usesCustom() { val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4", "custom 5") - whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(true) + whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) val stateActions = PlaybackState.ACTION_PLAY val stateBuilder = PlaybackState.Builder() .setActions(stateActions) @@ -709,7 +707,7 @@ class MediaDataManagerTest : SysuiTestCase() { @Test fun testPlaybackActions_reservedSpace() { val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4") - whenever(mediaFlags.areMediaSessionActionsEnabled(any(), anyInt())).thenReturn(true) + whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true) val stateActions = PlaybackState.ACTION_PLAY val stateBuilder = PlaybackState.Builder() .setActions(stateActions) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt index ccce5778c150..962d78c129f9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt @@ -81,6 +81,9 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { whenever(packageManager.getApplicationIcon(PACKAGE_NAME)).thenReturn(appIconFromPackageName) whenever(applicationInfo.loadLabel(packageManager)).thenReturn(APP_NAME) whenever(packageManager.getApplicationInfo( + any(), any<PackageManager.ApplicationInfoFlags>() + )).thenThrow(PackageManager.NameNotFoundException()) + whenever(packageManager.getApplicationInfo( eq(PACKAGE_NAME), any<PackageManager.ApplicationInfoFlags>() )).thenReturn(applicationInfo) context.setMockPackageManager(packageManager) @@ -189,6 +192,28 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { verify(windowManager, never()).removeView(any()) } + + @Test + fun displayChip_nullAppIconDrawableAndNullPackageName_stillHasIcon() { + controllerCommon.displayChip(getState()) + val chipView = getChipView() + + controllerCommon.setIcon(chipView, appPackageName = null, appIconDrawableOverride = null) + + assertThat(chipView.getAppIconView().drawable).isNotNull() + } + + @Test + fun displayChip_nullAppIconDrawableAndInvalidPackageName_stillHasIcon() { + controllerCommon.displayChip(getState()) + val chipView = getChipView() + + controllerCommon.setIcon( + chipView, appPackageName = "fakePackageName", appIconDrawableOverride = null + ) + + assertThat(chipView.getAppIconView().drawable).isNotNull() + } @Test fun setIcon_nullAppIconDrawable_iconIsFromPackageName() { @@ -212,6 +237,28 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { } @Test + fun displayChip_nullAppNameAndNullPackageName_stillHasContentDescription() { + controllerCommon.displayChip(getState()) + val chipView = getChipView() + + controllerCommon.setIcon(chipView, appPackageName = null, appNameOverride = null) + + assertThat(chipView.getAppIconView().contentDescription.toString()).isNotEmpty() + } + + @Test + fun displayChip_nullAppNameAndInvalidPackageName_stillHasContentDescription() { + controllerCommon.displayChip(getState()) + val chipView = getChipView() + + controllerCommon.setIcon( + chipView, appPackageName = "fakePackageName", appNameOverride = null + ) + + assertThat(chipView.getAppIconView().contentDescription.toString()).isNotEmpty() + } + + @Test fun displayChip_nullAppName_iconContentDescriptionIsFromPackageName() { controllerCommon.displayChip(getState()) val chipView = getChipView() 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 7fc5ece670d4..251ac7d250fe 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 @@ -41,6 +41,7 @@ import android.testing.TestableLooper; import androidx.asynclayoutinflater.view.AsyncLayoutInflater; import androidx.test.filters.SmallTest; +import com.android.internal.logging.MetricsLogger; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.NotificationMessagingUtil; import com.android.systemui.R; @@ -87,6 +88,7 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.InflatedSmartReplyState; import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder; +import com.android.systemui.statusbar.policy.SmartReplyConstants; import com.android.systemui.statusbar.policy.SmartReplyStateInflater; import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent; import com.android.systemui.util.concurrency.FakeExecutor; @@ -252,13 +254,17 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase { .thenAnswer((Answer<ExpandableNotificationRowController>) invocation -> new ExpandableNotificationRowController( viewCaptor.getValue(), - mListContainer, - mock(RemoteInputViewSubcomponent.Factory.class), mock(ActivatableNotificationViewController.class), + mock(RemoteInputViewSubcomponent.Factory.class), + mock(MetricsLogger.class), + mListContainer, mNotificationMediaManager, + mock(SmartReplyConstants.class), + mock(SmartReplyController.class), mock(PluginManager.class), new FakeSystemClock(), - "FOOBAR", "FOOBAR", + "FOOBAR", + "FOOBAR", mKeyguardBypassController, mGroupMembershipManager, mGroupExpansionManager, @@ -275,8 +281,7 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase { mock(FeatureFlags.class), mPeopleNotificationIdentifier, Optional.of(mock(BubblesManager.class)), - mock(ExpandableNotificationRowDragController.class) - )); + mock(ExpandableNotificationRowDragController.class))); when(mNotificationRowComponentBuilder.activatableNotificationView(any())) .thenReturn(mNotificationRowComponentBuilder); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java index 72f8f70058fc..1ecb09bc8514 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java @@ -44,6 +44,7 @@ import android.text.TextUtils; import android.view.LayoutInflater; import android.widget.RemoteViews; +import com.android.internal.logging.MetricsLogger; import com.android.systemui.TestableDependency; import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.classifier.FalsingManagerFake; @@ -54,6 +55,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShadeWindowController; +import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.ConversationNotificationProcessor; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; @@ -73,6 +75,7 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.policy.HeadsUpManagerLogger; import com.android.systemui.statusbar.policy.InflatedSmartReplyState; import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder; +import com.android.systemui.statusbar.policy.SmartReplyConstants; import com.android.systemui.statusbar.policy.SmartReplyStateInflater; import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent; import com.android.systemui.tests.R; @@ -505,7 +508,10 @@ public class NotificationTestHelper { mPeopleNotificationIdentifier, mOnUserInteractionCallback, Optional.of(mock(BubblesManager.class)), - mock(NotificationGutsManager.class)); + mock(NotificationGutsManager.class), + mock(MetricsLogger.class), + mock(SmartReplyConstants.class), + mock(SmartReplyController.class)); row.setAboveShelfChangedListener(aboveShelf -> { }); mBindStage.getStageParams(entry).requireContentViews(extraInflationFlags); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index eafcc354fac4..56541f3ceb6f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -161,17 +161,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - public void testUpdateStackEndHeight_forEndOfStackHeightAnimation() { - final float nsslHeight = 10f; - final float bottomMargin = 1f; - final float topPadding = 1f; - - mStackScroller.updateStackEndHeight(nsslHeight, bottomMargin, topPadding); - final float stackEndHeight = nsslHeight - bottomMargin - topPadding; - assertTrue(mAmbientState.getStackEndHeight() == stackEndHeight); - } - - @Test public void testUpdateStackHeight_withDozeAmount_whenDozeChanging() { final float dozeAmount = 0.5f; mAmbientState.setDozeAmount(dozeAmount); diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt new file mode 100644 index 000000000000..92afb038b321 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2022 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.util.animation + +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import java.lang.IllegalArgumentException + +@SmallTest +class AnimationUtilTest : SysuiTestCase() { + @Test + fun getMsForFrames_5frames_returns83() { + assertThat(AnimationUtil.getMsForFrames(5)).isEqualTo(83L) + } + + @Test + fun getMsForFrames_7frames_returns117() { + assertThat(AnimationUtil.getMsForFrames(7)).isEqualTo(117L) + } + + @Test + fun getMsForFrames_30frames_returns500() { + assertThat(AnimationUtil.getMsForFrames(30)).isEqualTo(500L) + } + + @Test + fun getMsForFrames_60frames_returns1000() { + assertThat(AnimationUtil.getMsForFrames(60)).isEqualTo(1000L) + } + + @Test(expected = IllegalArgumentException::class) + fun getMsForFrames_negativeFrames_throwsException() { + AnimationUtil.getMsForFrames(-1) + } +} diff --git a/services/api/current.txt b/services/api/current.txt index 5a2880223f6c..780fccfc2e4d 100644 --- a/services/api/current.txt +++ b/services/api/current.txt @@ -47,6 +47,9 @@ package com.android.server.am { package com.android.server.pm { public interface PackageManagerLocal { + method public void reconcileSdkData(@Nullable String, @NonNull String, @NonNull java.util.List<java.lang.String>, int, int, int, @NonNull String, int) throws java.io.IOException; + field public static final int FLAG_STORAGE_CE = 2; // 0x2 + field public static final int FLAG_STORAGE_DE = 1; // 0x1 } } diff --git a/services/cloudsearch/java/com/android/server/cloudsearch/CloudSearchPerUserService.java b/services/cloudsearch/java/com/android/server/cloudsearch/CloudSearchPerUserService.java index 116c7391b388..8e0e3959dd0e 100644 --- a/services/cloudsearch/java/com/android/server/cloudsearch/CloudSearchPerUserService.java +++ b/services/cloudsearch/java/com/android/server/cloudsearch/CloudSearchPerUserService.java @@ -107,6 +107,10 @@ public class CloudSearchPerUserService extends @GuardedBy("mLock") public void onSearchLocked(@NonNull SearchRequest searchRequest, @NonNull ICloudSearchManagerCallback callback) { + if (mRemoteComponentName == null) { + return; + } + String filterList = searchRequest.getSearchConstraints().containsKey( SearchRequest.CONSTRAINT_SEARCH_PROVIDER_FILTER) ? searchRequest.getSearchConstraints().getString( diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index 569d4809a541..2dfe94729bb8 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -1302,7 +1302,7 @@ final class UiModeManagerService extends SystemService { pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState); pw.print(" mNightMode="); pw.print(mNightMode); pw.print(" ("); - pw.print(Shell.nightModeToStr(mNightMode)); pw.print(") "); + pw.print(Shell.nightModeToStr(mNightMode, mNightModeCustomType)); pw.print(") "); pw.print(" mOverrideOn/Off="); pw.print(mOverrideNightModeOn); pw.print("/"); pw.print(mOverrideNightModeOff); @@ -1917,7 +1917,8 @@ final class UiModeManagerService extends SystemService { public static final String NIGHT_MODE_STR_YES = "yes"; public static final String NIGHT_MODE_STR_NO = "no"; public static final String NIGHT_MODE_STR_AUTO = "auto"; - public static final String NIGHT_MODE_STR_CUSTOM = "custom"; + public static final String NIGHT_MODE_STR_CUSTOM_SCHEDULE = "custom_schedule"; + public static final String NIGHT_MODE_STR_CUSTOM_BEDTIME = "custom_bedtime"; public static final String NIGHT_MODE_STR_UNKNOWN = "unknown"; private final IUiModeManager mInterface; @@ -1931,7 +1932,7 @@ final class UiModeManagerService extends SystemService { pw.println("UiModeManager service (uimode) commands:"); pw.println(" help"); pw.println(" Print this help text."); - pw.println(" night [yes|no|auto|custom]"); + pw.println(" night [yes|no|auto|custom_schedule|custom_bedtime]"); pw.println(" Set or read night mode."); pw.println(" car [yes|no]"); pw.println(" Set or read car mode."); @@ -2001,14 +2002,19 @@ final class UiModeManagerService extends SystemService { } final int mode = strToNightMode(modeStr); + final int customType = strToNightModeCustomType(modeStr); if (mode >= 0) { mInterface.setNightMode(mode); + if (mode == UiModeManager.MODE_NIGHT_CUSTOM) { + mInterface.setNightModeCustomType(customType); + } printCurrentNightMode(); return 0; } else { err.println("Error: mode must be '" + NIGHT_MODE_STR_YES + "', '" + NIGHT_MODE_STR_NO + "', or '" + NIGHT_MODE_STR_AUTO - + "', or '" + NIGHT_MODE_STR_CUSTOM + "'"); + + "', or '" + NIGHT_MODE_STR_CUSTOM_SCHEDULE + "', or '" + + NIGHT_MODE_STR_CUSTOM_BEDTIME + "'"); return -1; } } @@ -2016,11 +2022,12 @@ final class UiModeManagerService extends SystemService { private void printCurrentNightMode() throws RemoteException { final PrintWriter pw = getOutPrintWriter(); final int currMode = mInterface.getNightMode(); - final String currModeStr = nightModeToStr(currMode); + final int customType = mInterface.getNightModeCustomType(); + final String currModeStr = nightModeToStr(currMode, customType); pw.println("Night mode: " + currModeStr); } - private static String nightModeToStr(int mode) { + private static String nightModeToStr(int mode, int customType) { switch (mode) { case UiModeManager.MODE_NIGHT_YES: return NIGHT_MODE_STR_YES; @@ -2029,7 +2036,12 @@ final class UiModeManagerService extends SystemService { case UiModeManager.MODE_NIGHT_AUTO: return NIGHT_MODE_STR_AUTO; case MODE_NIGHT_CUSTOM: - return NIGHT_MODE_STR_CUSTOM; + if (customType == UiModeManager.MODE_NIGHT_CUSTOM_TYPE_SCHEDULE) { + return NIGHT_MODE_STR_CUSTOM_SCHEDULE; + } + if (customType == UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME) { + return NIGHT_MODE_STR_CUSTOM_BEDTIME; + } default: return NIGHT_MODE_STR_UNKNOWN; } @@ -2043,13 +2055,25 @@ final class UiModeManagerService extends SystemService { return UiModeManager.MODE_NIGHT_NO; case NIGHT_MODE_STR_AUTO: return UiModeManager.MODE_NIGHT_AUTO; - case NIGHT_MODE_STR_CUSTOM: + case NIGHT_MODE_STR_CUSTOM_SCHEDULE: + case NIGHT_MODE_STR_CUSTOM_BEDTIME: return UiModeManager.MODE_NIGHT_CUSTOM; default: return -1; } } + private static int strToNightModeCustomType(String customTypeStr) { + switch (customTypeStr) { + case NIGHT_MODE_STR_CUSTOM_BEDTIME: + return UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME; + case NIGHT_MODE_STR_CUSTOM_SCHEDULE: + return UiModeManager.MODE_NIGHT_CUSTOM_TYPE_SCHEDULE; + default: + return -1; + } + } + private int handleCarMode() throws RemoteException { final PrintWriter err = getErrPrintWriter(); final String modeStr = getNextArg(); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 0735648c1069..9d9ee8c7a03b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -2911,12 +2911,35 @@ public class ActivityManagerService extends IActivityManager.Stub return mAtmInternal.compatibilityInfoForPackage(ai); } + /** + * Enforces that the uid that calls a method is not an + * {@link UserHandle#isIsolated(int) isolated} uid. + * + * @param caller the name of the method being called. + * @throws SecurityException if the calling uid is an isolated uid. + */ /* package */ void enforceNotIsolatedCaller(String caller) { if (UserHandle.isIsolated(Binder.getCallingUid())) { throw new SecurityException("Isolated process not allowed to call " + caller); } } + /** + * Enforces that the uid that calls a method is not an + * {@link UserHandle#isIsolated(int) isolated} uid or an + * {@link Process#isSdkSandboxUid(int) SDK sandbox} uid. + * + * @param caller the name of the method being called. + * @throws SecurityException if the calling uid is an isolated uid or SDK sandbox uid. + */ + void enforceNotIsolatedOrSdkSandboxCaller(String caller) { + enforceNotIsolatedCaller(caller); + + if (Process.isSdkSandboxUid(Binder.getCallingUid())) { + throw new SecurityException("SDK sandbox process not allowed to call " + caller); + } + } + @Override public void setPackageScreenCompatMode(String packageName, int mode) { mActivityTaskManager.setPackageScreenCompatMode(packageName, mode); @@ -12843,7 +12866,7 @@ public class ActivityManagerService extends IActivityManager.Stub public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage, String callerFeatureId, String receiverId, IIntentReceiver receiver, IntentFilter filter, String permission, int userId, int flags) { - enforceNotIsolatedCaller("registerReceiver"); + enforceNotIsolatedOrSdkSandboxCaller("registerReceiver"); ArrayList<Intent> stickyIntents = null; ProcessRecord callerApp = null; final boolean visibleToInstantApps diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index d01be5820d34..309a4ff16753 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -102,6 +102,7 @@ import android.media.IRecordingConfigDispatcher; import android.media.IRingtonePlayer; import android.media.ISpatializerCallback; import android.media.ISpatializerHeadToSoundStagePoseCallback; +import android.media.ISpatializerHeadTrackerAvailableCallback; import android.media.ISpatializerHeadTrackingModeCallback; import android.media.ISpatializerOutputCallback; import android.media.IStrategyPreferredDevicesDispatcher; @@ -8723,6 +8724,11 @@ public class AudioService extends IAudioService.Stub return mSpatializerHelper.isHeadTrackerEnabled(Objects.requireNonNull(device)); } + /** @see Spatializer#isHeadTrackerAvailable() */ + public boolean isHeadTrackerAvailable() { + return mSpatializerHelper.isHeadTrackerAvailable(); + } + /** @see Spatializer#setSpatializerEnabled(boolean) */ public void setSpatializerEnabled(boolean enabled) { enforceModifyDefaultAudioEffectsPermission(); @@ -8767,6 +8773,13 @@ public class AudioService extends IAudioService.Stub mSpatializerHelper.unregisterHeadTrackingModeCallback(cb); } + /** @see Spatializer.SpatializerHeadTrackerAvailableDispatcherStub */ + public void registerSpatializerHeadTrackerAvailableCallback( + @NonNull ISpatializerHeadTrackerAvailableCallback cb, boolean register) { + Objects.requireNonNull(cb); + mSpatializerHelper.registerHeadTrackerAvailableCallback(cb, register); + } + /** @see Spatializer#setOnHeadToSoundstagePoseUpdatedListener */ public void registerHeadToSoundstagePoseCallback( @NonNull ISpatializerHeadToSoundStagePoseCallback cb) { diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java index 5af73c9e46ea..4a853e18b3a4 100644 --- a/services/core/java/com/android/server/audio/SpatializerHelper.java +++ b/services/core/java/com/android/server/audio/SpatializerHelper.java @@ -30,6 +30,7 @@ import android.media.INativeSpatializerCallback; import android.media.ISpatializer; import android.media.ISpatializerCallback; import android.media.ISpatializerHeadToSoundStagePoseCallback; +import android.media.ISpatializerHeadTrackerAvailableCallback; import android.media.ISpatializerHeadTrackingCallback; import android.media.ISpatializerHeadTrackingModeCallback; import android.media.ISpatializerOutputCallback; @@ -126,6 +127,7 @@ public class SpatializerHelper { private boolean mBinauralSupported = false; private int mActualHeadTrackingMode = Spatializer.HEAD_TRACKING_MODE_UNSUPPORTED; private int mDesiredHeadTrackingMode = Spatializer.HEAD_TRACKING_MODE_RELATIVE_WORLD; + private boolean mHeadTrackerAvailable = false; /** * The desired head tracking mode when enabling head tracking, tracks mDesiredHeadTrackingMode, * except when head tracking gets disabled through setting the desired mode to @@ -831,6 +833,7 @@ public class SpatializerHelper { mSpatCallback = null; try { mSpat.registerHeadTrackingCallback(null); + mHeadTrackerAvailable = false; mSpat.release(); } catch (RemoteException e) { Log.e(TAG, "Can't set release spatializer cleanly", e); @@ -890,6 +893,18 @@ public class SpatializerHelper { mHeadTrackingModeCallbacks.unregister(callback); } + final RemoteCallbackList<ISpatializerHeadTrackerAvailableCallback> mHeadTrackerCallbacks = + new RemoteCallbackList<>(); + + synchronized void registerHeadTrackerAvailableCallback( + @NonNull ISpatializerHeadTrackerAvailableCallback cb, boolean register) { + if (register) { + mHeadTrackerCallbacks.register(cb); + } else { + mHeadTrackerCallbacks.unregister(cb); + } + } + synchronized int[] getSupportedHeadTrackingModes() { switch (mState) { case STATE_UNINITIALIZED: @@ -1090,6 +1105,10 @@ public class SpatializerHelper { return false; } + synchronized boolean isHeadTrackerAvailable() { + return mHeadTrackerAvailable; + } + private boolean checkSpatForHeadTracking(String funcName) { switch (mState) { case STATE_UNINITIALIZED: @@ -1115,7 +1134,8 @@ public class SpatializerHelper { mHeadTrackingModeCallbacks.getBroadcastItem(i) .dispatchSpatializerActualHeadTrackingModeChanged(newMode); } catch (RemoteException e) { - Log.e(TAG, "Error in dispatchSpatializerActualHeadTrackingModeChanged", e); + Log.e(TAG, "Error in dispatchSpatializerActualHeadTrackingModeChanged(" + + newMode + ")", e); } } mHeadTrackingModeCallbacks.finishBroadcast(); @@ -1128,12 +1148,27 @@ public class SpatializerHelper { mHeadTrackingModeCallbacks.getBroadcastItem(i) .dispatchSpatializerDesiredHeadTrackingModeChanged(newMode); } catch (RemoteException e) { - Log.e(TAG, "Error in dispatchSpatializerDesiredHeadTrackingModeChanged", e); + Log.e(TAG, "Error in dispatchSpatializerDesiredHeadTrackingModeChanged(" + + newMode + ")", e); } } mHeadTrackingModeCallbacks.finishBroadcast(); } + private void dispatchHeadTrackerAvailable(boolean available) { + final int nbCallbacks = mHeadTrackerCallbacks.beginBroadcast(); + for (int i = 0; i < nbCallbacks; i++) { + try { + mHeadTrackerCallbacks.getBroadcastItem(i) + .dispatchSpatializerHeadTrackerAvailable(available); + } catch (RemoteException e) { + Log.e(TAG, "Error in dispatchSpatializerHeadTrackerAvailable(" + + available + ")", e); + } + } + mHeadTrackerCallbacks.finishBroadcast(); + } + //------------------------------------------------------ // head pose final RemoteCallbackList<ISpatializerHeadToSoundStagePoseCallback> mHeadPoseCallbacks = @@ -1348,6 +1383,10 @@ public class SpatializerHelper { try { Log.i(TAG, "setHeadSensor:" + headHandle); mSpat.setHeadSensor(headHandle); + if (mHeadTrackerAvailable != (headHandle != -1)) { + mHeadTrackerAvailable = (headHandle != -1); + dispatchHeadTrackerAvailable(mHeadTrackerAvailable); + } } catch (Exception e) { Log.e(TAG, "Error calling setHeadSensor:" + headHandle, e); } diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 76b9830cbde9..5902f487d353 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -27,6 +27,7 @@ import android.os.CreateAppDataArgs; import android.os.CreateAppDataResult; import android.os.IBinder; import android.os.IInstalld; +import android.os.ReconcileSdkDataArgs; import android.os.RemoteException; import android.os.ServiceManager; import android.os.storage.CrateMetadata; @@ -215,6 +216,21 @@ public class Installer extends SystemService { return result; } + static ReconcileSdkDataArgs buildReconcileSdkDataArgs(String uuid, String packageName, + List<String> subDirNames, int userId, int appId, + String seInfo, int flags) { + final ReconcileSdkDataArgs args = new ReconcileSdkDataArgs(); + args.uuid = uuid; + args.packageName = packageName; + args.subDirNames = subDirNames; + args.userId = userId; + args.appId = appId; + args.previousAppId = 0; + args.seInfo = seInfo; + args.flags = flags; + return args; + } + public @NonNull CreateAppDataResult createAppData(@NonNull CreateAppDataArgs args) throws InstallerException { if (!checkBeforeRemote()) { @@ -247,6 +263,18 @@ public class Installer extends SystemService { } } + void reconcileSdkData(@NonNull ReconcileSdkDataArgs args) + throws InstallerException { + if (!checkBeforeRemote()) { + return; + } + try { + mInstalld.reconcileSdkData(args); + } catch (Exception e) { + throw InstallerException.from(e); + } + } + /** * Class that collects multiple {@code installd} operations together in an * attempt to more efficiently execute them in bulk. diff --git a/services/core/java/com/android/server/pm/PackageManagerLocal.java b/services/core/java/com/android/server/pm/PackageManagerLocal.java index 7b76567fcc6e..39cc37ea2e7c 100644 --- a/services/core/java/com/android/server/pm/PackageManagerLocal.java +++ b/services/core/java/com/android/server/pm/PackageManagerLocal.java @@ -16,8 +16,16 @@ package com.android.server.pm; +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; +import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.List; + /** * In-process API for server side PackageManager related infrastructure. * @@ -28,4 +36,48 @@ import android.annotation.SystemApi; */ @SystemApi(client = SystemApi.Client.SYSTEM_SERVER) public interface PackageManagerLocal { + + /** + * Indicates if operation should include device encrypted storage. + */ + int FLAG_STORAGE_DE = Installer.FLAG_STORAGE_DE; + /** + * Indicates if operation should include credential encrypted storage. + */ + int FLAG_STORAGE_CE = Installer.FLAG_STORAGE_CE; + + /** + * Constants for use with {@link #reconcileSdkData} to specify which storage areas should be + * included for operation. + * + * @hide + */ + @IntDef(prefix = "FLAG_STORAGE_", value = { + FLAG_STORAGE_DE, + FLAG_STORAGE_CE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface StorageFlags {} + + /** + * Reconcile sdk data sub-directories for the given {@code packagName}. + * + * Sub directories are created if they do not exist already. If there is an existing per- + * sdk directory that is missing from {@code subDirNames}, then it is removed. + * + * Sdk package path is created if it doesn't exist before creating per-sdk directories. + * + * @param volumeUuid the volume in which the sdk data should be prepared. + * @param packageName package name of the app for which sdk data directory will be prepared. + * @param subDirNames names of sub directories that should be reconciled against. + * @param userId id of the user to whom the package belongs to. + * @param appId id of the package. + * @param previousAppId previous id of the package if package is being updated. + * @param flags flags from StorageManager to indicate which storage areas should be included. + * @param seInfo seInfo tag to be used for selinux policy. + * @throws IOException If any error occurs during the operation. + */ + void reconcileSdkData(@Nullable String volumeUuid, @NonNull String packageName, + @NonNull List<String> subDirNames, int userId, int appId, int previousAppId, + @NonNull String seInfo, @StorageFlags int flags) throws IOException; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 67056ead3423..eaecb17103a5 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -132,6 +132,7 @@ import android.os.Parcel; import android.os.ParcelableException; import android.os.PersistableBundle; import android.os.Process; +import android.os.ReconcileSdkDataArgs; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; @@ -6032,6 +6033,22 @@ public class PackageManagerService implements PackageSender, TestUtilityService } private class PackageManagerLocalImpl implements PackageManagerLocal { + @Override + public void reconcileSdkData(@Nullable String volumeUuid, @NonNull String packageName, + @NonNull List<String> subDirNames, int userId, int appId, int previousAppId, + @NonNull String seInfo, int flags) throws IOException { + synchronized (mInstallLock) { + ReconcileSdkDataArgs args = mInstaller.buildReconcileSdkDataArgs(volumeUuid, + packageName, subDirNames, userId, appId, seInfo, + flags); + args.previousAppId = previousAppId; + try { + mInstaller.reconcileSdkData(args); + } catch (InstallerException e) { + throw new IOException(e.getMessage()); + } + } + } } private class PackageManagerInternalImpl extends PackageManagerInternalBase { diff --git a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java index 53a9244837ed..6adf733ddae9 100644 --- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java +++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java @@ -42,8 +42,8 @@ import android.media.tv.interactive.ITvInteractiveAppService; import android.media.tv.interactive.ITvInteractiveAppServiceCallback; import android.media.tv.interactive.ITvInteractiveAppSession; import android.media.tv.interactive.ITvInteractiveAppSessionCallback; -import android.media.tv.interactive.TvInteractiveAppInfo; import android.media.tv.interactive.TvInteractiveAppService; +import android.media.tv.interactive.TvInteractiveAppServiceInfo; import android.net.Uri; import android.os.Binder; import android.os.Bundle; @@ -130,7 +130,7 @@ public class TvInteractiveAppManagerService extends SystemService { new Intent(TvInteractiveAppService.SERVICE_INTERFACE), PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, userId); - List<TvInteractiveAppInfo> iAppList = new ArrayList<>(); + List<TvInteractiveAppServiceInfo> iAppList = new ArrayList<>(); for (ResolveInfo ri : services) { ServiceInfo si = ri.serviceInfo; @@ -143,8 +143,8 @@ public class TvInteractiveAppManagerService extends SystemService { ComponentName component = new ComponentName(si.packageName, si.name); try { - TvInteractiveAppInfo info = - new TvInteractiveAppInfo(mContext, component); + TvInteractiveAppServiceInfo info = + new TvInteractiveAppServiceInfo(mContext, component); iAppList.add(info); } catch (Exception e) { Slogf.e(TAG, "failed to load TV Interactive App service " + si.name, e); @@ -154,10 +154,10 @@ public class TvInteractiveAppManagerService extends SystemService { } // sort the iApp list by iApp service id - Collections.sort(iAppList, Comparator.comparing(TvInteractiveAppInfo::getId)); + Collections.sort(iAppList, Comparator.comparing(TvInteractiveAppServiceInfo::getId)); Map<String, TvInteractiveAppState> iAppMap = new HashMap<>(); ArrayMap<String, Integer> tiasAppCount = new ArrayMap<>(iAppMap.size()); - for (TvInteractiveAppInfo info : iAppList) { + for (TvInteractiveAppServiceInfo info : iAppList) { String iAppServiceId = info.getId(); if (DEBUG) { Slogf.d(TAG, "add " + iAppServiceId); @@ -195,7 +195,7 @@ public class TvInteractiveAppManagerService extends SystemService { for (String iAppServiceId : userState.mIAppMap.keySet()) { if (!iAppMap.containsKey(iAppServiceId)) { - TvInteractiveAppInfo info = userState.mIAppMap.get(iAppServiceId).mInfo; + TvInteractiveAppServiceInfo info = userState.mIAppMap.get(iAppServiceId).mInfo; ServiceState serviceState = userState.mServiceStateMap.get(info.getComponent()); if (serviceState != null) { abortPendingCreateSessionRequestsLocked(serviceState, iAppServiceId, userId); @@ -283,7 +283,7 @@ public class TvInteractiveAppManagerService extends SystemService { userState.mCallbacks.finishBroadcast(); } - private int getInteractiveAppUid(TvInteractiveAppInfo info) { + private int getInteractiveAppUid(TvInteractiveAppServiceInfo info) { try { return getContext().getPackageManager().getApplicationInfo( info.getServiceInfo().packageName, 0).uid; @@ -642,7 +642,7 @@ public class TvInteractiveAppManagerService extends SystemService { private final class BinderService extends ITvInteractiveAppManager.Stub { @Override - public List<TvInteractiveAppInfo> getTvInteractiveAppServiceList(int userId) { + public List<TvInteractiveAppServiceInfo> getTvInteractiveAppServiceList(int userId) { final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), Binder.getCallingUid(), userId, "getTvInteractiveAppServiceList"); final long identity = Binder.clearCallingIdentity(); @@ -653,7 +653,7 @@ public class TvInteractiveAppManagerService extends SystemService { mGetServiceListCalled = true; } UserState userState = getOrCreateUserStateLocked(resolvedUserId); - List<TvInteractiveAppInfo> iAppList = new ArrayList<>(); + List<TvInteractiveAppServiceInfo> iAppList = new ArrayList<>(); for (TvInteractiveAppState state : userState.mIAppMap.values()) { iAppList.add(state.mInfo); } @@ -1738,7 +1738,7 @@ public class TvInteractiveAppManagerService extends SystemService { private static final class TvInteractiveAppState { private String mIAppServiceId; private ComponentName mComponentName; - private TvInteractiveAppInfo mInfo; + private TvInteractiveAppServiceInfo mInfo; private int mUid; private int mIAppNumber; } diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index 543e44cce8b6..ffc438834658 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -746,8 +746,9 @@ class ActivityClientController extends IActivityClientController.Stub { // if it is not already expanding to fullscreen. Otherwise, the arguments will // be used the next time the activity enters PiP. final Task rootTask = r.getRootTask(); - rootTask.setPictureInPictureAspectRatio(r.pictureInPictureArgs.getAspectRatio(), - r.pictureInPictureArgs.getExpandedAspectRatio()); + rootTask.setPictureInPictureAspectRatio( + r.pictureInPictureArgs.getAspectRatioFloat(), + r.pictureInPictureArgs.getExpandedAspectRatioFloat()); rootTask.setPictureInPictureActions(r.pictureInPictureArgs.getActions()); } } @@ -828,7 +829,7 @@ class ActivityClientController extends IActivityClientController.Stub { if (params.hasSetAspectRatio() && !mService.mWindowManager.isValidPictureInPictureAspectRatio( - r.mDisplayContent, params.getAspectRatio())) { + r.mDisplayContent, params.getAspectRatioFloat())) { throw new IllegalArgumentException(String.format(caller + ": Aspect ratio is too extreme (must be between %f and %f).", minAspectRatio, maxAspectRatio)); @@ -836,7 +837,7 @@ class ActivityClientController extends IActivityClientController.Stub { if (mService.mSupportsExpandedPictureInPicture && params.hasSetExpandedAspectRatio() && !mService.mWindowManager.isValidExpandedPictureInPictureAspectRatio( - r.mDisplayContent, params.getExpandedAspectRatio())) { + r.mDisplayContent, params.getExpandedAspectRatioFloat())) { throw new IllegalArgumentException(String.format(caller + ": Expanded aspect ratio is not extreme enough (must not be between" + " %f and %f).", diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index b5312c4de437..988a7c6cde9a 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -3523,8 +3523,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } // Only update the saved args from the args that are set r.setPictureInPictureParams(params); - final float aspectRatio = r.pictureInPictureArgs.getAspectRatio(); - final float expandedAspectRatio = r.pictureInPictureArgs.getExpandedAspectRatio(); + final float aspectRatio = r.pictureInPictureArgs.getAspectRatioFloat(); + final float expandedAspectRatio = + r.pictureInPictureArgs.getExpandedAspectRatioFloat(); final List<RemoteAction> actions = r.pictureInPictureArgs.getActions(); mRootWindowContainer.moveActivityToPinnedRootTask(r, null /* launchIntoPipHostActivity */, "enterPictureInPictureMode"); diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 597d29f5cd03..d187bd6f3dfd 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -63,8 +63,6 @@ import static com.android.server.wm.TaskFragmentProto.DISPLAY_ID; import static com.android.server.wm.TaskFragmentProto.MIN_HEIGHT; import static com.android.server.wm.TaskFragmentProto.MIN_WIDTH; import static com.android.server.wm.TaskFragmentProto.WINDOW_CONTAINER; -import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; -import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowContainerChildProto.TASK_FRAGMENT; import android.annotation.IntDef; @@ -2370,8 +2368,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { if (!hasChild()) { return false; } - return isAnimating(TRANSITION | CHILDREN, WindowState.EXIT_ANIMATING_TYPES) - || inTransition(); + return isExitAnimationRunningSelfOrChild() || inTransition(); } @Override diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index dab02dec5f7d..e7b4e834eb5a 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -1196,6 +1196,23 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< return false; } + boolean isExitAnimationRunningSelfOrChild() { + if (!mTransitionController.isShellTransitionsEnabled()) { + return isAnimating(TRANSITION | CHILDREN, WindowState.EXIT_ANIMATING_TYPES); + } + if (mTransitionController.isCollecting(this)) { + return true; + } + + for (int i = mChildren.size() - 1; i >= 0; --i) { + WindowContainer child = mChildren.get(i); + if (child.isExitAnimationRunningSelfOrChild()) { + return true; + } + } + return false; + } + void sendAppVisibilityToClients() { for (int i = mChildren.size() - 1; i >= 0; --i) { final WindowContainer wc = mChildren.get(i); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index d5f7a22a3d2b..c50888b5a172 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -119,7 +119,6 @@ import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING; import static com.android.server.wm.RootWindowContainer.MATCH_ATTACHED_TASK_OR_RECENT_TASKS; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; -import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; @@ -2503,8 +2502,6 @@ public class WindowManagerService extends IWindowManager.Stub ProtoLog.v(WM_DEBUG_FOCUS, "Relayout of %s: focusMayChange=%b", win, focusMayChange); - result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0; - if (DEBUG_LAYOUT) { Slog.v(TAG_WM, "Relayout complete " + win + ": outFrames=" + outFrames); } @@ -2563,8 +2560,7 @@ public class WindowManagerService extends IWindowManager.Stub if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) { focusMayChange = true; win.mAnimatingExit = true; - } else if (win.mDisplayContent.okToAnimate() && win.isAnimating(TRANSITION | PARENTS, - WindowState.EXIT_ANIMATING_TYPES)) { + } else if (win.mDisplayContent.okToAnimate() && win.isExitAnimationRunningSelfOrParent()) { // Currently in a hide animation... turn this into // an exit. win.mAnimatingExit = true; diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index f66739293512..60e196c58465 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -134,6 +134,7 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITIO import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_STARTING_REVEAL; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; +import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowContainerChildProto.WINDOW; @@ -2610,8 +2611,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mWmService.mAccessibilityController.onWindowTransition(this, transit); } } - final boolean isAnimating = mAnimatingExit - || isAnimating(TRANSITION | PARENTS, EXIT_ANIMATING_TYPES); + final boolean isAnimating = mAnimatingExit || isExitAnimationRunningSelfOrParent(); final boolean lastWindowIsStartingWindow = startingWindow && mActivityRecord != null && mActivityRecord.isLastWindow(this); // We delay the removal of a window if it has a showing surface that can be used to run @@ -4977,6 +4977,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return false; } + boolean isExitAnimationRunningSelfOrParent() { + return inAppOrRecentsTransition() + || isAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION); + } + + boolean isExitAnimationRunningSelfOrChild() { + return isAnimating(CHILDREN, ANIMATION_TYPE_WINDOW_ANIMATION); + } + private boolean shouldFinishAnimatingExit() { // Exit animation might be applied soon. if (inTransition()) { @@ -4988,7 +4997,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return true; } // Exit animation is running. - if (isAnimating(TRANSITION | PARENTS, EXIT_ANIMATING_TYPES)) { + if (isExitAnimationRunningSelfOrParent()) { ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "shouldWaitAnimatingExit: isAnimating: %s", this); return false; @@ -5081,7 +5090,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @Override boolean handleCompleteDeferredRemoval() { - if (mRemoveOnExit && !isSelfAnimating(0 /* flags */, EXIT_ANIMATING_TYPES)) { + if (mRemoveOnExit && !isSelfAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION)) { mRemoveOnExit = false; removeImmediately(); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java index 200b120843cc..ba00beea47cc 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java @@ -189,4 +189,9 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { public ParcelableResource getString(String stringId) { return null; } + + @Override + public boolean shouldAllowBypassingDevicePolicyManagementRoleQualification() { + return false; + } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 3d40f48f244d..850fdee0c733 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -18384,14 +18384,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } else { preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT); } - List<Integer> allowedUids = Arrays.stream( - preferentialNetworkServiceConfig.getIncludedUids()).boxed().collect( - Collectors.toList()); - List<Integer> excludedUids = Arrays.stream( - preferentialNetworkServiceConfig.getExcludedUids()).boxed().collect( - Collectors.toList()); - preferenceBuilder.setIncludedUids(allowedUids); - preferenceBuilder.setExcludedUids(excludedUids); + preferenceBuilder.setIncludedUids(preferentialNetworkServiceConfig.getIncludedUids()); + preferenceBuilder.setExcludedUids(preferentialNetworkServiceConfig.getExcludedUids()); preferenceBuilder.setPreferenceEnterpriseId( preferentialNetworkServiceConfig.getNetworkId()); @@ -18790,4 +18784,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mInjector.binderWithCleanCallingIdentity(() -> Settings.Secure.putInt( mContext.getContentResolver(), MANAGED_PROVISIONING_DPC_DOWNLOADED, setTo)); } + + @Override + public boolean shouldAllowBypassingDevicePolicyManagementRoleQualification() { + Preconditions.checkCallAuthorization(hasCallingOrSelfPermission( + android.Manifest.permission.MANAGE_ROLE_HOLDERS)); + return mInjector.binderWithCleanCallingIdentity(() -> { + if (mUserManager.getUserCount() > 1) { + return false; + } + AccountManager am = AccountManager.get(mContext); + Account[] accounts = am.getAccounts(); + return accounts.length == 0; + }); + } } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index 1ebcbe10fae6..8438afcfe5e4 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -4260,14 +4260,11 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpm.setPreferentialNetworkServiceConfigs(List.of(preferentialNetworkServiceConfigEnabled)); assertThat(dpm.getPreferentialNetworkServiceConfigs().get(0) .isEnabled()).isTrue(); - List<Integer> includedList = new ArrayList<>(); - includedList.add(1); - includedList.add(2); ProfileNetworkPreference preferenceDetails = new ProfileNetworkPreference.Builder() .setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK) .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1) - .setIncludedUids(includedList) + .setIncludedUids(new int[]{1, 2}) .build(); List<ProfileNetworkPreference> preferences = new ArrayList<>(); preferences.add(preferenceDetails); @@ -4295,14 +4292,11 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpm.setPreferentialNetworkServiceConfigs(List.of(preferentialNetworkServiceConfigEnabled)); assertThat(dpm.getPreferentialNetworkServiceConfigs().get(0) .isEnabled()).isTrue(); - List<Integer> excludedUids = new ArrayList<>(); - excludedUids.add(1); - excludedUids.add(2); ProfileNetworkPreference preferenceDetails = new ProfileNetworkPreference.Builder() .setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK) .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1) - .setExcludedUids(excludedUids) + .setExcludedUids(new int[]{1, 2}) .build(); List<ProfileNetworkPreference> preferences = new ArrayList<>(); preferences.clear(); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index 25d7334a529c..b4d305bbe4d0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -932,7 +932,7 @@ public class WindowOrganizerTests extends WindowTestsBase { mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents(); assertNotNull(o.mChangedInfo); assertNotNull(o.mChangedInfo.pictureInPictureParams); - final Rational ratio = o.mChangedInfo.pictureInPictureParams.getAspectRatioRational(); + final Rational ratio = o.mChangedInfo.pictureInPictureParams.getAspectRatio(); assertEquals(3, ratio.getNumerator()); assertEquals(4, ratio.getDenominator()); } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 837cf8b28ff8..cff90bb9b848 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -504,7 +504,12 @@ public class CarrierConfigManager { /** Control whether users can choose a network operator. */ public static final String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool"; - /** Used in Cellular Network Settings for preferred network type. */ + /** + * Used in the Preferred Network Types menu to determine if the 2G option is displayed. + * Value defaults to false as of Android T to discourage the use of insecure 2G protocols. + * + * @see #KEY_HIDE_ENABLE_2G + */ public static final String KEY_PREFER_2G_BOOL = "prefer_2g_bool"; /** @@ -8594,7 +8599,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL, false); sDefaults.putBoolean(KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL, false); sDefaults.putBoolean(KEY_OPERATOR_SELECTION_EXPAND_BOOL, true); - sDefaults.putBoolean(KEY_PREFER_2G_BOOL, true); + sDefaults.putBoolean(KEY_PREFER_2G_BOOL, false); sDefaults.putBoolean(KEY_4G_ONLY_BOOL, false); sDefaults.putBoolean(KEY_SHOW_APN_SETTING_CDMA_BOOL, false); sDefaults.putBoolean(KEY_SHOW_CDMA_CHOICES_BOOL, false); diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java index d2a4c3e7197c..3a3b3632dc9b 100644 --- a/telephony/java/android/telephony/DataFailCause.java +++ b/telephony/java/android/telephony/DataFailCause.java @@ -1090,13 +1090,6 @@ public final class DataFailCause { */ public static final int NO_RETRY_FAILURE = 0x1000B; - /** - * Traffic descriptors in DataCallResponse is empty. - * - * @hide - */ - public static final int NO_TRAFFIC_DESCRIPTORS = 0x1000C; - private static final Map<Integer, String> sFailCauseMap; static { sFailCauseMap = new HashMap<>(); @@ -1531,7 +1524,6 @@ public final class DataFailCause { sFailCauseMap.put(SERVICE_TEMPORARILY_UNAVAILABLE, "SERVICE_TEMPORARILY_UNAVAILABLE"); sFailCauseMap.put(REQUEST_NOT_SUPPORTED, "REQUEST_NOT_SUPPORTED"); sFailCauseMap.put(NO_RETRY_FAILURE, "NO_RETRY_FAILURE"); - sFailCauseMap.put(NO_TRAFFIC_DESCRIPTORS, "NO_TRAFFIC_DESCRIPTORS"); } private DataFailCause() { diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java index 532679cb6c43..8143da5ad431 100644 --- a/telephony/java/android/telephony/data/ApnSetting.java +++ b/telephony/java/android/telephony/data/ApnSetting.java @@ -549,7 +549,6 @@ public class ApnSetting implements Parcelable { * Returns the profile id to which the APN saved in modem. * * @return the profile id of the APN - * @hide */ public int getProfileId() { return mProfileId; @@ -558,8 +557,7 @@ public class ApnSetting implements Parcelable { /** * Returns if the APN setting is persistent on the modem. * - * @return is the APN setting to be set in modem - * @hide + * @return {@code true} if the APN setting is persistent on the modem. */ public boolean isPersistent() { return mPersistent; diff --git a/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java b/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java index fe4453081362..5ffee5638cfa 100644 --- a/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java +++ b/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java @@ -32,7 +32,12 @@ import java.util.List; import java.util.Objects; /** - * Provides Qos attributes of an EPS bearer. + * Provides QOS attributes of an EPS bearer. + * + * <p> The dedicated EPS bearer along with QOS is allocated by the LTE network and notified to the + * device. The Telephony framework creates the {@link EpsBearerQosSessionAttributes} object which + * represents the QOS of the dedicated bearer and notifies the same to applications via + * {@link QosCallback}. * * {@hide} */ |