Merge "Dump battery history without locking"
diff --git a/Android.bp b/Android.bp
index ea7ced9..effd7ce 100644
--- a/Android.bp
+++ b/Android.bp
@@ -235,6 +235,7 @@
"android.hardware.usb-V1.0-java-constants",
"android.hardware.usb-V1.1-java-constants",
"android.hardware.usb-V1.2-java-constants",
+ "android.hardware.usb.gadget-V1-java",
"android.hardware.usb.gadget-V1.0-java",
"android.hardware.usb.gadget-V1.1-java",
"android.hardware.usb.gadget-V1.2-java",
diff --git a/apex/jobscheduler/framework/java/android/app/job/UserVisibleJobSummary.java b/apex/jobscheduler/framework/java/android/app/job/UserVisibleJobSummary.java
index 311a9b2..ba79c30 100644
--- a/apex/jobscheduler/framework/java/android/app/job/UserVisibleJobSummary.java
+++ b/apex/jobscheduler/framework/java/android/app/job/UserVisibleJobSummary.java
@@ -30,6 +30,8 @@
*/
public class UserVisibleJobSummary implements Parcelable {
private final int mCallingUid;
+ @NonNull
+ private final String mCallingPackageName;
private final int mSourceUserId;
@NonNull
private final String mSourcePackageName;
@@ -37,9 +39,11 @@
private final String mNamespace;
private final int mJobId;
- public UserVisibleJobSummary(int callingUid, int sourceUserId,
- @NonNull String sourcePackageName, String namespace, int jobId) {
+ public UserVisibleJobSummary(int callingUid, @NonNull String callingPackageName,
+ int sourceUserId, @NonNull String sourcePackageName,
+ @Nullable String namespace, int jobId) {
mCallingUid = callingUid;
+ mCallingPackageName = callingPackageName;
mSourceUserId = sourceUserId;
mSourcePackageName = sourcePackageName;
mNamespace = namespace;
@@ -48,12 +52,18 @@
protected UserVisibleJobSummary(Parcel in) {
mCallingUid = in.readInt();
+ mCallingPackageName = in.readString();
mSourceUserId = in.readInt();
mSourcePackageName = in.readString();
mNamespace = in.readString();
mJobId = in.readInt();
}
+ @NonNull
+ public String getCallingPackageName() {
+ return mCallingPackageName;
+ }
+
public int getCallingUid() {
return mCallingUid;
}
@@ -62,6 +72,7 @@
return mJobId;
}
+ @Nullable
public String getNamespace() {
return mNamespace;
}
@@ -70,6 +81,7 @@
return mSourceUserId;
}
+ @NonNull
public String getSourcePackageName() {
return mSourcePackageName;
}
@@ -80,6 +92,7 @@
if (!(o instanceof UserVisibleJobSummary)) return false;
UserVisibleJobSummary that = (UserVisibleJobSummary) o;
return mCallingUid == that.mCallingUid
+ && mCallingPackageName.equals(that.mCallingPackageName)
&& mSourceUserId == that.mSourceUserId
&& mSourcePackageName.equals(that.mSourcePackageName)
&& Objects.equals(mNamespace, that.mNamespace)
@@ -90,6 +103,7 @@
public int hashCode() {
int result = 0;
result = 31 * result + mCallingUid;
+ result = 31 * result + mCallingPackageName.hashCode();
result = 31 * result + mSourceUserId;
result = 31 * result + mSourcePackageName.hashCode();
if (mNamespace != null) {
@@ -103,6 +117,7 @@
public String toString() {
return "UserVisibleJobSummary{"
+ "callingUid=" + mCallingUid
+ + ", callingPackageName='" + mCallingPackageName + "'"
+ ", sourceUserId=" + mSourceUserId
+ ", sourcePackageName='" + mSourcePackageName + "'"
+ ", namespace=" + mNamespace
@@ -118,6 +133,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mCallingUid);
+ dest.writeString(mCallingPackageName);
dest.writeInt(mSourceUserId);
dest.writeString(mSourcePackageName);
dest.writeString(mNamespace);
diff --git a/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java b/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
index 95d6f850..581ea7a 100644
--- a/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
+++ b/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
@@ -126,7 +126,7 @@
public static final String KEY_ENABLE_TARE_MODE = "enable_tare_mode";
public static final String KEY_ENABLE_POLICY_ALARM = "enable_policy_alarm";
public static final String KEY_ENABLE_POLICY_JOB_SCHEDULER = "enable_policy_job";
- public static final int DEFAULT_ENABLE_TARE_MODE = ENABLED_MODE_ON;
+ public static final int DEFAULT_ENABLE_TARE_MODE = ENABLED_MODE_OFF;
public static final boolean DEFAULT_ENABLE_POLICY_ALARM = true;
public static final boolean DEFAULT_ENABLE_POLICY_JOB_SCHEDULER = true;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobCompletedListener.java b/apex/jobscheduler/service/java/com/android/server/job/JobCompletedListener.java
index 862d8b7..3f46cc4 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobCompletedListener.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobCompletedListener.java
@@ -16,6 +16,8 @@
package com.android.server.job;
+import android.app.job.JobParameters;
+
import com.android.server.job.controllers.JobStatus;
/**
@@ -26,8 +28,12 @@
/**
* Callback for when a job is completed.
*
- * @param stopReason The stop reason provided to JobParameters.
- * @param needsReschedule Whether the implementing class should reschedule this job.
+ * @param stopReason The stop reason returned from
+ * {@link JobParameters#getStopReason()}.
+ * @param internalStopReason The stop reason returned from
+ * {@link JobParameters#getInternalStopReasonCode()}.
+ * @param needsReschedule Whether the implementing class should reschedule this job.
*/
- void onJobCompletedLocked(JobStatus jobStatus, int stopReason, boolean needsReschedule);
+ void onJobCompletedLocked(JobStatus jobStatus, int stopReason, int internalStopReason,
+ boolean needsReschedule);
}
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 5e4d000..299cb6c 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -1695,10 +1695,28 @@
}
private void stopUserVisibleJobsInternal(@NonNull String packageName, int userId) {
+ final int packageUid = mLocalPM.getPackageUid(packageName, 0, userId);
+ if (packageUid < 0) {
+ Slog.wtf(TAG, "Asked to stop jobs of an unknown package");
+ return;
+ }
synchronized (mLock) {
mConcurrencyManager.stopUserVisibleJobsLocked(userId, packageName,
JobParameters.STOP_REASON_USER,
JobParameters.INTERNAL_STOP_REASON_USER_UI_STOP);
+ final ArraySet<JobStatus> jobs = mJobs.getJobsByUid(packageUid);
+ for (int i = jobs.size() - 1; i >= 0; i--) {
+ final JobStatus job = jobs.valueAt(i);
+
+ // For now, demote all jobs of the app. However, if the app was only doing work
+ // on behalf of another app and the user wanted just that work to stop, this
+ // unfairly penalizes any other jobs that may be scheduled.
+ // For example, if apps A & B ask app C to do something (thus A & B are "source"
+ // and C is "calling"), but only A's work was under way and the user wanted
+ // to stop only that work, B's jobs would be demoted as well.
+ // TODO(255768978): make it possible to demote only the relevant subset of jobs
+ job.addInternalFlags(JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER);
+ }
}
}
@@ -2352,7 +2370,7 @@
*/
@VisibleForTesting
JobStatus getRescheduleJobForFailureLocked(JobStatus failureToReschedule,
- int internalStopReason) {
+ @JobParameters.StopReason int stopReason, int internalStopReason) {
final long elapsedNowMillis = sElapsedRealtimeClock.millis();
final JobInfo job = failureToReschedule.getJob();
@@ -2360,9 +2378,11 @@
int numFailures = failureToReschedule.getNumFailures();
int numSystemStops = failureToReschedule.getNumSystemStops();
// We should back off slowly if JobScheduler keeps stopping the job,
- // but back off immediately if the issue appeared to be the app's fault.
+ // but back off immediately if the issue appeared to be the app's fault
+ // or the user stopped the job somehow.
if (internalStopReason == JobParameters.INTERNAL_STOP_REASON_SUCCESSFUL_FINISH
- || internalStopReason == JobParameters.INTERNAL_STOP_REASON_TIMEOUT) {
+ || internalStopReason == JobParameters.INTERNAL_STOP_REASON_TIMEOUT
+ || stopReason == JobParameters.STOP_REASON_USER) {
numFailures++;
} else {
numSystemStops++;
@@ -2393,11 +2413,14 @@
}
delayMillis =
Math.min(delayMillis, JobInfo.MAX_BACKOFF_DELAY_MILLIS);
- // TODO(255767350): demote all jobs to regular for user stops so they don't keep privileges
JobStatus newJob = new JobStatus(failureToReschedule,
elapsedNowMillis + delayMillis,
JobStatus.NO_LATEST_RUNTIME, numFailures, numSystemStops,
failureToReschedule.getLastSuccessfulRunTime(), sSystemClock.millis());
+ if (stopReason == JobParameters.STOP_REASON_USER) {
+ // Demote all jobs to regular for user stops so they don't keep privileges.
+ newJob.addInternalFlags(JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER);
+ }
if (job.isPeriodic()) {
newJob.setOriginalLatestRunTimeElapsed(
failureToReschedule.getOriginalLatestRunTimeElapsed());
@@ -2518,8 +2541,8 @@
* @param needsReschedule Whether the implementing class should reschedule this job.
*/
@Override
- public void onJobCompletedLocked(JobStatus jobStatus, int debugStopReason,
- boolean needsReschedule) {
+ public void onJobCompletedLocked(JobStatus jobStatus, @JobParameters.StopReason int stopReason,
+ int debugStopReason, boolean needsReschedule) {
if (DEBUG) {
Slog.d(TAG, "Completed " + jobStatus + ", reason=" + debugStopReason
+ ", reschedule=" + needsReschedule);
@@ -2546,7 +2569,7 @@
// job so we can transfer any appropriate state over from the previous job when
// we stop it.
final JobStatus rescheduledJob = needsReschedule
- ? getRescheduleJobForFailureLocked(jobStatus, debugStopReason) : null;
+ ? getRescheduleJobForFailureLocked(jobStatus, stopReason, debugStopReason) : null;
if (rescheduledJob != null
&& !rescheduledJob.shouldTreatAsUserInitiatedJob()
&& (debugStopReason == JobParameters.INTERNAL_STOP_REASON_TIMEOUT
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index c2168d2..911744f 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -1194,6 +1194,7 @@
applyStoppedReasonLocked(reason);
completedJob = mRunningJob;
final int internalStopReason = mParams.getInternalStopReasonCode();
+ final int stopReason = mParams.getStopReason();
mPreviousJobHadSuccessfulFinish =
(internalStopReason == JobParameters.INTERNAL_STOP_REASON_SUCCESSFUL_FINISH);
if (!mPreviousJobHadSuccessfulFinish) {
@@ -1214,7 +1215,7 @@
completedJob.hasContentTriggerConstraint(),
completedJob.isRequestedExpeditedJob(),
completedJob.startedAsExpeditedJob,
- mParams.getStopReason(),
+ stopReason,
completedJob.getJob().isPrefetch(),
completedJob.getJob().getPriority(),
completedJob.getEffectivePriority(),
@@ -1267,7 +1268,8 @@
if (completedJob.isUserVisibleJob()) {
mService.informObserversOfUserVisibleJobChange(this, completedJob, false);
}
- mCompletedListener.onJobCompletedLocked(completedJob, internalStopReason, reschedule);
+ mCompletedListener.onJobCompletedLocked(completedJob, stopReason, internalStopReason,
+ reschedule);
mJobConcurrencyManager.onJobCompletedLocked(this, completedJob, workType);
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/PendingJobQueue.java b/apex/jobscheduler/service/java/com/android/server/job/PendingJobQueue.java
index 0a305a2..4f4096f 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/PendingJobQueue.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/PendingJobQueue.java
@@ -219,6 +219,8 @@
ajq.clear();
mAppJobQueuePool.release(ajq);
} else if (prevTimestamp != ajq.peekNextTimestamp()) {
+ // Removing the job changed the "next timestamp" in the queue, so we need to reinsert
+ // it to fix the ordering.
mOrderedQueues.remove(ajq);
mOrderedQueues.offer(ajq);
}
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 9a69fdf..ce33a8e 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
@@ -373,6 +373,11 @@
* @hide
*/
public static final int INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION = 1 << 0;
+ /**
+ * Flag for {@link #mInternalFlags}: this job was stopped by the user for some reason
+ * and is thus considered demoted from whatever privileged state it had in the past.
+ */
+ public static final int INTERNAL_FLAG_DEMOTED_BY_USER = 1 << 1;
/** Minimum difference between start and end time to have flexible constraint */
@VisibleForTesting
@@ -1380,8 +1385,8 @@
* for any reason.
*/
public boolean shouldTreatAsUserInitiatedJob() {
- // TODO(248386641): update implementation to handle loss of privilege
- return getJob().isUserInitiated();
+ return getJob().isUserInitiated()
+ && (getInternalFlags() & INTERNAL_FLAG_DEMOTED_BY_USER) == 0;
}
/**
@@ -1391,7 +1396,8 @@
public UserVisibleJobSummary getUserVisibleJobSummary() {
if (mUserVisibleJobSummary == null) {
mUserVisibleJobSummary = new UserVisibleJobSummary(
- callingUid, getSourceUserId(), getSourcePackageName(),
+ callingUid, getServiceComponent().getPackageName(),
+ getSourceUserId(), getSourcePackageName(),
getNamespace(), getJobId());
}
return mUserVisibleJobSummary;
diff --git a/core/api/current.txt b/core/api/current.txt
index 7bdbd7b..53890eb 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -1900,6 +1900,18 @@
field public static final int system_accent3_700 = 17170522; // 0x106005a
field public static final int system_accent3_800 = 17170523; // 0x106005b
field public static final int system_accent3_900 = 17170524; // 0x106005c
+ field public static final int system_background_dark;
+ field public static final int system_background_light;
+ field public static final int system_control_activated_dark;
+ field public static final int system_control_activated_light;
+ field public static final int system_control_highlight_dark;
+ field public static final int system_control_highlight_light;
+ field public static final int system_control_normal_dark;
+ field public static final int system_control_normal_light;
+ field public static final int system_error_container_dark;
+ field public static final int system_error_container_light;
+ field public static final int system_error_dark;
+ field public static final int system_error_light;
field public static final int system_neutral1_0 = 17170461; // 0x106001d
field public static final int system_neutral1_10 = 17170462; // 0x106001e
field public static final int system_neutral1_100 = 17170464; // 0x1060020
@@ -1926,6 +1938,104 @@
field public static final int system_neutral2_700 = 17170483; // 0x1060033
field public static final int system_neutral2_800 = 17170484; // 0x1060034
field public static final int system_neutral2_900 = 17170485; // 0x1060035
+ field public static final int system_on_background_dark;
+ field public static final int system_on_background_light;
+ field public static final int system_on_error_container_dark;
+ field public static final int system_on_error_container_light;
+ field public static final int system_on_error_dark;
+ field public static final int system_on_error_light;
+ field public static final int system_on_primary_container_dark;
+ field public static final int system_on_primary_container_light;
+ field public static final int system_on_primary_dark;
+ field public static final int system_on_primary_fixed_dark;
+ field public static final int system_on_primary_fixed_light;
+ field public static final int system_on_primary_fixed_variant_dark;
+ field public static final int system_on_primary_fixed_variant_light;
+ field public static final int system_on_primary_light;
+ field public static final int system_on_secondary_container_dark;
+ field public static final int system_on_secondary_container_light;
+ field public static final int system_on_secondary_dark;
+ field public static final int system_on_secondary_fixed_dark;
+ field public static final int system_on_secondary_fixed_light;
+ field public static final int system_on_secondary_fixed_variant_dark;
+ field public static final int system_on_secondary_fixed_variant_light;
+ field public static final int system_on_secondary_light;
+ field public static final int system_on_surface_dark;
+ field public static final int system_on_surface_light;
+ field public static final int system_on_surface_variant_dark;
+ field public static final int system_on_surface_variant_light;
+ field public static final int system_on_tertiary_container_dark;
+ field public static final int system_on_tertiary_container_light;
+ field public static final int system_on_tertiary_dark;
+ field public static final int system_on_tertiary_fixed_dark;
+ field public static final int system_on_tertiary_fixed_light;
+ field public static final int system_on_tertiary_fixed_variant_dark;
+ field public static final int system_on_tertiary_fixed_variant_light;
+ field public static final int system_on_tertiary_light;
+ field public static final int system_outline_dark;
+ field public static final int system_outline_light;
+ field public static final int system_palette_key_color_neutral_dark;
+ field public static final int system_palette_key_color_neutral_light;
+ field public static final int system_palette_key_color_neutral_variant_dark;
+ field public static final int system_palette_key_color_neutral_variant_light;
+ field public static final int system_palette_key_color_primary_dark;
+ field public static final int system_palette_key_color_primary_light;
+ field public static final int system_palette_key_color_secondary_dark;
+ field public static final int system_palette_key_color_secondary_light;
+ field public static final int system_palette_key_color_tertiary_dark;
+ field public static final int system_palette_key_color_tertiary_light;
+ field public static final int system_primary_container_dark;
+ field public static final int system_primary_container_light;
+ field public static final int system_primary_dark;
+ field public static final int system_primary_fixed_dark;
+ field public static final int system_primary_fixed_darker_light;
+ field public static final int system_primary_fixed_light;
+ field public static final int system_primary_fixeder_dark;
+ field public static final int system_primary_light;
+ field public static final int system_secondary_container_dark;
+ field public static final int system_secondary_container_light;
+ field public static final int system_secondary_dark;
+ field public static final int system_secondary_fixed_dark;
+ field public static final int system_secondary_fixed_darker_light;
+ field public static final int system_secondary_fixed_light;
+ field public static final int system_secondary_fixeder_dark;
+ field public static final int system_secondary_light;
+ field public static final int system_surface_bright_dark;
+ field public static final int system_surface_bright_light;
+ field public static final int system_surface_container_dark;
+ field public static final int system_surface_container_high_dark;
+ field public static final int system_surface_container_high_light;
+ field public static final int system_surface_container_highest_dark;
+ field public static final int system_surface_container_highest_light;
+ field public static final int system_surface_container_light;
+ field public static final int system_surface_container_low_dark;
+ field public static final int system_surface_container_low_light;
+ field public static final int system_surface_container_lowest_dark;
+ field public static final int system_surface_container_lowest_light;
+ field public static final int system_surface_dark;
+ field public static final int system_surface_dim_dark;
+ field public static final int system_surface_dim_light;
+ field public static final int system_surface_light;
+ field public static final int system_surface_variant_dark;
+ field public static final int system_surface_variant_light;
+ field public static final int system_tertiary_container_dark;
+ field public static final int system_tertiary_container_light;
+ field public static final int system_tertiary_dark;
+ field public static final int system_tertiary_fixed_dark;
+ field public static final int system_tertiary_fixed_darker_light;
+ field public static final int system_tertiary_fixed_light;
+ field public static final int system_tertiary_fixeder_dark;
+ field public static final int system_tertiary_light;
+ field public static final int system_text_hint_inverse_dark;
+ field public static final int system_text_hint_inverse_light;
+ field public static final int system_text_primary_inverse_dark;
+ field public static final int system_text_primary_inverse_disable_only_dark;
+ field public static final int system_text_primary_inverse_disable_only_light;
+ field public static final int system_text_primary_inverse_light;
+ field public static final int system_text_secondary_and_tertiary_inverse_dark;
+ field public static final int system_text_secondary_and_tertiary_inverse_disabled_dark;
+ field public static final int system_text_secondary_and_tertiary_inverse_disabled_light;
+ field public static final int system_text_secondary_and_tertiary_inverse_light;
field public static final int tab_indicator_text = 17170441; // 0x1060009
field @Deprecated public static final int tertiary_text_dark = 17170448; // 0x1060010
field @Deprecated public static final int tertiary_text_light = 17170449; // 0x1060011
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 46ac819..a40d97e 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -5807,14 +5807,19 @@
public final class DisplayPortAltModeInfo implements android.os.Parcelable {
method public int describeContents();
method public int getCableStatus();
+ method public int getLinkTrainingStatus();
method public int getNumberOfLanes();
method public int getPartnerSinkStatus();
+ method public boolean isHotPlugDetectActive();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.usb.DisplayPortAltModeInfo> CREATOR;
field public static final int DISPLAYPORT_ALT_MODE_STATUS_CAPABLE = 2; // 0x2
field public static final int DISPLAYPORT_ALT_MODE_STATUS_ENABLED = 3; // 0x3
field public static final int DISPLAYPORT_ALT_MODE_STATUS_NOT_CAPABLE = 1; // 0x1
field public static final int DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN = 0; // 0x0
+ field public static final int LINK_TRAINING_STATUS_FAILURE = 2; // 0x2
+ field public static final int LINK_TRAINING_STATUS_SUCCESS = 1; // 0x1
+ field public static final int LINK_TRAINING_STATUS_UNKNOWN = 0; // 0x0
}
public class UsbDeviceConnection {
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 57214e0..2a390a7 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1997,10 +1997,12 @@
/**
* Sets background activity launch logic won't use pending intent creator foreground state.
+ *
* @hide
*/
- public void setIgnorePendingIntentCreatorForegroundState(boolean state) {
+ public ActivityOptions setIgnorePendingIntentCreatorForegroundState(boolean state) {
mIgnorePendingIntentCreatorForegroundState = state;
+ return this;
}
/**
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 44bfbf6..25b395b 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1408,14 +1408,16 @@
AppProtoEnums.APP_OP_FOREGROUND_SERVICE_SPECIAL_USE;
/**
- * Exempt from start foreground service from background restriction.
+ * Exempt an app from all power-related restrictions, including app standby and doze.
+ * In addition, the app will be able to start foreground services from the background, and the
+ * user will not be able to stop foreground services run by the app.
*
* Only to be used by the system.
*
* @hide
*/
- public static final int OP_SYSTEM_EXEMPT_FROM_FGS_BG_START_RESTRICTION =
- AppProtoEnums.APP_OP_SYSTEM_EXEMPT_FROM_FGS_BG_START_RESTRICTION;
+ public static final int OP_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS =
+ AppProtoEnums.APP_OP_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS;
/**
* Exempt from start foreground service from background with while in user permission
@@ -1994,14 +1996,16 @@
"android:foreground_service_special_use";
/**
- * Exempt from start foreground service from background restriction.
+ * Exempt an app from all power-related restrictions, including app standby and doze.
+ * In addition, the app will be able to start foreground services from the background, and the
+ * user will not be able to stop foreground services run by the app.
*
* Only to be used by the system.
*
* @hide
*/
- public static final String OPSTR_SYSTEM_EXEMPT_FROM_FGS_BG_START_RESTRICTION =
- "android:system_exempt_from_fgs_bg_start_restriction";
+ public static final String OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS =
+ "android:system_exempt_from_power_restrictions";
/**
* Exempt from start foreground service from background with while in user permission
@@ -2535,9 +2539,9 @@
new AppOpInfo.Builder(OP_FOREGROUND_SERVICE_SPECIAL_USE,
OPSTR_FOREGROUND_SERVICE_SPECIAL_USE, "FOREGROUND_SERVICE_SPECIAL_USE")
.setPermission(Manifest.permission.FOREGROUND_SERVICE_SPECIAL_USE).build(),
- new AppOpInfo.Builder(OP_SYSTEM_EXEMPT_FROM_FGS_BG_START_RESTRICTION,
- OPSTR_SYSTEM_EXEMPT_FROM_FGS_BG_START_RESTRICTION,
- "SYSTEM_EXEMPT_FROM_FGS_BG_START_RESTRICTION").build(),
+ new AppOpInfo.Builder(OP_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS,
+ OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS,
+ "SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS").build(),
new AppOpInfo.Builder(
OP_SYSTEM_EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION,
OPSTR_SYSTEM_EXEMPT_FROM_FGS_BG_START_WHILE_IN_USE_PERMISSION_RESTRICTION,
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index dd44531..e1ee3e0 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -57,7 +57,6 @@
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
-import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
@@ -430,10 +429,9 @@
}
// Whenever creation or retrieval of a mutable implicit PendingIntent occurs:
- // - For apps with target SDK >= U, Log.wtfStack() that it is blocked for security reasons.
- // This will be changed to a throw of an exception on the server side once we finish
- // migrating to safer PendingIntents b/262253127.
- // - Otherwise, warn that it will be blocked from target SDK U.
+ // - For apps with target SDK >= U, throw an IllegalArgumentException for
+ // security reasons.
+ // - Otherwise, warn that it will be blocked from target SDK U onwards.
if (isNewMutableDisallowedImplicitPendingIntent(flags, intent)) {
if (Compatibility.isChangeEnabled(BLOCK_MUTABLE_IMPLICIT_PENDING_INTENT)) {
String msg = packageName + ": Targeting U+ (version "
@@ -445,7 +443,7 @@
+ " PendingIntent, use FLAG_NO_CREATE, however, to create a"
+ " new PendingIntent with an implicit Intent use"
+ " FLAG_IMMUTABLE.";
- Slog.wtfStack(TAG, msg);
+ throw new IllegalArgumentException(msg);
} else {
String msg = "New mutable implicit PendingIntent: pkg=" + packageName
+ ", action=" + intent.getAction()
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 1f5182a..52d1d68 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -510,11 +510,12 @@
return new BinaryTransparencyManager(ctx, service);
}});
+ // InputManager stores its own static instance for historical purposes.
registerService(Context.INPUT_SERVICE, InputManager.class,
- new StaticServiceFetcher<InputManager>() {
+ new ServiceFetcher<InputManager>() {
@Override
- public InputManager createService() {
- return InputManager.getInstance();
+ public InputManager getService(ContextImpl ctx) {
+ return InputManager.getInstance(ctx);
}});
registerService(Context.DISPLAY_SERVICE, DisplayManager.class,
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index e803084..e7bac02 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1234,6 +1234,56 @@
@Overridable
public static final long OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS = 263259275L;
+ // Compat framework that per-app overrides rely on only supports booleans. That's why we have
+ // multiple OVERRIDE_*_ORIENTATION_* change ids below instead of just one override with
+ // the integer value.
+
+ /**
+ * Enables {@link #SCREEN_ORIENTATION_PORTRAIT}. Unless OVERRIDE_ANY_ORIENTATION
+ * is enabled, this override is used only when no other fixed orientation was specified by the
+ * activity.
+ * @hide
+ */
+ @ChangeId
+ @Disabled
+ @Overridable
+ public static final long OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT = 265452344L;
+
+ /**
+ * Enables {@link #SCREEN_ORIENTATION_NOSENSOR}. Unless OVERRIDE_ANY_ORIENTATION
+ * is enabled, this override is used only when no other fixed orientation was specified by the
+ * activity.
+ * @hide
+ */
+ @ChangeId
+ @Disabled
+ @Overridable
+ public static final long OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR = 265451093L;
+
+ /**
+ * Enables {@link #SCREEN_ORIENTATION_REVERSE_LANDSCAPE}. Unless OVERRIDE_ANY_ORIENTATION
+ * is enabled, this override is used only when activity specify landscape orientation.
+ * This can help apps that assume that landscape display orientation corresponds to {@link
+ * android.view.Surface#ROTATION_90}, while on some devices it can be {@link
+ * android.view.Surface#ROTATION_270}.
+ * @hide
+ */
+ @ChangeId
+ @Disabled
+ @Overridable
+ public static final long OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE = 266124927L;
+
+ /**
+ * When enabled, allows OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE,
+ * OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR and OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT
+ * to override any orientation requested by the activity.
+ * @hide
+ */
+ @ChangeId
+ @Disabled
+ @Overridable
+ public static final long OVERRIDE_ANY_ORIENTATION = 265464455L;
+
/**
* Compares activity window layout min width/height with require space for multi window to
* determine if it can be put into multi window mode.
@@ -1453,8 +1503,19 @@
* @hide
*/
public boolean isFixedOrientation() {
- return isFixedOrientationLandscape() || isFixedOrientationPortrait()
- || screenOrientation == SCREEN_ORIENTATION_LOCKED;
+ return isFixedOrientation(screenOrientation);
+ }
+
+ /**
+ * Returns true if the passed activity's orientation is fixed.
+ * @hide
+ */
+ public static boolean isFixedOrientation(@ScreenOrientation int orientation) {
+ return orientation == SCREEN_ORIENTATION_LOCKED
+ // Orientation is fixed to natural display orientation
+ || orientation == SCREEN_ORIENTATION_NOSENSOR
+ || isFixedOrientationLandscape(orientation)
+ || isFixedOrientationPortrait(orientation);
}
/**
diff --git a/core/java/android/credentials/ui/BaseDialogResult.java b/core/java/android/credentials/ui/BaseDialogResult.java
index 5223314..f0442de 100644
--- a/core/java/android/credentials/ui/BaseDialogResult.java
+++ b/core/java/android/credentials/ui/BaseDialogResult.java
@@ -56,14 +56,14 @@
* The intent extra key for the {@code BaseDialogResult} object when the credential
* selector activity finishes.
*/
- private static final String EXTRA_BASE_RESULT =
- "android.credentials.ui.extra.BASE_RESULT";
+ private static final String EXTRA_BASE_RESULT = "android.credentials.ui.extra.BASE_RESULT";
/** @hide **/
@IntDef(prefix = {"RESULT_CODE_"}, value = {
RESULT_CODE_DIALOG_USER_CANCELED,
RESULT_CODE_CANCELED_AND_LAUNCHED_SETTINGS,
RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION,
+ RESULT_CODE_DATA_PARSING_FAILURE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ResultCode {}
@@ -80,6 +80,10 @@
* {@code resultData}.
*/
public static final int RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION = 2;
+ /**
+ * The UI was canceled because it failed to parse the incoming data.
+ */
+ public static final int RESULT_CODE_DATA_PARSING_FAILURE = 3;
@NonNull
private final IBinder mRequestToken;
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 7409187..9a092a5 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -21,6 +21,7 @@
import android.companion.virtual.IVirtualDevice;
import android.graphics.Point;
import android.hardware.SensorManager;
+import android.hardware.input.HostUsiVersion;
import android.os.Handler;
import android.os.PowerManager;
import android.util.IntArray;
@@ -403,6 +404,14 @@
public abstract SurfaceControl.DisplayPrimaries getDisplayNativePrimaries(int displayId);
/**
+ * Get the version of the Universal Stylus Initiative (USI) Protocol supported by the display.
+ * @param displayId The id of the display.
+ * @return The USI version, or null if not supported
+ */
+ @Nullable
+ public abstract HostUsiVersion getHostUsiVersion(int displayId);
+
+ /**
* Describes the requested power state of the display.
*
* This object is intended to describe the general characteristics of the
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 197739b..96098f8 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -26,6 +26,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricFaceConstants;
@@ -87,6 +88,7 @@
private CryptoObject mCryptoObject;
private Face mRemovalFace;
private Handler mHandler;
+ private List<FaceSensorPropertiesInternal> mProps = new ArrayList<>();
private final IFaceServiceReceiver mServiceReceiver = new IFaceServiceReceiver.Stub() {
@@ -168,6 +170,16 @@
Slog.v(TAG, "FaceAuthenticationManagerService was null");
}
mHandler = new MyHandler(context);
+ if (context.checkCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL)
+ == PackageManager.PERMISSION_GRANTED) {
+ addAuthenticatorsRegisteredCallback(new IFaceAuthenticatorsRegisteredCallback.Stub() {
+ @Override
+ public void onAllAuthenticatorsRegistered(
+ @NonNull List<FaceSensorPropertiesInternal> sensors) {
+ mProps = sensors;
+ }
+ });
+ }
}
/**
@@ -664,14 +676,14 @@
@NonNull
public List<FaceSensorPropertiesInternal> getSensorPropertiesInternal() {
try {
- if (mService == null) {
- return new ArrayList<>();
+ if (!mProps.isEmpty() || mService == null) {
+ return mProps;
}
return mService.getSensorPropertiesInternal(mContext.getOpPackageName());
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
- return new ArrayList<>();
+ return mProps;
}
/**
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index b24b30e..d9f8f8e 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -153,6 +153,7 @@
@Nullable private RemoveTracker mRemoveTracker;
private Handler mHandler;
@Nullable private float[] mEnrollStageThresholds;
+ private List<FingerprintSensorPropertiesInternal> mProps = new ArrayList<>();
/**
* Retrieves a list of properties for all fingerprint sensors on the device.
@@ -1185,8 +1186,8 @@
@NonNull
public List<FingerprintSensorPropertiesInternal> getSensorPropertiesInternal() {
try {
- if (mService == null) {
- return new ArrayList<>();
+ if (!mProps.isEmpty() || mService == null) {
+ return mProps;
}
return mService.getSensorPropertiesInternal(mContext.getOpPackageName());
} catch (RemoteException e) {
@@ -1502,6 +1503,17 @@
Slog.v(TAG, "FingerprintService was null");
}
mHandler = new MyHandler(context);
+ if (context.checkCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL)
+ == PackageManager.PERMISSION_GRANTED) {
+ addAuthenticatorsRegisteredCallback(
+ new IFingerprintAuthenticatorsRegisteredCallback.Stub() {
+ @Override
+ public void onAllAuthenticatorsRegistered(
+ @NonNull List<FingerprintSensorPropertiesInternal> sensors) {
+ mProps = sensors;
+ }
+ });
+ }
}
private int getCurrentUserId() {
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 222cf08..c3fae55 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -17,6 +17,7 @@
package android.hardware.input;
import android.graphics.Rect;
+import android.hardware.input.HostUsiVersion;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.IInputDevicesChangedListener;
@@ -233,4 +234,6 @@
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
+ "android.Manifest.permission.MONITOR_KEYBOARD_BACKLIGHT)")
void unregisterKeyboardBacklightListener(IKeyboardBacklightListener listener);
+
+ HostUsiVersion getHostUsiVersionFromDisplayConfig(int displayId);
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index f27c34c..3ccc940 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -55,8 +55,6 @@
import android.os.Vibrator;
import android.os.VibratorManager;
import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
-import android.util.DisplayUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
@@ -71,7 +69,6 @@
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
-import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
@@ -102,19 +99,33 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final IInputManager mIm;
- private final boolean mIsStylusPointerIconEnabled;
+ /**
+ * InputManager has historically used its own static getter {@link #getInstance()} that doesn't
+ * provide a context. We provide a Context to the InputManager instance through the
+ * {@link android.app.SystemServiceRegistry}. Methods that need a Context must use
+ * {@link #getContext()} to obtain it.
+ */
+ @Nullable
+ private Context mLateInitContext;
+
+ /**
+ * Whether a PointerIcon is shown for stylus pointers.
+ * Obtain using {@link #isStylusPointerIconEnabled()}.
+ */
+ @Nullable
+ private Boolean mIsStylusPointerIconEnabled = null;
// Guarded by mInputDevicesLock
private final Object mInputDevicesLock = new Object();
private SparseArray<InputDevice> mInputDevices;
private InputDevicesChangedListener mInputDevicesChangedListener;
- private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners =
- new ArrayList<InputDeviceListenerDelegate>();
+ private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners = new ArrayList<>();
// Guarded by mTabletModeLock
private final Object mTabletModeLock = new Object();
+ @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
private TabletModeChangedListener mTabletModeChangedListener;
- private List<OnTabletModeChangedListenerDelegate> mOnTabletModeChangedListeners;
+ private ArrayList<OnTabletModeChangedListenerDelegate> mOnTabletModeChangedListeners;
private final Object mBatteryListenersLock = new Object();
// Maps a deviceId whose battery is currently being monitored to an entry containing the
@@ -126,7 +137,7 @@
private final Object mKeyboardBacklightListenerLock = new Object();
@GuardedBy("mKeyboardBacklightListenerLock")
- private List<KeyboardBacklightListenerDelegate> mKeyboardBacklightListeners;
+ private ArrayList<KeyboardBacklightListenerDelegate> mKeyboardBacklightListeners;
@GuardedBy("mKeyboardBacklightListenerLock")
private IKeyboardBacklightListener mKeyboardBacklightListener;
@@ -326,15 +337,6 @@
} catch (RemoteException ex) {
Log.w(TAG, "Could not get VelocityTracker strategy: " + ex);
}
-
- // TODO(b/266013036): Pass a Context into InputManager constructor.
- final Context context = ActivityThread.currentApplication();
- if (context != null) {
- mIsStylusPointerIconEnabled = context.getResources()
- .getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon);
- } else {
- mIsStylusPointerIconEnabled = false;
- }
}
/**
@@ -368,24 +370,47 @@
* Gets an instance of the input manager.
*
* @return The input manager instance.
- *
+ * @deprecated Use {@link Context#getSystemService(Class)} or {@link #getInstance(Context)}
+ * to obtain the InputManager instance.
* @hide
*/
+ @Deprecated
@UnsupportedAppUsage
public static InputManager getInstance() {
+ return getInstance(ActivityThread.currentApplication());
+ }
+
+ /**
+ * Gets an instance of the input manager.
+ *
+ * @return The input manager instance.
+ * @hide
+ */
+ public static InputManager getInstance(Context context) {
synchronized (InputManager.class) {
if (sInstance == null) {
try {
sInstance = new InputManager(IInputManager.Stub
.asInterface(ServiceManager.getServiceOrThrow(Context.INPUT_SERVICE)));
+
} catch (ServiceNotFoundException e) {
throw new IllegalStateException(e);
}
}
+ if (sInstance.mLateInitContext == null) {
+ sInstance.mLateInitContext = context;
+ }
return sInstance;
}
}
+ @NonNull
+ private Context getContext() {
+ return Objects.requireNonNull(mLateInitContext,
+ "A context is required for InputManager. Get the InputManager instance using "
+ + "Context#getSystemService before calling this method.");
+ }
+
/**
* Get the current VelocityTracker strategy. Only works when the system has fully booted up.
* @hide
@@ -499,7 +524,7 @@
/**
* Enables an InputDevice.
* <p>
- * Requires {@link android.Manifest.permission.DISABLE_INPUT_DEVICE}.
+ * Requires {@link android.Manifest.permission#DISABLE_INPUT_DEVICE}.
* </p>
*
* @param id The input device Id.
@@ -518,7 +543,7 @@
/**
* Disables an InputDevice.
* <p>
- * Requires {@link android.Manifest.permission.DISABLE_INPUT_DEVICE}.
+ * Requires {@link android.Manifest.permission#DISABLE_INPUT_DEVICE}.
* </p>
*
* @param id The input device Id.
@@ -975,6 +1000,7 @@
*/
@TestApi
@NonNull
+ @SuppressWarnings("unchecked")
@RequiresPermission(Manifest.permission.REMAP_MODIFIER_KEYS)
public Map<Integer, Integer> getModifierKeyRemapping() {
try {
@@ -1005,7 +1031,7 @@
* Sets the TouchCalibration to apply to the specified input device's coordinates.
* <p>
* This method may have the side-effect of causing the input device in question
- * to be reconfigured. Requires {@link android.Manifest.permission.SET_INPUT_CALIBRATION}.
+ * to be reconfigured. Requires {@link android.Manifest.permission#SET_INPUT_CALIBRATION}.
* </p>
*
* @param inputDeviceDescriptor The input device descriptor.
@@ -1121,19 +1147,14 @@
* @hide
*/
public int getPointerSpeed(Context context) {
- int speed = DEFAULT_POINTER_SPEED;
- try {
- speed = Settings.System.getInt(context.getContentResolver(),
- Settings.System.POINTER_SPEED);
- } catch (SettingNotFoundException snfe) {
- }
- return speed;
+ return Settings.System.getInt(context.getContentResolver(),
+ Settings.System.POINTER_SPEED, DEFAULT_POINTER_SPEED);
}
/**
* Sets the mouse pointer speed.
* <p>
- * Requires {@link android.Manifest.permission.WRITE_SETTINGS}.
+ * Requires {@link android.Manifest.permission#WRITE_SETTINGS}.
* </p>
*
* @param context The application context.
@@ -1154,7 +1175,7 @@
/**
* Changes the mouse pointer speed temporarily, but does not save the setting.
* <p>
- * Requires {@link android.Manifest.permission.SET_POINTER_SPEED}.
+ * Requires {@link android.Manifest.permission#SET_POINTER_SPEED}.
* </p>
*
* @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
@@ -1188,8 +1209,7 @@
*/
@FloatRange(from = 0, to = 1)
public float getMaximumObscuringOpacityForTouch() {
- Context context = ActivityThread.currentApplication();
- return Settings.Global.getFloat(context.getContentResolver(),
+ return Settings.Global.getFloat(getContext().getContentResolver(),
Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH,
DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH);
}
@@ -1225,8 +1245,7 @@
throw new IllegalArgumentException(
"Maximum obscuring opacity for touch should be >= 0 and <= 1");
}
- Context context = ActivityThread.currentApplication();
- Settings.Global.putFloat(context.getContentResolver(),
+ Settings.Global.putFloat(getContext().getContentResolver(),
Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH, opacity);
}
@@ -1307,7 +1326,7 @@
* The synchronization mode determines whether the method blocks while waiting for
* input injection to proceed.
* <p>
- * Requires the {@link android.Manifest.permission.INJECT_EVENTS} permission.
+ * Requires the {@link android.Manifest.permission#INJECT_EVENTS} permission.
* </p><p>
* Make sure you correctly set the event time and input source of the event
* before calling this method.
@@ -1315,9 +1334,9 @@
*
* @param event The event to inject.
* @param mode The synchronization mode. One of:
- * {@link android.os.InputEventInjectionSync.NONE},
- * {@link android.os.InputEventInjectionSync.WAIT_FOR_RESULT}, or
- * {@link android.os.InputEventInjectionSync.WAIT_FOR_FINISHED}.
+ * {@link android.os.InputEventInjectionSync#NONE},
+ * {@link android.os.InputEventInjectionSync#WAIT_FOR_RESULT}, or
+ * {@link android.os.InputEventInjectionSync#WAIT_FOR_FINISHED}.
* @param targetUid The uid to target, or {@link android.os.Process#INVALID_UID} to target all
* windows.
* @return True if input event injection succeeded.
@@ -1347,7 +1366,7 @@
* The synchronization mode determines whether the method blocks while waiting for
* input injection to proceed.
* <p>
- * Requires the {@link android.Manifest.permission.INJECT_EVENTS} permission.
+ * Requires the {@link android.Manifest.permission#INJECT_EVENTS} permission.
* </p><p>
* Make sure you correctly set the event time and input source of the event
* before calling this method.
@@ -1355,9 +1374,9 @@
*
* @param event The event to inject.
* @param mode The synchronization mode. One of:
- * {@link android.os.InputEventInjectionSync.NONE},
- * {@link android.os.InputEventInjectionSync.WAIT_FOR_RESULT}, or
- * {@link android.os.InputEventInjectionSync.WAIT_FOR_FINISHED}.
+ * {@link android.os.InputEventInjectionSync#NONE},
+ * {@link android.os.InputEventInjectionSync#WAIT_FOR_RESULT}, or
+ * {@link android.os.InputEventInjectionSync#WAIT_FOR_FINISHED}.
* @return True if input event injection succeeded.
*
* @hide
@@ -1381,7 +1400,8 @@
* {@link android.view.InputEvent}
* {@code null} if the event could not be verified.
*/
- public @Nullable VerifiedInputEvent verifyInputEvent(@NonNull InputEvent event) {
+ @Nullable
+ public VerifiedInputEvent verifyInputEvent(@NonNull InputEvent event) {
try {
return mIm.verifyInputEvent(event);
} catch (RemoteException ex) {
@@ -1393,7 +1413,7 @@
* Changes the mouse pointer's icon shape into the specified id.
*
* @param iconId The id of the pointer graphic, as a value between
- * {@link PointerIcon.TYPE_ARROW} and {@link PointerIcon.TYPE_HANDWRITING}.
+ * {@link PointerIcon#TYPE_ARROW} and {@link PointerIcon#TYPE_HANDWRITING}.
*
* @hide
*/
@@ -1422,6 +1442,10 @@
* stylus pointer, false if there is no pointer icon shown for styluses.
*/
public boolean isStylusPointerIconEnabled() {
+ if (mIsStylusPointerIconEnabled == null) {
+ mIsStylusPointerIconEnabled = getContext().getResources()
+ .getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon);
+ }
return mIsStylusPointerIconEnabled;
}
@@ -1543,7 +1567,7 @@
* @param inputPort The port of the input device.
* @param displayPort The physical port of the associated display.
* <p>
- * Requires {@link android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
+ * Requires {@link android.Manifest.permission#ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
* </p>
* @hide
*/
@@ -1560,7 +1584,7 @@
* static association for the cleared input port will be restored.
* @param inputPort The port of the input device to be cleared.
* <p>
- * Requires {@link android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
+ * Requires {@link android.Manifest.permission#ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
* </p>
* @hide
*/
@@ -1578,7 +1602,7 @@
* @param inputPort The port of the input device.
* @param displayUniqueId The unique id of the associated display.
* <p>
- * Requires {@link android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
+ * Requires {@link android.Manifest.permission#ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
* </p>
* @hide
*/
@@ -1595,7 +1619,7 @@
* Removes a runtime association between the input device and display.
* @param inputPort The port of the input device.
* <p>
- * Requires {@link android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
+ * Requires {@link android.Manifest.permission#ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
* </p>
* @hide
*/
@@ -1637,35 +1661,11 @@
// If there are no input devices that report a valid USI version, see if there is a config
// that specifies the USI version for the display. This is to handle cases where the USI
// input device is not registered by the kernel/driver all the time.
- return findConfigUsiVersionForDisplay(display);
- }
-
- private HostUsiVersion findConfigUsiVersionForDisplay(@NonNull Display display) {
- final Context context = Objects.requireNonNull(ActivityThread.currentApplication());
- final String[] displayUniqueIds = context.getResources().getStringArray(
- R.array.config_displayUniqueIdArray);
- final int index;
- if (displayUniqueIds.length == 0 && display.getDisplayId() == context.getDisplayId()) {
- index = 0;
- } else {
- index = DisplayUtils.getDisplayUniqueIdConfigIndex(context.getResources(),
- display.getUniqueId());
+ try {
+ return mIm.getHostUsiVersionFromDisplayConfig(display.getDisplayId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
-
- final String[] versions = context.getResources().getStringArray(
- R.array.config_displayUsiVersionArray);
- if (index < 0 || index >= versions.length) {
- return null;
- }
- final String version = versions[index];
- if (version == null || version.isEmpty()) {
- return null;
- }
- final String[] majorMinor = version.split("\\.");
- if (majorMinor.length != 2) {
- throw new IllegalStateException("Failed to parse USI version: " + version);
- }
- return new HostUsiVersion(Integer.parseInt(majorMinor[0]), Integer.parseInt(majorMinor[1]));
}
private void populateInputDevicesLocked() {
@@ -1687,9 +1687,9 @@
throw ex.rethrowFromSystemServer();
}
- mInputDevices = new SparseArray<InputDevice>();
- for (int i = 0; i < ids.length; i++) {
- mInputDevices.put(ids[i], null);
+ mInputDevices = new SparseArray<>();
+ for (int id : ids) {
+ mInputDevices.put(id, null);
}
}
}
@@ -1761,8 +1761,8 @@
+ "whenNanos=" + whenNanos + ", inTabletMode=" + inTabletMode);
}
synchronized (mTabletModeLock) {
- final int N = mOnTabletModeChangedListeners.size();
- for (int i = 0; i < N; i++) {
+ final int numListeners = mOnTabletModeChangedListeners.size();
+ for (int i = 0; i < numListeners; i++) {
OnTabletModeChangedListenerDelegate listener =
mOnTabletModeChangedListeners.get(i);
listener.sendTabletModeChanged(whenNanos, inTabletMode);
@@ -1965,7 +1965,7 @@
}
List<LightState> lightStateList = request.getLightStates();
mIm.setLightStates(deviceId, lightIds,
- lightStateList.toArray(new LightState[lightStateList.size()]),
+ lightStateList.toArray(new LightState[0]),
token);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -2072,8 +2072,11 @@
} else {
// The deviceId is already being monitored for battery changes.
// Ensure that the listener is not already registered.
- for (InputDeviceBatteryListenerDelegate delegate : listenersForDevice.mDelegates) {
- if (Objects.equals(listener, delegate.mListener)) {
+ final int numDelegates = listenersForDevice.mDelegates.size();
+ for (int i = 0; i < numDelegates; i++) {
+ InputDeviceBatteryListener registeredListener =
+ listenersForDevice.mDelegates.get(i).mListener;
+ if (Objects.equals(listener, registeredListener)) {
throw new IllegalArgumentException(
"Attempting to register an InputDeviceBatteryListener that has "
+ "already been registered for deviceId: "
@@ -2208,7 +2211,7 @@
* Changes the touchpad pointer speed temporarily, but does not save the setting.
*
* The new speed will only apply to gesture-compatible touchpads.
- * Requires {@link android.Manifest.permission.SET_POINTER_SPEED}.
+ * Requires {@link android.Manifest.permission#SET_POINTER_SPEED}.
*
* @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
* {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
@@ -2398,8 +2401,9 @@
throw e.rethrowFromSystemServer();
}
}
- for (KeyboardBacklightListenerDelegate delegate : mKeyboardBacklightListeners) {
- if (delegate.mListener == listener) {
+ final int numListeners = mKeyboardBacklightListeners.size();
+ for (int i = 0; i < numListeners; i++) {
+ if (mKeyboardBacklightListeners.get(i).mListener == listener) {
throw new IllegalArgumentException("Listener has already been registered!");
}
}
@@ -2572,21 +2576,19 @@
public void sendTabletModeChanged(long whenNanos, boolean inTabletMode) {
SomeArgs args = SomeArgs.obtain();
- args.argi1 = (int) (whenNanos & 0xFFFFFFFF);
+ args.argi1 = (int) whenNanos;
args.argi2 = (int) (whenNanos >> 32);
- args.arg1 = (Boolean) inTabletMode;
+ args.arg1 = inTabletMode;
obtainMessage(MSG_TABLET_MODE_CHANGED, args).sendToTarget();
}
@Override
public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_TABLET_MODE_CHANGED:
- SomeArgs args = (SomeArgs) msg.obj;
- long whenNanos = (args.argi1 & 0xFFFFFFFFl) | ((long) args.argi2 << 32);
- boolean inTabletMode = (boolean) args.arg1;
- mListener.onTabletModeChanged(whenNanos, inTabletMode);
- break;
+ if (msg.what == MSG_TABLET_MODE_CHANGED) {
+ SomeArgs args = (SomeArgs) msg.obj;
+ long whenNanos = (args.argi1 & 0xFFFFFFFFL) | ((long) args.argi2 << 32);
+ boolean inTabletMode = (boolean) args.arg1;
+ mListener.onTabletModeChanged(whenNanos, inTabletMode);
}
}
}
@@ -2654,8 +2656,10 @@
if (entry == null) return;
entry.mInputDeviceBatteryState = state;
- for (InputDeviceBatteryListenerDelegate delegate : entry.mDelegates) {
- delegate.notifyBatteryStateChanged(entry.mInputDeviceBatteryState);
+ final int numDelegates = entry.mDelegates.size();
+ for (int i = 0; i < numDelegates; i++) {
+ entry.mDelegates.get(i)
+ .notifyBatteryStateChanged(entry.mInputDeviceBatteryState);
}
}
}
@@ -2668,8 +2672,8 @@
private final int mBrightnessLevel;
private final int mMaxBrightnessLevel;
- LocalKeyboardBacklightState(int brightnesslevel, int maxBrightnessLevel) {
- mBrightnessLevel = brightnesslevel;
+ LocalKeyboardBacklightState(int brightnessLevel, int maxBrightnessLevel) {
+ mBrightnessLevel = brightnessLevel;
mMaxBrightnessLevel = maxBrightnessLevel;
}
@@ -2709,8 +2713,10 @@
boolean isTriggeredByKeyPress) {
synchronized (mKeyboardBacklightListenerLock) {
if (mKeyboardBacklightListeners == null) return;
- for (KeyboardBacklightListenerDelegate delegate : mKeyboardBacklightListeners) {
- delegate.notifyKeyboardBacklightChange(deviceId, state, isTriggeredByKeyPress);
+ final int numListeners = mKeyboardBacklightListeners.size();
+ for (int i = 0; i < numListeners; i++) {
+ mKeyboardBacklightListeners.get(i)
+ .notifyKeyboardBacklightChange(deviceId, state, isTriggeredByKeyPress);
}
}
}
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index 621eab5..b7a694c 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -2017,26 +2017,14 @@
* - {@link #STATUS_BAD_VALUE} if modules is null
* - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails
*
- * @deprecated Please use {@link #listModulesAsOriginator(ArrayList, Identity)} or
+ * @removed Please use {@link #listModulesAsOriginator(ArrayList, Identity)} or
* {@link #listModulesAsMiddleman(ArrayList, Identity, Identity)}, based on whether the
* client is acting on behalf of its own identity or a separate identity.
* @hide
*/
@UnsupportedAppUsage
public static int listModules(@NonNull ArrayList<ModuleProperties> modules) {
- // TODO(ytai): This is a temporary hack to retain prior behavior, which makes
- // assumptions about process affinity and Binder context, namely that the binder calling ID
- // reliably reflects the originator identity.
- Identity middlemanIdentity = new Identity();
- middlemanIdentity.packageName = ActivityThread.currentOpPackageName();
-
- Identity originatorIdentity = new Identity();
- originatorIdentity.pid = Binder.getCallingPid();
- originatorIdentity.uid = Binder.getCallingUid();
-
- try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
- return listModulesAsMiddleman(modules, middlemanIdentity, originatorIdentity);
- }
+ return STATUS_OK;
}
/**
@@ -2051,10 +2039,11 @@
* - {@link #STATUS_NO_INIT} if the native service cannot be reached
* - {@link #STATUS_BAD_VALUE} if modules is null
* - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails
- *
+ * @deprecated Use {@link android.media.soundtrigger.SoundTriggerManager} instead.
* @hide
*/
@RequiresPermission(allOf = {RECORD_AUDIO, CAPTURE_AUDIO_HOTWORD})
+ @Deprecated
public static int listModulesAsOriginator(@NonNull ArrayList<ModuleProperties> modules,
@NonNull Identity originatorIdentity) {
try {
@@ -2082,9 +2071,11 @@
* - {@link #STATUS_BAD_VALUE} if modules is null
* - {@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails
*
+ * @deprecated Use {@link android.media.soundtrigger.SoundTriggerManager} instead.
* @hide
*/
@RequiresPermission(SOUNDTRIGGER_DELEGATE_IDENTITY)
+ @Deprecated
public static int listModulesAsMiddleman(@NonNull ArrayList<ModuleProperties> modules,
@NonNull Identity middlemanIdentity,
@NonNull Identity originatorIdentity) {
@@ -2123,30 +2114,14 @@
* is OK.
* @return a valid sound module in case of success or null in case of error.
*
- * @deprecated Please use
- * {@link #attachModuleAsOriginator(int, StatusListener, Handler, Identity)} or
- * {@link #attachModuleAsMiddleman(int, StatusListener, Handler, Identity, Identity)}, based
- * on whether the client is acting on behalf of its own identity or a separate identity.
+ * @removed Use {@link android.media.soundtrigger.SoundTriggerManager} instead.
* @hide
*/
@UnsupportedAppUsage
private static SoundTriggerModule attachModule(int moduleId,
@NonNull StatusListener listener,
@Nullable Handler handler) {
- // TODO(ytai): This is a temporary hack to retain prior behavior, which makes
- // assumptions about process affinity and Binder context, namely that the binder calling ID
- // reliably reflects the originator identity.
- Identity middlemanIdentity = new Identity();
- middlemanIdentity.packageName = ActivityThread.currentOpPackageName();
-
- Identity originatorIdentity = new Identity();
- originatorIdentity.pid = Binder.getCallingPid();
- originatorIdentity.uid = Binder.getCallingUid();
-
- try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
- return attachModuleAsMiddleman(moduleId, listener, handler, middlemanIdentity,
- originatorIdentity);
- }
+ return null;
}
/**
@@ -2162,10 +2137,11 @@
* @param originatorIdentity The identity of the originator, which will be used for permission
* purposes.
* @return a valid sound module in case of success or null in case of error.
- *
+ * @deprecated Use {@link android.media.soundtrigger.SoundTriggerManager} instead.
* @hide
*/
@RequiresPermission(SOUNDTRIGGER_DELEGATE_IDENTITY)
+ @Deprecated
public static SoundTriggerModule attachModuleAsMiddleman(int moduleId,
@NonNull SoundTrigger.StatusListener listener,
@Nullable Handler handler, Identity middlemanIdentity,
diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
index eed92c1..a1d74df 100644
--- a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
+++ b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
@@ -102,7 +102,9 @@
* Detach from this module. The {@link SoundTrigger.StatusListener} callback will not be called
* anymore and associated resources will be released.
* All models must have been unloaded prior to detaching.
+ * @deprecated Use {@link android.media.soundtrigger.SoundTriggerManager} instead.
*/
+ @Deprecated
@UnsupportedAppUsage
public synchronized void detach() {
try {
@@ -131,7 +133,9 @@
* - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native
* service fails
* - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
+ * @deprecated Use {@link android.media.soundtrigger.SoundTriggerManager} instead.
*/
+ @Deprecated
@UnsupportedAppUsage
public synchronized int loadSoundModel(@NonNull SoundTrigger.SoundModel model,
@NonNull int[] soundModelHandle) {
@@ -191,8 +195,10 @@
* - {@link SoundTrigger#STATUS_BAD_VALUE} if the sound model handle is invalid
* - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native
* service fails
+ * @deprecated Use {@link android.media.soundtrigger.SoundTriggerManager} instead.
*/
@UnsupportedAppUsage
+ @Deprecated
public synchronized int unloadSoundModel(int soundModelHandle) {
try {
mService.unloadModel(soundModelHandle);
@@ -219,8 +225,10 @@
* - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native
* service fails
* - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
+ * @deprecated Use {@link android.media.soundtrigger.SoundTriggerManager} instead.
*/
@UnsupportedAppUsage
+ @Deprecated
public synchronized int startRecognition(int soundModelHandle,
SoundTrigger.RecognitionConfig config) {
try {
@@ -244,8 +252,10 @@
* - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native
* service fails
* - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
+ * @deprecated Use {@link android.media.soundtrigger.SoundTriggerManager} instead.
*/
@UnsupportedAppUsage
+ @Deprecated
public synchronized int stopRecognition(int soundModelHandle) {
try {
mService.stopRecognition(soundModelHandle);
diff --git a/core/java/android/hardware/usb/DisplayPortAltModeInfo.java b/core/java/android/hardware/usb/DisplayPortAltModeInfo.java
index ef2fefc..7c62373 100644
--- a/core/java/android/hardware/usb/DisplayPortAltModeInfo.java
+++ b/core/java/android/hardware/usb/DisplayPortAltModeInfo.java
@@ -39,8 +39,8 @@
private final @DisplayPortAltModeStatus int mPartnerSinkStatus;
private final @DisplayPortAltModeStatus int mCableStatus;
private final int mNumLanes;
- private final boolean mHpd;
- private final int mLinkTrainingStatus;
+ private final boolean mHotPlugDetect;
+ private final @LinkTrainingStatus int mLinkTrainingStatus;
/**
* Port Partners:
@@ -90,6 +90,25 @@
*/
public static final int DISPLAYPORT_ALT_MODE_STATUS_ENABLED = 3;
+ /*
+ * Indicates that DisplayPort Alt Mode link training has not initiated or completed.
+ */
+ public static final int LINK_TRAINING_STATUS_UNKNOWN = 0;
+
+ /*
+ * Indicates that DisplayPort Alt Mode link training has completed and the optimal data
+ * transmission settings between the device and the connected port partner have successfully
+ * been negotiated.
+ */
+ public static final int LINK_TRAINING_STATUS_SUCCESS = 1;
+
+ /*
+ * Indicates that DisplayPort Alt Mode link training has completed but no data transmission
+ * settings between the device and the connected port partner could be established, and that the
+ * link initialization has terminated.
+ */
+ public static final int LINK_TRAINING_STATUS_FAILURE = 2;
+
/** @hide */
@IntDef(prefix = { "DISPLAYPORT_ALT_MODE_STATUS_" }, value = {
DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN,
@@ -101,21 +120,30 @@
public @interface DisplayPortAltModeStatus {}
/** @hide */
+ @IntDef(prefix = { "LINK_TRAINING_STATUS_" }, value = {
+ LINK_TRAINING_STATUS_UNKNOWN,
+ LINK_TRAINING_STATUS_SUCCESS,
+ LINK_TRAINING_STATUS_FAILURE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LinkTrainingStatus {}
+
+ /** @hide */
public DisplayPortAltModeInfo() {
mPartnerSinkStatus = DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN;
mCableStatus = DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN;
mNumLanes = 0;
- mHpd = false;
- mLinkTrainingStatus = 0;
+ mHotPlugDetect = false;
+ mLinkTrainingStatus = LINK_TRAINING_STATUS_UNKNOWN;
}
/** @hide */
public DisplayPortAltModeInfo(int partnerSinkStatus, int cableStatus,
- int numLanes, boolean hpd, int linkTrainingStatus) {
+ int numLanes, boolean hotPlugDetect, int linkTrainingStatus) {
mPartnerSinkStatus = partnerSinkStatus;
mCableStatus = cableStatus;
mNumLanes = numLanes;
- mHpd = hpd;
+ mHotPlugDetect = hotPlugDetect;
mLinkTrainingStatus = linkTrainingStatus;
}
@@ -151,6 +179,21 @@
return mNumLanes;
}
+ /**
+ * Returns whether or not the Hot Plug Detect (HPD) value of the connected DisplayPort Alt Mode
+ * partner sink is active.
+ */
+ public boolean isHotPlugDetectActive() {
+ return mHotPlugDetect;
+ }
+
+ /**
+ * Returns the DisplayPort Alt Mode link training status.
+ */
+ public @LinkTrainingStatus int getLinkTrainingStatus() {
+ return mLinkTrainingStatus;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -161,7 +204,7 @@
dest.writeInt(mPartnerSinkStatus);
dest.writeInt(mCableStatus);
dest.writeInt(mNumLanes);
- dest.writeBoolean(mHpd);
+ dest.writeBoolean(mHotPlugDetect);
dest.writeInt(mLinkTrainingStatus);
}
@@ -174,8 +217,8 @@
+ mCableStatus
+ " numLanes="
+ mNumLanes
- + " hpd="
- + mHpd
+ + " hotPlugDetect="
+ + mHotPlugDetect
+ " linkTrainingStatus="
+ mLinkTrainingStatus
+ "}";
@@ -192,12 +235,15 @@
DisplayPortAltModeInfo other = (DisplayPortAltModeInfo) o;
return this.mPartnerSinkStatus == other.mPartnerSinkStatus
&& this.mCableStatus == other.mCableStatus
- && this.mNumLanes == other.mNumLanes;
+ && this.mNumLanes == other.mNumLanes
+ && this.mHotPlugDetect == other.mHotPlugDetect
+ && this.mLinkTrainingStatus == other.mLinkTrainingStatus;
}
@Override
public int hashCode() {
- return Objects.hash(mPartnerSinkStatus, mCableStatus, mNumLanes);
+ return Objects.hash(mPartnerSinkStatus, mCableStatus, mNumLanes, mHotPlugDetect,
+ mLinkTrainingStatus);
}
public static final @NonNull Parcelable.Creator<DisplayPortAltModeInfo> CREATOR =
@@ -207,10 +253,10 @@
int partnerSinkStatus = in.readInt();
int cableStatus = in.readInt();
int numLanes = in.readInt();
- boolean hpd = in.readBoolean();
+ boolean hotPlugDetect = in.readBoolean();
int linkTrainingStatus = in.readInt();
- return new DisplayPortAltModeInfo(partnerSinkStatus, cableStatus, numLanes, hpd,
- linkTrainingStatus);
+ return new DisplayPortAltModeInfo(partnerSinkStatus, cableStatus, numLanes,
+ hotPlugDetect, linkTrainingStatus);
}
@Override
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 909d147..0483b71 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -37,8 +37,8 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.hardware.usb.gadget.V1_0.GadgetFunction;
-import android.hardware.usb.gadget.V1_2.UsbSpeed;
+import android.hardware.usb.gadget.GadgetFunction;
+import android.hardware.usb.gadget.UsbSpeed;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -54,15 +54,12 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.StringJoiner;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.Executor;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* This class allows you to access the state of USB and communicate with USB devices.
@@ -78,7 +75,7 @@
public class UsbManager {
private static final String TAG = "UsbManager";
- /**
+ /**
* Broadcast Action: A sticky broadcast for USB state change events when in device mode.
*
* This is a sticky broadcast for clients that includes USB connected/disconnected state,
@@ -104,7 +101,7 @@
* MIDI function is enabled
* </ul>
* If the sticky intent has not been found, that indicates USB is disconnected,
- * USB is not configued, MTP function is enabled, and all the other functions are disabled.
+ * USB is not configured, MTP function is enabled, and all the other functions are disabled.
*
* @hide
*/
@@ -124,7 +121,7 @@
public static final String ACTION_USB_PORT_CHANGED =
"android.hardware.usb.action.USB_PORT_CHANGED";
- /**
+ /**
* Broadcast Action: A broadcast for USB compliance warning changes.
*
* This intent is sent when a port partner's
@@ -137,7 +134,7 @@
public static final String ACTION_USB_PORT_COMPLIANCE_CHANGED =
"android.hardware.usb.action.USB_PORT_COMPLIANCE_CHANGED";
- /**
+ /**
* Activity intent sent when user attaches a USB device.
*
* This intent is sent when a USB device is attached to the USB bus when in host mode.
@@ -150,7 +147,7 @@
public static final String ACTION_USB_DEVICE_ATTACHED =
"android.hardware.usb.action.USB_DEVICE_ATTACHED";
- /**
+ /**
* Broadcast Action: A broadcast for USB device detached event.
*
* This intent is sent when a USB device is detached from the USB bus when in host mode.
@@ -163,7 +160,7 @@
public static final String ACTION_USB_DEVICE_DETACHED =
"android.hardware.usb.action.USB_DEVICE_DETACHED";
- /**
+ /**
* Activity intent sent when user attaches a USB accessory.
*
* <ul>
@@ -175,7 +172,7 @@
public static final String ACTION_USB_ACCESSORY_ATTACHED =
"android.hardware.usb.action.USB_ACCESSORY_ATTACHED";
- /**
+ /**
* Broadcast Action: A broadcast for USB accessory detached event.
*
* This intent is sent when a USB accessory is detached.
@@ -616,6 +613,7 @@
/**
* Code for the charging usb function. Passed into {@link #setCurrentFunctions(long)}
+ * Must be equal to {@link GadgetFunction#NONE}
* @hide
*/
@SystemApi
@@ -623,55 +621,63 @@
/**
* Code for the mtp usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
+ * Must be equal to {@link GadgetFunction#MTP}
* @hide
*/
@SystemApi
- public static final long FUNCTION_MTP = GadgetFunction.MTP;
+ public static final long FUNCTION_MTP = 1 << 2;
/**
* Code for the ptp usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
+ * Must be equal to {@link GadgetFunction#PTP}
* @hide
*/
@SystemApi
- public static final long FUNCTION_PTP = GadgetFunction.PTP;
+ public static final long FUNCTION_PTP = 1 << 4;
/**
* Code for the rndis usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
+ * Must be equal to {@link GadgetFunction#RNDIS}
* @hide
*/
@SystemApi
- public static final long FUNCTION_RNDIS = GadgetFunction.RNDIS;
+ public static final long FUNCTION_RNDIS = 1 << 5;
/**
* Code for the midi usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
+ * Must be equal to {@link GadgetFunction#MIDI}
* @hide
*/
@SystemApi
- public static final long FUNCTION_MIDI = GadgetFunction.MIDI;
+ public static final long FUNCTION_MIDI = 1 << 3;
/**
* Code for the accessory usb function.
+ * Must be equal to {@link GadgetFunction#ACCESSORY}
* @hide
*/
@SystemApi
- public static final long FUNCTION_ACCESSORY = GadgetFunction.ACCESSORY;
+ public static final long FUNCTION_ACCESSORY = 1 << 1;
/**
* Code for the audio source usb function.
+ * Must be equal to {@link GadgetFunction#AUDIO_SOURCE}
* @hide
*/
@SystemApi
- public static final long FUNCTION_AUDIO_SOURCE = GadgetFunction.AUDIO_SOURCE;
+ public static final long FUNCTION_AUDIO_SOURCE = 1 << 6;
/**
* Code for the adb usb function.
+ * Must be equal to {@link GadgetFunction#ADB}
* @hide
*/
@SystemApi
- public static final long FUNCTION_ADB = GadgetFunction.ADB;
+ public static final long FUNCTION_ADB = 1;
/**
* Code for the ncm source usb function.
+ * Must be equal to {@link GadgetFunction#NCM}
* @hide
*/
@SystemApi
@@ -998,7 +1004,7 @@
}
}
- /**
+ /**
* Requests temporary permission for the given package to access the device.
* This may result in a system dialog being displayed to the user
* if permission had not already been granted.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ff57003..925547d86 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -40,6 +40,7 @@
import android.app.NotificationManager;
import android.app.SearchManager;
import android.app.WallpaperManager;
+import android.app.tare.EconomyManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -14682,7 +14683,7 @@
*
* @hide
*/
- public static final int DEFAULT_ENABLE_TARE = 1;
+ public static final int DEFAULT_ENABLE_TARE = EconomyManager.DEFAULT_ENABLE_TARE_MODE;
/**
* Whether to enable the TARE AlarmManager economic policy or not.
@@ -14697,7 +14698,8 @@
*
* @hide
*/
- public static final int DEFAULT_ENABLE_TARE_ALARM_MANAGER = 0;
+ public static final int DEFAULT_ENABLE_TARE_ALARM_MANAGER =
+ EconomyManager.DEFAULT_ENABLE_POLICY_ALARM ? 1 : 0;
/**
* Settings for AlarmManager's TARE EconomicPolicy (list of its economic factors).
@@ -14721,7 +14723,8 @@
*
* @hide
*/
- public static final int DEFAULT_ENABLE_TARE_JOB_SCHEDULER = 0;
+ public static final int DEFAULT_ENABLE_TARE_JOB_SCHEDULER =
+ EconomyManager.DEFAULT_ENABLE_POLICY_JOB_SCHEDULER ? 1 : 0;
/**
* Settings for JobScheduler's TARE EconomicPolicy (list of its economic factors).
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 5c23c31..fedb098 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -222,6 +222,8 @@
int transform);
private static native void nativeSetDataSpace(long transactionObj, long nativeObject,
@DataSpace.NamedDataSpace int dataSpace);
+ private static native void nativeSetExtendedRangeBrightness(long transactionObj,
+ long nativeObject, float currentBufferRatio, float desiredRatio);
private static native void nativeSetDamageRegion(long transactionObj, long nativeObject,
Region region);
private static native void nativeSetDimmingEnabled(long transactionObj, long nativeObject,
@@ -3610,6 +3612,46 @@
}
/**
+ * Sets the desired extended range brightness for the layer. This only applies for layers
+ * whose dataspace has RANGE_EXTENDED.
+ *
+ * @param sc The layer whose extended range brightness is being specified
+ * @param currentBufferRatio The current sdr/hdr ratio of the current buffer. For example
+ * if the buffer was rendered with a target SDR whitepoint of
+ * 100 nits and a max display brightness of 200 nits, this should
+ * be set to 2.0f.
+ *
+ * Default value is 1.0f.
+ *
+ * Transfer functions that encode their own brightness ranges,
+ * such as HLG or PQ, should also set this to 1.0f and instead
+ * communicate extended content brightness information via
+ * metadata such as CTA861_3 or SMPTE2086.
+ *
+ * @param desiredRatio The desired sdr/hdr ratio. This can be used to communicate the max
+ * desired brightness range. This is similar to the "max luminance"
+ * value in other HDR metadata formats, but represented as a ratio of
+ * the target SDR whitepoint to the max display brightness. The system
+ * may not be able to, or may choose not to, deliver the
+ * requested range.
+ *
+ * If unspecified, the system will attempt to provide the best range
+ * it can for the given ambient conditions & device state. However,
+ * voluntarily reducing the requested range can help improve battery
+ * life as well as can improve quality by ensuring greater bit depth
+ * is allocated to the luminance range in use.
+ * @return this
+ * @hide
+ **/
+ public @NonNull Transaction setExtendedRangeBrightness(@NonNull SurfaceControl sc,
+ float currentBufferRatio, float desiredRatio) {
+ checkPreconditions(sc);
+ nativeSetExtendedRangeBrightness(mNativeObject, sc.mNativeObject, currentBufferRatio,
+ desiredRatio);
+ return this;
+ }
+
+ /**
* Sets the trusted overlay state on this SurfaceControl and it is inherited to all the
* children. The caller must hold the ACCESS_SURFACE_FLINGER permission.
* @hide
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6eb932e..84ed845 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -75,7 +75,6 @@
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
@@ -440,6 +439,7 @@
@NonNull Display mDisplay;
final DisplayManager mDisplayManager;
final String mBasePackageName;
+ final InputManager mInputManager;
final int[] mTmpLocation = new int[2];
@@ -968,6 +968,7 @@
// TODO(b/222696368): remove getSfInstance usage and use vsyncId for transactions
mChoreographer = Choreographer.getInstance();
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
+ mInputManager = context.getSystemService(InputManager.class);
mInsetsController = new InsetsController(new ViewRootInsetsControllerHost(this));
mHandwritingInitiator = new HandwritingInitiator(
mViewConfiguration,
@@ -5337,7 +5338,7 @@
Log.e(mTag, "No input channel to request Pointer Capture.");
return;
}
- InputManager.getInstance().requestPointerCapture(inputToken, enabled);
+ mInputManager.requestPointerCapture(inputToken, enabled);
}
private void handlePointerCaptureChanged(boolean hasCapture) {
@@ -6860,9 +6861,8 @@
if (event.getPointerCount() != 1) {
return;
}
- final boolean needsStylusPointerIcon =
- InputManager.getInstance().isStylusPointerIconEnabled()
- && event.isStylusPointer();
+ final boolean needsStylusPointerIcon = event.isStylusPointer()
+ && mInputManager.isStylusPointerIconEnabled();
if (needsStylusPointerIcon || event.isFromSource(InputDevice.SOURCE_MOUSE)) {
if (event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER
|| event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
@@ -6934,7 +6934,7 @@
PointerIcon pointerIcon = null;
- if (event.isStylusPointer() && InputManager.getInstance().isStylusPointerIconEnabled()) {
+ if (event.isStylusPointer() && mInputManager.isStylusPointerIconEnabled()) {
pointerIcon = mHandwritingInitiator.onResolvePointerIcon(mContext, event);
}
@@ -6949,14 +6949,14 @@
mPointerIconType = pointerType;
mCustomPointerIcon = null;
if (mPointerIconType != PointerIcon.TYPE_CUSTOM) {
- InputManager.getInstance().setPointerIconType(pointerType);
+ mInputManager.setPointerIconType(pointerType);
return true;
}
}
if (mPointerIconType == PointerIcon.TYPE_CUSTOM &&
!pointerIcon.equals(mCustomPointerIcon)) {
mCustomPointerIcon = pointerIcon;
- InputManager.getInstance().setCustomPointerIcon(mCustomPointerIcon);
+ mInputManager.setCustomPointerIcon(mCustomPointerIcon);
}
return true;
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 5144f3a..ee4b6c4 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1099,6 +1099,32 @@
"android.window.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE";
/**
+ * Activity level {@link android.content.pm.PackageManager.Property PackageManager
+ * .Property} for an app to inform the system that the activity should be excluded from the
+ * compatibility override for orientation set by the device manufacturer.
+ *
+ * <p>With this property set to {@code true} or unset, device manufacturers can override
+ * orientation for the activity using their discretion to improve display compatibility.
+ *
+ * <p>With this property set to {@code false}, device manufactured per-app override for
+ * orientation won't be applied.
+ *
+ * <p><b>Syntax:</b>
+ * <pre>
+ * <activity>
+ * <property
+ * android:name="android.window.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE"
+ * android:value="true|false"/>
+ * </activity>
+ * </pre>
+ *
+ * @hide
+ */
+ // TODO(b/263984287): Make this public API.
+ String PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE =
+ "android.window.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE";
+
+ /**
* @hide
*/
public static final String PARCEL_KEY_SHORTCUTS_ARRAY = "shortcuts_array";
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 4f7f8ba..b9373be 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -567,11 +567,6 @@
public static final String VOLUME_SEPARATE_NOTIFICATION = "volume_separate_notification";
/**
- * (boolean) Whether the clipboard overlay is enabled.
- */
- public static final String CLIPBOARD_OVERLAY_ENABLED = "clipboard_overlay_enabled";
-
- /**
* (boolean) Whether widget provider info would be saved to / loaded from system persistence
* layer as opposed to individual manifests in respective apps.
*/
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index ae45a0e..1557f9e 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -19,18 +19,18 @@
#include "android_media_AudioTrack.h"
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedUtfChars.h>
-#include "core_jni_helpers.h"
-
-#include <utils/Log.h>
+#include <android-base/macros.h>
+#include <android_os_Parcel.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
#include <media/AudioParameter.h>
#include <media/AudioSystem.h>
#include <media/AudioTrack.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include <utils/Log.h>
-#include <android-base/macros.h>
-#include <binder/MemoryHeapBase.h>
-#include <binder/MemoryBase.h>
+#include <cinttypes>
#include "android_media_AudioAttributes.h"
#include "android_media_AudioErrors.h"
@@ -41,8 +41,7 @@
#include "android_media_MediaMetricsJNI.h"
#include "android_media_PlaybackParams.h"
#include "android_media_VolumeShaper.h"
-
-#include <cinttypes>
+#include "core_jni_helpers.h"
// ----------------------------------------------------------------------------
@@ -245,9 +244,10 @@
jobject jaa, jintArray jSampleRate,
jint channelPositionMask, jint channelIndexMask,
jint audioFormat, jint buffSizeInBytes, jint memoryMode,
- jintArray jSession, jlong nativeAudioTrack,
- jboolean offload, jint encapsulationMode,
- jobject tunerConfiguration, jstring opPackageName) {
+ jintArray jSession, jobject jAttributionSource,
+ jlong nativeAudioTrack, jboolean offload,
+ jint encapsulationMode, jobject tunerConfiguration,
+ jstring opPackageName) {
ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d,"
" nativeAudioTrack=0x%" PRIX64 ", offload=%d encapsulationMode=%d tuner=%p",
jSampleRate, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes,
@@ -323,10 +323,9 @@
// create the native AudioTrack object
ScopedUtfChars opPackageNameStr(env, opPackageName);
- // TODO b/182469354: make consistent with AudioRecord
- AttributionSourceState attributionSource;
- attributionSource.packageName = std::string(opPackageNameStr.c_str());
- attributionSource.token = sp<BBinder>::make();
+
+ android::content::AttributionSourceState attributionSource;
+ attributionSource.readFromParcel(parcelForJavaObject(env, jAttributionSource));
lpTrack = sp<AudioTrack>::make(attributionSource);
// read the AudioAttributes values
@@ -382,7 +381,7 @@
offload ? AudioTrack::TRANSFER_SYNC_NOTIF_CALLBACK
: AudioTrack::TRANSFER_SYNC,
(offload || encapsulationMode) ? &offloadInfo : NULL,
- AttributionSourceState(), // default uid, pid values
+ attributionSource, // Passed from Java
paa.get());
break;
@@ -401,14 +400,14 @@
format, // word length, PCM
nativeChannelMask, frameCount, AUDIO_OUTPUT_FLAG_NONE,
lpJniStorage,
- 0, // notificationFrames == 0 since not using EVENT_MORE_DATA
- // to feed the AudioTrack
- iMem, // shared mem
- true, // thread can call Java
- sessionId, // audio session ID
+ 0, // notificationFrames == 0 since not using EVENT_MORE_DATA
+ // to feed the AudioTrack
+ iMem, // shared mem
+ true, // thread can call Java
+ sessionId, // audio session ID
AudioTrack::TRANSFER_SHARED,
- nullptr , // default offloadInfo
- AttributionSourceState(), // default uid, pid values
+ nullptr, // default offloadInfo
+ attributionSource, // Passed from Java
paa.get());
break;
}
@@ -1456,7 +1455,8 @@
{"native_pause", "()V", (void *)android_media_AudioTrack_pause},
{"native_flush", "()V", (void *)android_media_AudioTrack_flush},
{"native_setup",
- "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJZILjava/lang/Object;Ljava/lang/String;)I",
+ "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[ILandroid/os/Parcel;"
+ "JZILjava/lang/Object;Ljava/lang/String;)I",
(void *)android_media_AudioTrack_setup},
{"native_finalize", "()V", (void *)android_media_AudioTrack_finalize},
{"native_release", "()V", (void *)android_media_AudioTrack_release},
diff --git a/core/jni/android_os_PerformanceHintManager.cpp b/core/jni/android_os_PerformanceHintManager.cpp
index 0223b96..d8a2497 100644
--- a/core/jni/android_os_PerformanceHintManager.cpp
+++ b/core/jni/android_os_PerformanceHintManager.cpp
@@ -41,7 +41,7 @@
typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
typedef void (*APH_closeSession)(APerformanceHintSession* session);
typedef void (*APH_sendHint)(APerformanceHintSession*, int32_t);
-typedef void (*APH_setThreads)(APerformanceHintSession*, const int32_t*, size_t);
+typedef void (*APH_setThreads)(APerformanceHintSession*, const pid_t*, size_t);
typedef void (*APH_getThreadIds)(APerformanceHintSession*, int32_t* const, size_t* const);
bool gAPerformanceHintBindingInitialized = false;
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 34589b7..225ed2c 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -579,6 +579,14 @@
transaction->setDataspace(ctrl, dataspace);
}
+static void nativeSetExtendedRangeBrightness(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, float currentBufferRatio,
+ float desiredRatio) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+ transaction->setExtendedRangeBrightness(ctrl, currentBufferRatio, desiredRatio);
+}
+
static void nativeSetBlurRegions(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jobjectArray regions, jint regionsLength) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -2086,6 +2094,8 @@
{"nativeSetBufferTransform", "(JJI)V", (void*) nativeSetBufferTransform},
{"nativeSetDataSpace", "(JJI)V",
(void*)nativeSetDataSpace },
+ {"nativeSetExtendedRangeBrightness", "(JJFF)V",
+ (void*)nativeSetExtendedRangeBrightness },
{"nativeAddWindowInfosReportedListener", "(JLjava/lang/Runnable;)V",
(void*)nativeAddWindowInfosReportedListener },
{"nativeGetDisplayBrightnessSupport", "(Landroid/os/IBinder;)Z",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 07aefbd..7d69d56 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4153,7 +4153,7 @@
<p>Should only be requested by the System, should be required by
TileService declarations.-->
<permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature|recents" />
<!-- Allows SystemUI to request third party controls.
<p>Should only be requested by the System and required by
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index fa77c45..e242e20 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -435,6 +435,119 @@
This value can be overlaid at runtime by OverlayManager RROs. -->
<color name="system_neutral2_1000">#000000</color>
+ <!-- Colors used in Android system, from Material design system.
+ These values can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_primary_container_light">#D8E2FF</color>
+ <color name="system_on_primary_container_light">#001A41</color>
+ <color name="system_primary_light">#445E91</color>
+ <color name="system_on_primary_light">#FFFFFF</color>
+ <color name="system_secondary_container_light">#DBE2F9</color>
+ <color name="system_on_secondary_container_light">#141B2C</color>
+ <color name="system_secondary_light">#575E71</color>
+ <color name="system_on_secondary_light">#FFFFFF</color>
+ <color name="system_tertiary_container_light">#FBD7FC</color>
+ <color name="system_on_tertiary_container_light">#29132D</color>
+ <color name="system_tertiary_light">#715573</color>
+ <color name="system_on_tertiary_light">#FFFFFF</color>
+ <color name="system_background_light">#FAF9FD</color>
+ <color name="system_on_background_light">#1B1B1F</color>
+ <color name="system_surface_light">#FAF9FD</color>
+ <color name="system_on_surface_light">#1B1B1F</color>
+ <color name="system_surface_container_low_light">#F5F3F7</color>
+ <color name="system_surface_container_lowest_light">#FFFFFF</color>
+ <color name="system_surface_container_light">#EFEDF1</color>
+ <color name="system_surface_container_high_light">#E9E7EC</color>
+ <color name="system_surface_container_highest_light">#E3E2E6</color>
+ <color name="system_surface_bright_light">#FAF9FD</color>
+ <color name="system_surface_dim_light">#DBD9DD</color>
+ <color name="system_surface_variant_light">#E1E2EC</color>
+ <color name="system_on_surface_variant_light">#44474F</color>
+ <color name="system_outline_light">#72747D</color>
+ <color name="system_error_light">#C00003</color>
+ <color name="system_on_error_light">#FFFFFF</color>
+ <color name="system_error_container_light">#FFDAD5</color>
+ <color name="system_on_error_container_light">#410000</color>
+ <color name="system_primary_fixed_light">#D8E2FF</color>
+ <color name="system_primary_fixed_darker_light">#ADC6FF</color>
+ <color name="system_on_primary_fixed_light">#001A41</color>
+ <color name="system_on_primary_fixed_variant_light">#2B4678</color>
+ <color name="system_secondary_fixed_light">#DBE2F9</color>
+ <color name="system_secondary_fixed_darker_light">#BFC6DC</color>
+ <color name="system_on_secondary_fixed_light">#141B2C</color>
+ <color name="system_on_secondary_fixed_variant_light">#3F4759</color>
+ <color name="system_tertiary_fixed_light">#FBD7FC</color>
+ <color name="system_tertiary_fixed_darker_light">#DEBCDF</color>
+ <color name="system_on_tertiary_fixed_light">#29132D</color>
+ <color name="system_on_tertiary_fixed_variant_light">#583E5B</color>
+ <color name="system_control_activated_light">#D8E2FF</color>
+ <color name="system_control_normal_light">#44474F</color>
+ <color name="system_control_highlight_light">#1F000000</color>
+ <color name="system_text_primary_inverse_light">#E3E2E6</color>
+ <color name="system_text_secondary_and_tertiary_inverse_light">#C4C6D0</color>
+ <color name="system_text_primary_inverse_disable_only_light">#E3E2E6</color>
+ <color name="system_text_secondary_and_tertiary_inverse_disabled_light">#E3E2E6</color>
+ <color name="system_text_hint_inverse_light">#E3E2E6</color>
+ <color name="system_palette_key_color_primary_light">#5D77AC</color>
+ <color name="system_palette_key_color_secondary_light">#6C7488</color>
+ <color name="system_palette_key_color_tertiary_light">#907292</color>
+ <color name="system_palette_key_color_neutral_light">#838387</color>
+ <color name="system_palette_key_color_neutral_variant_light">#777982</color>
+ <color name="system_primary_container_dark">#2B4678</color>
+ <color name="system_on_primary_container_dark">#D8E2FF</color>
+ <color name="system_primary_dark">#ADC6FF</color>
+ <color name="system_on_primary_dark">#102F60</color>
+ <color name="system_secondary_container_dark">#3F4759</color>
+ <color name="system_on_secondary_container_dark">#DBE2F9</color>
+ <color name="system_secondary_dark">#BFC6DC</color>
+ <color name="system_on_secondary_dark">#293041</color>
+ <color name="system_tertiary_container_dark">#583E5B</color>
+ <color name="system_on_tertiary_container_dark">#FBD7FC</color>
+ <color name="system_tertiary_dark">#DEBCDF</color>
+ <color name="system_on_tertiary_dark">#402843</color>
+ <color name="system_background_dark">#121316</color>
+ <color name="system_on_background_dark">#E3E2E6</color>
+ <color name="system_surface_dark">#121316</color>
+ <color name="system_on_surface_dark">#E3E2E6</color>
+ <color name="system_surface_container_low_dark">#1B1B1F</color>
+ <color name="system_surface_container_lowest_dark">#0D0E11</color>
+ <color name="system_surface_container_dark">#1F1F23</color>
+ <color name="system_surface_container_high_dark">#292A2D</color>
+ <color name="system_surface_container_highest_dark">#343538</color>
+ <color name="system_surface_bright_dark">#38393C</color>
+ <color name="system_surface_dim_dark">#121316</color>
+ <color name="system_surface_variant_dark">#44474F</color>
+ <color name="system_on_surface_variant_dark">#C4C6D0</color>
+ <color name="system_outline_dark">#72747D</color>
+ <color name="system_error_dark">#FFB4A8</color>
+ <color name="system_on_error_dark">#690001</color>
+ <color name="system_error_container_dark">#930001</color>
+ <color name="system_on_error_container_dark">#FFDAD5</color>
+ <color name="system_primary_fixed_dark">#D8E2FF</color>
+ <color name="system_primary_fixeder_dark">#ADC6FF</color>
+ <color name="system_on_primary_fixed_dark">#001A41</color>
+ <color name="system_on_primary_fixed_variant_dark">#2B4678</color>
+ <color name="system_secondary_fixed_dark">#DBE2F9</color>
+ <color name="system_secondary_fixeder_dark">#BFC6DC</color>
+ <color name="system_on_secondary_fixed_dark">#141B2C</color>
+ <color name="system_on_secondary_fixed_variant_dark">#3F4759</color>
+ <color name="system_tertiary_fixed_dark">#FBD7FC</color>
+ <color name="system_tertiary_fixeder_dark">#DEBCDF</color>
+ <color name="system_on_tertiary_fixed_dark">#29132D</color>
+ <color name="system_on_tertiary_fixed_variant_dark">#583E5B</color>
+ <color name="system_control_activated_dark">#2B4678</color>
+ <color name="system_control_normal_dark">#C4C6D0</color>
+ <color name="system_control_highlight_dark">#33FFFFFF</color>
+ <color name="system_text_primary_inverse_dark">#1B1B1F</color>
+ <color name="system_text_secondary_and_tertiary_inverse_dark">#44474F</color>
+ <color name="system_text_primary_inverse_disable_only_dark">#1B1B1F</color>
+ <color name="system_text_secondary_and_tertiary_inverse_disabled_dark">#1B1B1F</color>
+ <color name="system_text_hint_inverse_dark">#1B1B1F</color>
+ <color name="system_palette_key_color_primary_dark">#5D77AC</color>
+ <color name="system_palette_key_color_secondary_dark">#6C7488</color>
+ <color name="system_palette_key_color_tertiary_dark">#907292</color>
+ <color name="system_palette_key_color_neutral_dark">#838387</color>
+ <color name="system_palette_key_color_neutral_variant_dark">#777982</color>
+
<!-- Accessibility shortcut icon background color -->
<color name="accessibility_feature_background">#5F6368</color> <!-- Google grey 700 -->
<color name="accessibility_magnification_background">#F50D60</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f544feb..602ee55 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -642,6 +642,16 @@
The default is false. -->
<bool name="config_lidControlsSleep">false</bool>
+ <!-- The device states (supplied by DeviceStateManager) that should be treated as open by the
+ device fold controller. Default is empty. -->
+ <integer-array name="config_openDeviceStates">
+ <!-- Example:
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ -->
+ </integer-array>
+
<!-- The device states (supplied by DeviceStateManager) that should be treated as folded by the
display fold controller. Default is empty. -->
<integer-array name="config_foldedDeviceStates">
@@ -662,6 +672,16 @@
-->
</integer-array>
+ <!-- The device states (supplied by DeviceStateManager) that should be treated as a rear display
+ state. Default is empty. -->
+ <integer-array name="config_rearDisplayDeviceStates">
+ <!-- Example:
+ <item>0</item>
+ <item>1</item>
+ <item>2</item>
+ -->
+ </integer-array>
+
<!-- Indicates whether the window manager reacts to half-fold device states by overriding
rotation. -->
<bool name="config_windowManagerHalfFoldAutoRotateOverride">false</bool>
@@ -5820,7 +5840,6 @@
- config_roundedCornerDrawableArray (config in SystemUI resource)
- config_roundedCornerTopDrawableArray (config in SystemUI resource)
- config_roundedCornerBottomDrawableArray (config in SystemUI resource)
- - config_displayUsiVersionArray
Leave this array empty for single display device and the system will load the default main
built-in related configs.
@@ -6189,21 +6208,4 @@
trusted certificate using the SHA-256 digest algorithm. -->
<string-array name="config_healthConnectMigrationKnownSigners">
</string-array>
-
- <!-- The Universal Stylus Initiative (USI) protocol version supported by each display.
- (@see https://universalstylus.org/).
-
- The i-th value in this array corresponds to the supported USI version of the i-th display
- listed in config_displayUniqueIdArray. On a single-display device, the
- config_displayUniqueIdArray may be empty, in which case the only value in this array should
- be the USI version for the main built-in display.
-
- If the display does not support USI, the version value should be an empty string. If the
- display supports USI, the version must be in the following format:
- "<major-version>.<minor-version>"
-
- For example, "", "1.0", and "2.0" are valid values. -->
- <string-array name="config_displayUsiVersionArray" translatable="false">
- <item>""</item>
- </string-array>
</resources>
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index 58b8601..f7ed38c 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -154,6 +154,116 @@
</staging-public-group>
<staging-public-group type="color" first-id="0x01c90000">
+ <public name="system_primary_container_light" />
+ <public name="system_on_primary_container_light" />
+ <public name="system_primary_light" />
+ <public name="system_on_primary_light" />
+ <public name="system_secondary_container_light" />
+ <public name="system_on_secondary_container_light" />
+ <public name="system_secondary_light" />
+ <public name="system_on_secondary_light" />
+ <public name="system_tertiary_container_light" />
+ <public name="system_on_tertiary_container_light" />
+ <public name="system_tertiary_light" />
+ <public name="system_on_tertiary_light" />
+ <public name="system_background_light" />
+ <public name="system_on_background_light" />
+ <public name="system_surface_light" />
+ <public name="system_on_surface_light" />
+ <public name="system_surface_container_low_light" />
+ <public name="system_surface_container_lowest_light" />
+ <public name="system_surface_container_light" />
+ <public name="system_surface_container_high_light" />
+ <public name="system_surface_container_highest_light" />
+ <public name="system_surface_bright_light" />
+ <public name="system_surface_dim_light" />
+ <public name="system_surface_variant_light" />
+ <public name="system_on_surface_variant_light" />
+ <public name="system_outline_light" />
+ <public name="system_error_light" />
+ <public name="system_on_error_light" />
+ <public name="system_error_container_light" />
+ <public name="system_on_error_container_light" />
+ <public name="system_primary_fixed_light" />
+ <public name="system_primary_fixed_darker_light" />
+ <public name="system_on_primary_fixed_light" />
+ <public name="system_on_primary_fixed_variant_light" />
+ <public name="system_secondary_fixed_light" />
+ <public name="system_secondary_fixed_darker_light" />
+ <public name="system_on_secondary_fixed_light" />
+ <public name="system_on_secondary_fixed_variant_light" />
+ <public name="system_tertiary_fixed_light" />
+ <public name="system_tertiary_fixed_darker_light" />
+ <public name="system_on_tertiary_fixed_light" />
+ <public name="system_on_tertiary_fixed_variant_light" />
+ <public name="system_control_activated_light" />
+ <public name="system_control_normal_light" />
+ <public name="system_control_highlight_light" />
+ <public name="system_text_primary_inverse_light" />
+ <public name="system_text_secondary_and_tertiary_inverse_light" />
+ <public name="system_text_primary_inverse_disable_only_light" />
+ <public name="system_text_secondary_and_tertiary_inverse_disabled_light" />
+ <public name="system_text_hint_inverse_light" />
+ <public name="system_palette_key_color_primary_light" />
+ <public name="system_palette_key_color_secondary_light" />
+ <public name="system_palette_key_color_tertiary_light" />
+ <public name="system_palette_key_color_neutral_light" />
+ <public name="system_palette_key_color_neutral_variant_light" />
+ <public name="system_primary_container_dark"/>
+ <public name="system_on_primary_container_dark"/>
+ <public name="system_primary_dark"/>
+ <public name="system_on_primary_dark"/>
+ <public name="system_secondary_container_dark"/>
+ <public name="system_on_secondary_container_dark"/>
+ <public name="system_secondary_dark"/>
+ <public name="system_on_secondary_dark"/>
+ <public name="system_tertiary_container_dark"/>
+ <public name="system_on_tertiary_container_dark"/>
+ <public name="system_tertiary_dark"/>
+ <public name="system_on_tertiary_dark"/>
+ <public name="system_background_dark"/>
+ <public name="system_on_background_dark"/>
+ <public name="system_surface_dark"/>
+ <public name="system_on_surface_dark"/>
+ <public name="system_surface_container_low_dark"/>
+ <public name="system_surface_container_lowest_dark"/>
+ <public name="system_surface_container_dark"/>
+ <public name="system_surface_container_high_dark"/>
+ <public name="system_surface_container_highest_dark"/>
+ <public name="system_surface_bright_dark"/>
+ <public name="system_surface_dim_dark"/>
+ <public name="system_surface_variant_dark"/>
+ <public name="system_on_surface_variant_dark"/>
+ <public name="system_outline_dark"/>
+ <public name="system_error_dark"/>
+ <public name="system_on_error_dark"/>
+ <public name="system_error_container_dark"/>
+ <public name="system_on_error_container_dark"/>
+ <public name="system_primary_fixed_dark"/>
+ <public name="system_primary_fixeder_dark"/>
+ <public name="system_on_primary_fixed_dark"/>
+ <public name="system_on_primary_fixed_variant_dark"/>
+ <public name="system_secondary_fixed_dark"/>
+ <public name="system_secondary_fixeder_dark"/>
+ <public name="system_on_secondary_fixed_dark"/>
+ <public name="system_on_secondary_fixed_variant_dark"/>
+ <public name="system_tertiary_fixed_dark"/>
+ <public name="system_tertiary_fixeder_dark"/>
+ <public name="system_on_tertiary_fixed_dark"/>
+ <public name="system_on_tertiary_fixed_variant_dark"/>
+ <public name="system_control_activated_dark"/>
+ <public name="system_control_normal_dark"/>
+ <public name="system_control_highlight_dark"/>
+ <public name="system_text_primary_inverse_dark"/>
+ <public name="system_text_secondary_and_tertiary_inverse_dark"/>
+ <public name="system_text_primary_inverse_disable_only_dark"/>
+ <public name="system_text_secondary_and_tertiary_inverse_disabled_dark"/>
+ <public name="system_text_hint_inverse_dark"/>
+ <public name="system_palette_key_color_primary_dark"/>
+ <public name="system_palette_key_color_secondary_dark"/>
+ <public name="system_palette_key_color_tertiary_dark"/>
+ <public name="system_palette_key_color_neutral_dark"/>
+ <public name="system_palette_key_color_neutral_variant_dark"/>
</staging-public-group>
<staging-public-group type="array" first-id="0x01c80000">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index fa8ba9d..e330ee3 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5024,6 +5024,14 @@
<!-- Cling help message confirmation button when hiding the navigation bar entering immersive mode [CHAR LIMIT=30] -->
<string name="immersive_cling_positive">Got it</string>
+ <!-- Text on a toast shown after the system rotates the screen for camera app
+ compatibility. [CHAR LIMIT=NONE] -->
+ <string name="display_rotation_camera_compat_toast_after_rotation">Rotate for a better view</string>
+
+ <!-- Text on a toast shown when a camera view is started within the app that may not be able
+ to display the camera preview correctly while in split screen. [CHAR LIMIT=NONE] -->
+ <string name="display_rotation_camera_compat_toast_in_split_screen">Exit split screen for a better view</string>
+
<!-- Label for button to confirm chosen date or time [CHAR LIMIT=30] -->
<string name="done_label">Done</string>
<!--
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 9dc7835..a54e242 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3960,8 +3960,10 @@
<java-symbol type="integer" name="config_maxScanTasksForHomeVisibility" />
<!-- For Foldables -->
+ <java-symbol type="array" name="config_openDeviceStates" />
<java-symbol type="array" name="config_foldedDeviceStates" />
<java-symbol type="array" name="config_halfFoldedDeviceStates" />
+ <java-symbol type="array" name="config_rearDisplayDeviceStates" />
<java-symbol type="bool" name="config_windowManagerHalfFoldAutoRotateOverride" />
<java-symbol type="array" name="config_deviceStatesOnWhichToWakeUp" />
<java-symbol type="array" name="config_deviceStatesOnWhichToSleep" />
@@ -4781,7 +4783,6 @@
<java-symbol type="array" name="config_mainBuiltInDisplayWaterfallCutout" />
<java-symbol type="array" name="config_secondaryBuiltInDisplayWaterfallCutout" />
<java-symbol type="array" name="config_waterfallCutoutArray" />
- <java-symbol type="array" name="config_displayUsiVersionArray" />
<java-symbol type="fraction" name="global_actions_vertical_padding_percentage" />
<java-symbol type="fraction" name="global_actions_horizontal_padding_percentage" />
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index 3afb419..4485044 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -155,23 +155,12 @@
skcms_TransferFunction fn;
if (!colorSpace->isNumericalTransferFn(&fn)) {
- // pq with the default white point
- auto rec2020PQ = SkColorSpace::MakeRGB(GetPQSkTransferFunction(), SkNamedGamut::kRec2020);
- if (SkColorSpace::Equals(colorSpace, rec2020PQ.get())) {
+ auto res = skcms_TransferFunction_getType(&fn);
+ if (res == skcms_TFType_PQish) {
return HAL_DATASPACE_BT2020_PQ;
}
- // standard PQ
- rec2020PQ = SkColorSpace::MakeRGB(SkNamedTransferFn::kPQ, SkNamedGamut::kRec2020);
- if (SkColorSpace::Equals(colorSpace, rec2020PQ.get())) {
- return HAL_DATASPACE_BT2020_PQ;
- }
- // HLG
- const auto hlgFn = GetHLGScaleTransferFunction();
- if (hlgFn.has_value()) {
- auto rec2020HLG = SkColorSpace::MakeRGB(hlgFn.value(), SkNamedGamut::kRec2020);
- if (SkColorSpace::Equals(colorSpace, rec2020HLG.get())) {
- return static_cast<android_dataspace>(HAL_DATASPACE_BT2020_HLG);
- }
+ if (res == skcms_TFType_HLGish) {
+ return static_cast<android_dataspace>(HAL_DATASPACE_BT2020_HLG);
}
LOG_ALWAYS_FATAL("Only select non-numerical transfer functions are supported");
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index a4d5606..0636451 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -8329,7 +8329,8 @@
Objects.requireNonNull(device);
try {
if (device.getId() == 0) {
- throw new IllegalArgumentException("In valid device: " + device);
+ Log.w(TAG, "setCommunicationDevice: device not found: " + device);
+ return false;
}
return getService().setCommunicationDevice(mICallBack, device.getId());
} catch (RemoteException e) {
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 50749e7..948fef4 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -28,6 +28,8 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.AttributionSource;
+import android.content.AttributionSource.ScopedParcelState;
import android.content.Context;
import android.media.audiopolicy.AudioMix;
import android.media.audiopolicy.AudioMixingRule;
@@ -39,6 +41,7 @@
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
+import android.os.Parcel;
import android.os.PersistableBundle;
import android.util.ArrayMap;
import android.util.Log;
@@ -822,15 +825,20 @@
int[] session = new int[1];
session[0] = resolvePlaybackSessionId(context, sessionId);
+ AttributionSource attributionSource = context == null
+ ? AttributionSource.myAttributionSource() : context.getAttributionSource();
+
// native initialization
- int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
- sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
- mNativeBufferSizeInBytes, mDataLoadMode, session, 0 /*nativeTrackInJavaObj*/,
- offload, encapsulationMode, tunerConfiguration,
- getCurrentOpPackageName());
- if (initResult != SUCCESS) {
- loge("Error code "+initResult+" when initializing AudioTrack.");
- return; // with mState == STATE_UNINITIALIZED
+ try (ScopedParcelState attributionSourceState = attributionSource.asScopedParcelState()) {
+ int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
+ sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
+ mNativeBufferSizeInBytes, mDataLoadMode, session,
+ attributionSourceState.getParcel(), 0 /*nativeTrackInJavaObj*/, offload,
+ encapsulationMode, tunerConfiguration, getCurrentOpPackageName());
+ if (initResult != SUCCESS) {
+ loge("Error code " + initResult + " when initializing AudioTrack.");
+ return; // with mState == STATE_UNINITIALIZED
+ }
}
mSampleRate = sampleRate[0];
@@ -902,23 +910,27 @@
// *Native* AudioTrack, so the attributes parameters to native_setup() are ignored.
int[] session = { 0 };
int[] rates = { 0 };
- int initResult = native_setup(new WeakReference<AudioTrack>(this),
- null /*mAttributes - NA*/,
- rates /*sampleRate - NA*/,
- 0 /*mChannelMask - NA*/,
- 0 /*mChannelIndexMask - NA*/,
- 0 /*mAudioFormat - NA*/,
- 0 /*mNativeBufferSizeInBytes - NA*/,
- 0 /*mDataLoadMode - NA*/,
- session,
- nativeTrackInJavaObj,
- false /*offload*/,
- ENCAPSULATION_MODE_NONE,
- null /* tunerConfiguration */,
- "" /* opPackagename */);
- if (initResult != SUCCESS) {
- loge("Error code "+initResult+" when initializing AudioTrack.");
- return; // with mState == STATE_UNINITIALIZED
+ try (ScopedParcelState attributionSourceState =
+ AttributionSource.myAttributionSource().asScopedParcelState()) {
+ int initResult = native_setup(new WeakReference<AudioTrack>(this),
+ null /*mAttributes - NA*/,
+ rates /*sampleRate - NA*/,
+ 0 /*mChannelMask - NA*/,
+ 0 /*mChannelIndexMask - NA*/,
+ 0 /*mAudioFormat - NA*/,
+ 0 /*mNativeBufferSizeInBytes - NA*/,
+ 0 /*mDataLoadMode - NA*/,
+ session,
+ attributionSourceState.getParcel(),
+ nativeTrackInJavaObj,
+ false /*offload*/,
+ ENCAPSULATION_MODE_NONE,
+ null /* tunerConfiguration */,
+ "" /* opPackagename */);
+ if (initResult != SUCCESS) {
+ loge("Error code " + initResult + " when initializing AudioTrack.");
+ return; // with mState == STATE_UNINITIALIZED
+ }
}
mSessionId = session[0];
@@ -4371,9 +4383,9 @@
private native final int native_setup(Object /*WeakReference<AudioTrack>*/ audiotrack_this,
Object /*AudioAttributes*/ attributes,
int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
- int buffSizeInBytes, int mode, int[] sessionId, long nativeAudioTrack,
- boolean offload, int encapsulationMode, Object tunerConfiguration,
- @NonNull String opPackageName);
+ int buffSizeInBytes, int mode, int[] sessionId, @NonNull Parcel attributionSource,
+ long nativeAudioTrack, boolean offload, int encapsulationMode,
+ Object tunerConfiguration, @NonNull String opPackageName);
private native final void native_finalize();
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 681d76a..b70818d 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -1021,9 +1021,10 @@
static jbyteArray android_media_MediaDrm_getSupportedCryptoSchemesNative(JNIEnv *env) {
sp<IDrm> drm = android::DrmUtils::MakeDrm();
+ if (drm == NULL) return env->NewByteArray(0);
+
std::vector<uint8_t> bv;
drm->getSupportedSchemes(bv);
-
jbyteArray jUuidBytes = env->NewByteArray(bv.size());
env->SetByteArrayRegion(jUuidBytes, 0, bv.size(), reinterpret_cast<const jbyte *>(bv.data()));
return jUuidBytes;
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
index dfbd7b5..27666caa 100644
--- a/native/android/performance_hint.cpp
+++ b/native/android/performance_hint.cpp
@@ -339,7 +339,7 @@
return reinterpret_cast<APerformanceHintSession*>(session)->sendHint(hint);
}
-int APerformanceHint_setThreads(APerformanceHintSession* session, const int32_t* threadIds,
+int APerformanceHint_setThreads(APerformanceHintSession* session, const pid_t* threadIds,
size_t size) {
if (session == nullptr) {
return EINVAL;
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index 0761b64..a48cd2b 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -55,422 +55,457 @@
// Consider repo per screen, similar to view model?
class CredentialManagerRepo(
- private val context: Context,
- intent: Intent,
+ private val context: Context,
+ intent: Intent,
) {
- val requestInfo: RequestInfo
- private val providerEnabledList: List<ProviderData>
- private val providerDisabledList: List<DisabledProviderData>?
- // TODO: require non-null.
- val resultReceiver: ResultReceiver?
+ val requestInfo: RequestInfo
+ private val providerEnabledList: List<ProviderData>
+ private val providerDisabledList: List<DisabledProviderData>?
- init {
- requestInfo = intent.extras?.getParcelable(
- RequestInfo.EXTRA_REQUEST_INFO,
- RequestInfo::class.java
- ) ?: testCreatePasskeyRequestInfo()
+ // TODO: require non-null.
+ val resultReceiver: ResultReceiver?
- providerEnabledList = when (requestInfo.type) {
- RequestInfo.TYPE_CREATE ->
- intent.extras?.getParcelableArrayList(
- ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST,
- CreateCredentialProviderData::class.java
- ) ?: testCreateCredentialEnabledProviderList()
- RequestInfo.TYPE_GET ->
- intent.extras?.getParcelableArrayList(
- ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST,
- GetCredentialProviderData::class.java
- ) ?: testGetCredentialProviderList()
- else -> {
- // TODO: fail gracefully
- throw IllegalStateException("Unrecognized request type: ${requestInfo.type}")
- }
+ init {
+ requestInfo = intent.extras?.getParcelable(
+ RequestInfo.EXTRA_REQUEST_INFO,
+ RequestInfo::class.java
+ ) ?: testCreatePasskeyRequestInfo()
+
+ providerEnabledList = when (requestInfo.type) {
+ RequestInfo.TYPE_CREATE ->
+ intent.extras?.getParcelableArrayList(
+ ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST,
+ CreateCredentialProviderData::class.java
+ ) ?: testCreateCredentialEnabledProviderList()
+ RequestInfo.TYPE_GET ->
+ intent.extras?.getParcelableArrayList(
+ ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST,
+ GetCredentialProviderData::class.java
+ ) ?: testGetCredentialProviderList()
+ else -> {
+ // TODO: fail gracefully
+ throw IllegalStateException("Unrecognized request type: ${requestInfo.type}")
+ }
+ }
+
+ providerDisabledList =
+ intent.extras?.getParcelableArrayList(
+ ProviderData.EXTRA_DISABLED_PROVIDER_DATA_LIST,
+ DisabledProviderData::class.java
+ ) ?: testDisabledProviderList()
+
+ resultReceiver = intent.getParcelableExtra(
+ Constants.EXTRA_RESULT_RECEIVER,
+ ResultReceiver::class.java
+ )
}
- providerDisabledList =
- intent.extras?.getParcelableArrayList(
- ProviderData.EXTRA_DISABLED_PROVIDER_DATA_LIST,
- DisabledProviderData::class.java
- ) ?: testDisabledProviderList()
+ // The dialog is canceled by the user.
+ fun onUserCancel() {
+ onCancel(BaseDialogResult.RESULT_CODE_DIALOG_USER_CANCELED)
+ }
- resultReceiver = intent.getParcelableExtra(
- Constants.EXTRA_RESULT_RECEIVER,
- ResultReceiver::class.java
- )
- }
+ // The dialog is canceled because we launched into settings.
+ fun onSettingLaunchCancel() {
+ onCancel(BaseDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION)
+ }
- // The dialog is canceled by the user.
- fun onUserCancel() {
- onCancel(BaseDialogResult.RESULT_CODE_DIALOG_USER_CANCELED)
- }
+ fun onParsingFailureCancel() {
+ onCancel(BaseDialogResult.RESULT_CODE_DATA_PARSING_FAILURE)
+ }
- // The dialog is canceled because we launched into settings.
- fun onSettingLaunchCancel() {
- onCancel(BaseDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION)
- }
+ fun onCancel(cancelCode: Int) {
+ val resultData = Bundle()
+ BaseDialogResult.addToBundle(BaseDialogResult(requestInfo.token), resultData)
+ resultReceiver?.send(cancelCode, resultData)
+ }
- private fun onCancel(cancelCode: Int) {
- val resultData = Bundle()
- BaseDialogResult.addToBundle(BaseDialogResult(requestInfo.token), resultData)
- resultReceiver?.send(cancelCode, resultData)
- }
+ fun onOptionSelected(
+ providerId: String,
+ entryKey: String,
+ entrySubkey: String,
+ resultCode: Int? = null,
+ resultData: Intent? = null,
+ ) {
+ val userSelectionDialogResult = UserSelectionDialogResult(
+ requestInfo.token,
+ providerId,
+ entryKey,
+ entrySubkey,
+ if (resultCode != null) ProviderPendingIntentResponse(resultCode, resultData) else null
+ )
+ val resultData = Bundle()
+ UserSelectionDialogResult.addToBundle(userSelectionDialogResult, resultData)
+ resultReceiver?.send(
+ BaseDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION,
+ resultData
+ )
+ }
- fun onOptionSelected(
- providerId: String,
- entryKey: String,
- entrySubkey: String,
- resultCode: Int? = null,
- resultData: Intent? = null,
- ) {
- val userSelectionDialogResult = UserSelectionDialogResult(
- requestInfo.token,
- providerId,
- entryKey,
- entrySubkey,
- if (resultCode != null) ProviderPendingIntentResponse(resultCode, resultData) else null
- )
- val resultData = Bundle()
- UserSelectionDialogResult.addToBundle(userSelectionDialogResult, resultData)
- resultReceiver?.send(BaseDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION, resultData)
- }
+ fun getCredentialInitialUiState(): GetCredentialUiState? {
+ val providerEnabledList = GetFlowUtils.toProviderList(
+ // TODO: handle runtime cast error
+ providerEnabledList as List<GetCredentialProviderData>, context
+ )
+ val requestDisplayInfo = GetFlowUtils.toRequestDisplayInfo(requestInfo, context)
+ return GetCredentialUiState(
+ providerEnabledList,
+ requestDisplayInfo ?: return null,
+ )
+ }
- fun getCredentialInitialUiState(): GetCredentialUiState {
- val providerEnabledList = GetFlowUtils.toProviderList(
- // TODO: handle runtime cast error
- providerEnabledList as List<GetCredentialProviderData>, context)
- val requestDisplayInfo = GetFlowUtils.toRequestDisplayInfo(requestInfo, context)
- return GetCredentialUiState(
- providerEnabledList,
- requestDisplayInfo,
- )
- }
+ fun getCreateProviderEnableListInitialUiState(): List<EnabledProviderInfo> {
+ val providerEnabledList = CreateFlowUtils.toEnabledProviderList(
+ // Handle runtime cast error
+ providerEnabledList as List<CreateCredentialProviderData>, context
+ )
+ return providerEnabledList
+ }
- fun getCreateProviderEnableListInitialUiState(): List<EnabledProviderInfo> {
- val providerEnabledList = CreateFlowUtils.toEnabledProviderList(
- // Handle runtime cast error
- providerEnabledList as List<CreateCredentialProviderData>, context)
- return providerEnabledList
- }
+ fun getCreateProviderDisableListInitialUiState(): List<DisabledProviderInfo> {
+ return CreateFlowUtils.toDisabledProviderList(
+ // Handle runtime cast error
+ providerDisabledList, context
+ )
+ }
- fun getCreateProviderDisableListInitialUiState(): List<DisabledProviderInfo>? {
- return CreateFlowUtils.toDisabledProviderList(
- // Handle runtime cast error
- providerDisabledList, context)
- }
+ fun getCreateRequestDisplayInfoInitialUiState(): RequestDisplayInfo? {
+ return CreateFlowUtils.toRequestDisplayInfo(requestInfo, context)
+ }
- fun getCreateRequestDisplayInfoInitialUiState(): RequestDisplayInfo {
- return CreateFlowUtils.toRequestDisplayInfo(requestInfo, context)
- }
+ // TODO: below are prototype functionalities. To be removed for productionization.
+ private fun testCreateCredentialEnabledProviderList(): List<CreateCredentialProviderData> {
+ return listOf(
+ CreateCredentialProviderData
+ .Builder("io.enpass.app")
+ .setSaveEntries(
+ listOf<Entry>(
+ newCreateEntry(
+ "key1", "subkey-1", "elisa.beckett@gmail.com",
+ 20, 7, 27, 10L,
+ "Optional footer description"
+ ),
+ newCreateEntry(
+ "key1", "subkey-2", "elisa.work@google.com",
+ 20, 7, 27, 12L,
+ null
+ ),
+ )
+ )
+ .setRemoteEntry(
+ newRemoteEntry("key2", "subkey-1")
+ )
+ .build(),
+ CreateCredentialProviderData
+ .Builder("com.dashlane")
+ .setSaveEntries(
+ listOf<Entry>(
+ newCreateEntry(
+ "key1", "subkey-3", "elisa.beckett@dashlane.com",
+ 20, 7, 27, 11L,
+ null
+ ),
+ newCreateEntry(
+ "key1", "subkey-4", "elisa.work@dashlane.com",
+ 20, 7, 27, 14L,
+ null
+ ),
+ )
+ )
+ .build(),
+ )
+ }
- // TODO: below are prototype functionalities. To be removed for productionization.
- private fun testCreateCredentialEnabledProviderList(): List<CreateCredentialProviderData> {
- return listOf(
- CreateCredentialProviderData
- .Builder("io.enpass.app")
- .setSaveEntries(
- listOf<Entry>(
- newCreateEntry("key1", "subkey-1", "elisa.beckett@gmail.com",
- 20, 7, 27, 10L,
- "Optional footer description"),
- newCreateEntry("key1", "subkey-2", "elisa.work@google.com",
- 20, 7, 27, 12L,
- null),
- )
- )
- .setRemoteEntry(
- newRemoteEntry("key2", "subkey-1")
- )
- .build(),
- CreateCredentialProviderData
- .Builder("com.dashlane")
- .setSaveEntries(
- listOf<Entry>(
- newCreateEntry("key1", "subkey-3", "elisa.beckett@dashlane.com",
- 20, 7, 27, 11L,
- null),
- newCreateEntry("key1", "subkey-4", "elisa.work@dashlane.com",
- 20, 7, 27, 14L,
- null),
- )
- )
- .build(),
- )
- }
+ private fun testDisabledProviderList(): List<DisabledProviderData>? {
+ return listOf(
+ DisabledProviderData("com.lastpass.lpandroid"),
+ DisabledProviderData("com.google.android.youtube")
+ )
+ }
- private fun testDisabledProviderList(): List<DisabledProviderData>? {
- return listOf(
- DisabledProviderData("com.lastpass.lpandroid"),
- DisabledProviderData("com.google.android.youtube")
- )
- }
-
- private fun testGetCredentialProviderList(): List<GetCredentialProviderData> {
- return listOf(
- GetCredentialProviderData.Builder("io.enpass.app")
- .setCredentialEntries(
- listOf<Entry>(
- newGetEntry(
- "key1", "subkey-1", TYPE_PASSWORD_CREDENTIAL, "Password",
- "elisa.family@outlook.com", null, 3L
- ),
- newGetEntry(
- "key1", "subkey-1", TYPE_PUBLIC_KEY_CREDENTIAL, "Passkey",
- "elisa.bakery@gmail.com", "Elisa Beckett", 0L
- ),
- newGetEntry(
- "key1", "subkey-2", TYPE_PASSWORD_CREDENTIAL, "Password",
- "elisa.bakery@gmail.com", null, 10L
- ),
- newGetEntry(
- "key1", "subkey-3", TYPE_PUBLIC_KEY_CREDENTIAL, "Passkey",
- "elisa.family@outlook.com", "Elisa Beckett", 1L
- ),
- )
- ).setAuthenticationEntry(
- newAuthenticationEntry("key2", "subkey-1", TYPE_PASSWORD_CREDENTIAL)
- ).setActionChips(
- listOf(
- newActionEntry(
- "key3", "subkey-1", TYPE_PASSWORD_CREDENTIAL,
- "Open Google Password Manager", "elisa.beckett@gmail.com"
- ),
- newActionEntry(
- "key3", "subkey-2", TYPE_PASSWORD_CREDENTIAL,
- "Open Google Password Manager", "beckett-family@gmail.com"
- ),
- )
- ).setRemoteEntry(
- newRemoteEntry("key4", "subkey-1")
- ).build(),
- GetCredentialProviderData.Builder("com.dashlane")
- .setCredentialEntries(
- listOf<Entry>(
- newGetEntry(
- "key1", "subkey-2", TYPE_PASSWORD_CREDENTIAL, "Password",
- "elisa.family@outlook.com", null, 4L
- ),
- newGetEntry(
- "key1", "subkey-3", TYPE_PASSWORD_CREDENTIAL, "Password",
- "elisa.work@outlook.com", null, 11L
- ),
- )
- ).setAuthenticationEntry(
- newAuthenticationEntry("key2", "subkey-1", TYPE_PASSWORD_CREDENTIAL)
- ).setActionChips(
- listOf(
- newActionEntry(
- "key3", "subkey-1", TYPE_PASSWORD_CREDENTIAL,
- "Open Enpass"
- ),
- )
- ).build(),
- )
- }
+ private fun testGetCredentialProviderList(): List<GetCredentialProviderData> {
+ return listOf(
+ GetCredentialProviderData.Builder("io.enpass.app")
+ .setCredentialEntries(
+ listOf<Entry>(
+ newGetEntry(
+ "key1", "subkey-1", TYPE_PASSWORD_CREDENTIAL, "Password",
+ "elisa.family@outlook.com", null, 3L
+ ),
+ newGetEntry(
+ "key1", "subkey-1", TYPE_PUBLIC_KEY_CREDENTIAL, "Passkey",
+ "elisa.bakery@gmail.com", "Elisa Beckett", 0L
+ ),
+ newGetEntry(
+ "key1", "subkey-2", TYPE_PASSWORD_CREDENTIAL, "Password",
+ "elisa.bakery@gmail.com", null, 10L
+ ),
+ newGetEntry(
+ "key1", "subkey-3", TYPE_PUBLIC_KEY_CREDENTIAL, "Passkey",
+ "elisa.family@outlook.com", "Elisa Beckett", 1L
+ ),
+ )
+ ).setAuthenticationEntry(
+ newAuthenticationEntry("key2", "subkey-1", TYPE_PASSWORD_CREDENTIAL)
+ ).setActionChips(
+ listOf(
+ newActionEntry(
+ "key3", "subkey-1", TYPE_PASSWORD_CREDENTIAL,
+ "Open Google Password Manager", "elisa.beckett@gmail.com"
+ ),
+ newActionEntry(
+ "key3", "subkey-2", TYPE_PASSWORD_CREDENTIAL,
+ "Open Google Password Manager", "beckett-family@gmail.com"
+ ),
+ )
+ ).setRemoteEntry(
+ newRemoteEntry("key4", "subkey-1")
+ ).build(),
+ GetCredentialProviderData.Builder("com.dashlane")
+ .setCredentialEntries(
+ listOf<Entry>(
+ newGetEntry(
+ "key1", "subkey-2", TYPE_PASSWORD_CREDENTIAL, "Password",
+ "elisa.family@outlook.com", null, 4L
+ ),
+ newGetEntry(
+ "key1", "subkey-3", TYPE_PASSWORD_CREDENTIAL, "Password",
+ "elisa.work@outlook.com", null, 11L
+ ),
+ )
+ ).setAuthenticationEntry(
+ newAuthenticationEntry("key2", "subkey-1", TYPE_PASSWORD_CREDENTIAL)
+ ).setActionChips(
+ listOf(
+ newActionEntry(
+ "key3", "subkey-1", TYPE_PASSWORD_CREDENTIAL,
+ "Open Enpass"
+ ),
+ )
+ ).build(),
+ )
+ }
private fun newActionEntry(
- key: String,
- subkey: String,
- credentialType: String,
- text: String,
- subtext: String? = null,
+ key: String,
+ subkey: String,
+ credentialType: String,
+ text: String,
+ subtext: String? = null,
): Entry {
val action = Action(text, subtext, null)
return Entry(
- key,
- subkey,
- Action.toSlice(action)
+ key,
+ subkey,
+ Action.toSlice(action)
)
}
private fun newAuthenticationEntry(
- key: String,
- subkey: String,
- credentialType: String,
+ key: String,
+ subkey: String,
+ credentialType: String,
): Entry {
val slice = Slice.Builder(
- Uri.EMPTY, SliceSpec(credentialType, 1)
+ Uri.EMPTY, SliceSpec(credentialType, 1)
)
return Entry(
- key,
- subkey,
- slice.build()
+ key,
+ subkey,
+ slice.build()
)
}
private fun newGetEntry(
- key: String,
- subkey: String,
- credentialType: String,
- credentialTypeDisplayName: String,
- userName: String,
- userDisplayName: String?,
- lastUsedTimeMillis: Long?,
+ key: String,
+ subkey: String,
+ credentialType: String,
+ credentialTypeDisplayName: String,
+ userName: String,
+ userDisplayName: String?,
+ lastUsedTimeMillis: Long?,
): Entry {
val intent = Intent("com.androidauth.androidvault.CONFIRM_PASSWORD")
- .setPackage("com.androidauth.androidvault")
+ .setPackage("com.androidauth.androidvault")
intent.putExtra("provider_extra_sample", "testprovider")
- val pendingIntent = PendingIntent.getActivity(context, 1,
- intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
- or PendingIntent.FLAG_ONE_SHOT))
+ val pendingIntent = PendingIntent.getActivity(
+ context, 1,
+ intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+ or PendingIntent.FLAG_ONE_SHOT)
+ )
- val credentialEntry = CredentialEntry(credentialType, credentialTypeDisplayName, userName,
- userDisplayName, pendingIntent, lastUsedTimeMillis
- ?: 0L, null, false)
+ val credentialEntry = CredentialEntry(
+ credentialType, credentialTypeDisplayName, userName,
+ userDisplayName, pendingIntent, lastUsedTimeMillis
+ ?: 0L, null, false
+ )
return Entry(
- key,
- subkey,
- CredentialEntry.toSlice(credentialEntry),
- Intent()
- )
- }
-
- private fun newCreateEntry(
- key: String,
- subkey: String,
- providerDisplayName: String,
- passwordCount: Int,
- passkeyCount: Int,
- totalCredentialCount: Int,
- lastUsedTimeMillis: Long,
- footerDescription: String?,
- ): Entry {
- val intent = Intent("com.androidauth.androidvault.CONFIRM_PASSWORD")
- .setPackage("com.androidauth.androidvault")
- intent.putExtra("provider_extra_sample", "testprovider")
- val pendingIntent = PendingIntent.getActivity(context, 1,
- intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
- or PendingIntent.FLAG_ONE_SHOT))
- val createPasswordRequest = android.service.credentials.CreateCredentialRequest(
- android.service.credentials.CallingAppInfo(
- context.applicationInfo.packageName, SigningInfo()),
- TYPE_PASSWORD_CREDENTIAL,
- toCredentialDataBundle("beckett-bakert@gmail.com", "password123")
- )
- val fillInIntent = Intent().putExtra(
- CredentialProviderService.EXTRA_CREATE_CREDENTIAL_REQUEST,
- createPasswordRequest)
-
- val createEntry = CreateEntry(
- providerDisplayName, pendingIntent,
- null, lastUsedTimeMillis,
- listOf(
- CredentialCountInformation.createPasswordCountInformation(passwordCount),
- CredentialCountInformation.createPublicKeyCountInformation(passkeyCount),
- ), footerDescription)
- return Entry(
- key,
- subkey,
- CreateEntry.toSlice(createEntry),
- fillInIntent
+ key,
+ subkey,
+ CredentialEntry.toSlice(credentialEntry),
+ Intent()
)
}
- private fun newRemoteEntry(
- key: String,
- subkey: String,
- ): Entry {
- return Entry(
- key,
- subkey,
- Slice.Builder(
- Uri.EMPTY, SliceSpec("type", 1)
- ).build()
- )
- }
-
- private fun testCreatePasskeyRequestInfo(): RequestInfo {
- val request = CreatePublicKeyCredentialRequest("{\"extensions\": {\n" +
- " \"webauthn.loc\": true\n" +
- " },\n" +
- " \"attestation\": \"direct\",\n" +
- " \"challenge\": \"-rSQHXSQUdaK1N-La5bE-JPt6EVAW4SxX1K_tXhZ_Gk\",\n" +
- " \"user\": {\n" +
- " \"displayName\": \"testName\",\n" +
- " \"name\": \"credManTesting@gmail.com\",\n" +
- " \"id\": \"eD4o2KoXLpgegAtnM5cDhhUPvvk2\"\n" +
- " },\n" +
- " \"excludeCredentials\": [],\n" +
- " \"rp\": {\n" +
- " \"name\": \"Address Book\",\n" +
- " \"id\": \"addressbook-c7876.uc.r.appspot.com\"\n" +
- " },\n" +
- " \"timeout\": 60000,\n" +
- " \"pubKeyCredParams\": [\n" +
- " {\n" +
- " \"type\": \"public-key\",\n" +
- " \"alg\": -7\n" +
- " },\n" +
- " {\n" +
- " \"type\": \"public-key\",\n" +
- " \"alg\": -257\n" +
- " },\n" +
- " {\n" +
- " \"type\": \"public-key\",\n" +
- " \"alg\": -37\n" +
- " }\n" +
- " ],\n" +
- " \"authenticatorSelection\": {\n" +
- " \"residentKey\": \"required\",\n" +
- " \"requireResidentKey\": true\n" +
- " }}")
- val credentialData = request.credentialData
- return RequestInfo.newCreateRequestInfo(
- Binder(),
- CreateCredentialRequest(
- TYPE_PUBLIC_KEY_CREDENTIAL,
- credentialData,
- // TODO: populate with actual data
- /*candidateQueryData=*/ Bundle(),
- /*isSystemProviderRequired=*/ false
- ),
- "com.google.android.youtube"
- )
- }
-
- private fun testCreatePasswordRequestInfo(): RequestInfo {
- val data = toCredentialDataBundle("beckett-bakert@gmail.com", "password123")
- return RequestInfo.newCreateRequestInfo(
- Binder(),
- CreateCredentialRequest(
- TYPE_PASSWORD_CREDENTIAL,
- data,
- // TODO: populate with actual data
- /*candidateQueryData=*/ Bundle(),
- /*isSystemProviderRequired=*/ false
- ),
- "com.google.android.youtube"
- )
- }
-
- private fun testCreateOtherCredentialRequestInfo(): RequestInfo {
- val data = Bundle()
- return RequestInfo.newCreateRequestInfo(
- Binder(),
- CreateCredentialRequest(
- "other-sign-ins",
- data,
- /*candidateQueryData=*/ Bundle(),
- /*isSystemProviderRequired=*/ false
- ),
- "com.google.android.youtube"
- )
- }
-
- private fun testGetRequestInfo(): RequestInfo {
- return RequestInfo.newGetRequestInfo(
- Binder(),
- GetCredentialRequest.Builder(
- Bundle()
- )
- .addGetCredentialOption(
- GetCredentialOption(
- TYPE_PUBLIC_KEY_CREDENTIAL, Bundle(), Bundle(), /*isSystemProviderRequired=*/ false)
+ private fun newCreateEntry(
+ key: String,
+ subkey: String,
+ providerDisplayName: String,
+ passwordCount: Int,
+ passkeyCount: Int,
+ totalCredentialCount: Int,
+ lastUsedTimeMillis: Long,
+ footerDescription: String?,
+ ): Entry {
+ val intent = Intent("com.androidauth.androidvault.CONFIRM_PASSWORD")
+ .setPackage("com.androidauth.androidvault")
+ intent.putExtra("provider_extra_sample", "testprovider")
+ val pendingIntent = PendingIntent.getActivity(
+ context, 1,
+ intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+ or PendingIntent.FLAG_ONE_SHOT)
)
- .build(),
- "com.google.android.youtube"
- )
- }
+ val createPasswordRequest = android.service.credentials.CreateCredentialRequest(
+ android.service.credentials.CallingAppInfo(
+ context.applicationInfo.packageName, SigningInfo()
+ ),
+ TYPE_PASSWORD_CREDENTIAL,
+ toCredentialDataBundle("beckett-bakert@gmail.com", "password123")
+ )
+ val fillInIntent = Intent().putExtra(
+ CredentialProviderService.EXTRA_CREATE_CREDENTIAL_REQUEST,
+ createPasswordRequest
+ )
+
+ val createEntry = CreateEntry(
+ providerDisplayName, pendingIntent,
+ null, lastUsedTimeMillis,
+ listOf(
+ CredentialCountInformation.createPasswordCountInformation(passwordCount),
+ CredentialCountInformation.createPublicKeyCountInformation(passkeyCount),
+ ), footerDescription
+ )
+ return Entry(
+ key,
+ subkey,
+ CreateEntry.toSlice(createEntry),
+ fillInIntent
+ )
+ }
+
+ private fun newRemoteEntry(
+ key: String,
+ subkey: String,
+ ): Entry {
+ return Entry(
+ key,
+ subkey,
+ Slice.Builder(
+ Uri.EMPTY, SliceSpec("type", 1)
+ ).build()
+ )
+ }
+
+ private fun testCreatePasskeyRequestInfo(): RequestInfo {
+ val request = CreatePublicKeyCredentialRequest(
+ "{\"extensions\": {\n" +
+ " \"webauthn.loc\": true\n" +
+ " },\n" +
+ " \"attestation\": \"direct\",\n" +
+ " \"challenge\":" +
+ " \"-rSQHXSQUdaK1N-La5bE-JPt6EVAW4SxX1K_tXhZ_Gk\",\n" +
+ " \"user\": {\n" +
+ " \"displayName\": \"testName\",\n" +
+ " \"name\": \"credManTesting@gmail.com\",\n" +
+ " \"id\": \"eD4o2KoXLpgegAtnM5cDhhUPvvk2\"\n" +
+ " },\n" +
+ " \"excludeCredentials\": [],\n" +
+ " \"rp\": {\n" +
+ " \"name\": \"Address Book\",\n" +
+ " \"id\": \"addressbook-c7876.uc.r.appspot.com\"\n" +
+ " },\n" +
+ " \"timeout\": 60000,\n" +
+ " \"pubKeyCredParams\": [\n" +
+ " {\n" +
+ " \"type\": \"public-key\",\n" +
+ " \"alg\": -7\n" +
+ " },\n" +
+ " {\n" +
+ " \"type\": \"public-key\",\n" +
+ " \"alg\": -257\n" +
+ " },\n" +
+ " {\n" +
+ " \"type\": \"public-key\",\n" +
+ " \"alg\": -37\n" +
+ " }\n" +
+ " ],\n" +
+ " \"authenticatorSelection\": {\n" +
+ " \"residentKey\": \"required\",\n" +
+ " \"requireResidentKey\": true\n" +
+ " }}"
+ )
+ val credentialData = request.credentialData
+ return RequestInfo.newCreateRequestInfo(
+ Binder(),
+ CreateCredentialRequest(
+ TYPE_PUBLIC_KEY_CREDENTIAL,
+ credentialData,
+ // TODO: populate with actual data
+ /*candidateQueryData=*/ Bundle(),
+ /*isSystemProviderRequired=*/ false
+ ),
+ "com.google.android.youtube"
+ )
+ }
+
+ private fun testCreatePasswordRequestInfo(): RequestInfo {
+ val data = toCredentialDataBundle("beckett-bakert@gmail.com", "password123")
+ return RequestInfo.newCreateRequestInfo(
+ Binder(),
+ CreateCredentialRequest(
+ TYPE_PASSWORD_CREDENTIAL,
+ data,
+ // TODO: populate with actual data
+ /*candidateQueryData=*/ Bundle(),
+ /*isSystemProviderRequired=*/ false
+ ),
+ "com.google.android.youtube"
+ )
+ }
+
+ private fun testCreateOtherCredentialRequestInfo(): RequestInfo {
+ val data = Bundle()
+ return RequestInfo.newCreateRequestInfo(
+ Binder(),
+ CreateCredentialRequest(
+ "other-sign-ins",
+ data,
+ /*candidateQueryData=*/ Bundle(),
+ /*isSystemProviderRequired=*/ false
+ ),
+ "com.google.android.youtube"
+ )
+ }
+
+ private fun testGetRequestInfo(): RequestInfo {
+ return RequestInfo.newGetRequestInfo(
+ Binder(),
+ GetCredentialRequest.Builder(
+ Bundle()
+ )
+ .addGetCredentialOption(
+ GetCredentialOption(
+ TYPE_PUBLIC_KEY_CREDENTIAL,
+ Bundle(),
+ Bundle(), /*isSystemProviderRequired=*/
+ false
+ )
+ )
+ .build(),
+ "com.google.android.youtube"
+ )
+ }
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
index df85745..3b9c02a 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
@@ -31,6 +31,7 @@
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.lifecycle.viewmodel.compose.viewModel
+import com.android.credentialmanager.common.Constants
import com.android.credentialmanager.common.DialogState
import com.android.credentialmanager.common.ProviderActivityResult
import com.android.credentialmanager.createflow.CreateCredentialScreen
@@ -45,11 +46,15 @@
super.onCreate(savedInstanceState)
val credManRepo = CredentialManagerRepo(this, intent)
UserConfigRepo.setup(this)
- val requestInfo = credManRepo.requestInfo
- setContent {
- CredentialSelectorTheme {
- CredentialManagerBottomSheet(requestInfo.type, credManRepo)
+ try {
+ setContent {
+ CredentialSelectorTheme {
+ CredentialManagerBottomSheet(credManRepo.requestInfo.type, credManRepo)
+ }
}
+ } catch (e: Exception) {
+ Log.e(Constants.LOG_TAG, "Failed to show the credential selector", e)
+ reportInstantiationErrorAndFinishActivity(credManRepo)
}
}
@@ -65,7 +70,22 @@
when (requestType) {
RequestInfo.TYPE_CREATE -> {
val viewModel: CreateCredentialViewModel = viewModel {
- CreateCredentialViewModel(credManRepo)
+ val vm = CreateCredentialViewModel.newInstance(
+ credManRepo = credManRepo,
+ providerEnableListUiState =
+ credManRepo.getCreateProviderEnableListInitialUiState(),
+ providerDisableListUiState =
+ credManRepo.getCreateProviderDisableListInitialUiState(),
+ requestDisplayInfoUiState =
+ credManRepo.getCreateRequestDisplayInfoInitialUiState()
+ )
+ if (vm == null) {
+ // Input parsing failed. Close the activity.
+ reportInstantiationErrorAndFinishActivity(credManRepo)
+ throw IllegalStateException()
+ } else {
+ vm
+ }
}
LaunchedEffect(viewModel.uiState.dialogState) {
handleDialogState(viewModel.uiState.dialogState)
@@ -74,11 +94,21 @@
viewModel.onProviderActivityResult(it)
providerActivityResult.value = null
}
- CreateCredentialScreen(viewModel = viewModel, providerActivityLauncher = launcher)
+ CreateCredentialScreen(
+ viewModel = viewModel,
+ providerActivityLauncher = launcher
+ )
}
RequestInfo.TYPE_GET -> {
val viewModel: GetCredentialViewModel = viewModel {
- GetCredentialViewModel(credManRepo)
+ val initialUiState = credManRepo.getCredentialInitialUiState()
+ if (initialUiState == null) {
+ // Input parsing failed. Close the activity.
+ reportInstantiationErrorAndFinishActivity(credManRepo)
+ throw IllegalStateException()
+ } else {
+ GetCredentialViewModel(credManRepo, initialUiState)
+ }
}
LaunchedEffect(viewModel.uiState.dialogState) {
handleDialogState(viewModel.uiState.dialogState)
@@ -90,18 +120,24 @@
GetCredentialScreen(viewModel = viewModel, providerActivityLauncher = launcher)
}
else -> {
- Log.w("AccountSelector", "Unknown type, not rendering any UI")
- this.finish()
+ Log.d(Constants.LOG_TAG, "Unknown type, not rendering any UI")
+ reportInstantiationErrorAndFinishActivity(credManRepo)
}
}
}
+ private fun reportInstantiationErrorAndFinishActivity(credManRepo: CredentialManagerRepo) {
+ Log.w(Constants.LOG_TAG, "Finishing the activity due to instantiation failure.")
+ credManRepo.onParsingFailureCancel()
+ this@CredentialSelectorActivity.finish()
+ }
+
private fun handleDialogState(dialogState: DialogState) {
if (dialogState == DialogState.COMPLETE) {
- Log.i("AccountSelector", "Received signal to finish the activity.")
+ Log.d(Constants.LOG_TAG, "Received signal to finish the activity.")
this@CredentialSelectorActivity.finish()
} else if (dialogState == DialogState.CANCELED_FOR_SETTINGS) {
- Log.i("AccountSelector", "Received signal to finish the activity and launch settings.")
+ Log.d(Constants.LOG_TAG, "Received signal to finish the activity and launch settings.")
this@CredentialSelectorActivity.startActivity(Intent(Settings.ACTION_SYNC_SETTINGS))
this@CredentialSelectorActivity.finish()
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index d9e4dc8..3f705d6 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -19,21 +19,23 @@
import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager
-import android.credentials.ui.Entry
-import android.credentials.ui.GetCredentialProviderData
import android.credentials.ui.CreateCredentialProviderData
import android.credentials.ui.DisabledProviderData
+import android.credentials.ui.Entry
+import android.credentials.ui.GetCredentialProviderData
import android.credentials.ui.RequestInfo
import android.graphics.drawable.Drawable
import android.text.TextUtils
+import android.util.Log
+import com.android.credentialmanager.common.Constants
+import com.android.credentialmanager.createflow.ActiveEntry
+import com.android.credentialmanager.createflow.CreateCredentialUiState
import com.android.credentialmanager.createflow.CreateOptionInfo
+import com.android.credentialmanager.createflow.CreateScreenState
+import com.android.credentialmanager.createflow.DisabledProviderInfo
+import com.android.credentialmanager.createflow.EnabledProviderInfo
import com.android.credentialmanager.createflow.RemoteInfo
import com.android.credentialmanager.createflow.RequestDisplayInfo
-import com.android.credentialmanager.createflow.EnabledProviderInfo
-import com.android.credentialmanager.createflow.CreateScreenState
-import com.android.credentialmanager.createflow.ActiveEntry
-import com.android.credentialmanager.createflow.DisabledProviderInfo
-import com.android.credentialmanager.createflow.CreateCredentialUiState
import com.android.credentialmanager.getflow.ActionEntryInfo
import com.android.credentialmanager.getflow.AuthenticationEntryInfo
import com.android.credentialmanager.getflow.CredentialEntryInfo
@@ -45,416 +47,480 @@
import com.android.credentialmanager.jetpack.developer.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
import com.android.credentialmanager.jetpack.provider.Action
import com.android.credentialmanager.jetpack.provider.AuthenticationAction
+import com.android.credentialmanager.jetpack.provider.CreateEntry
import com.android.credentialmanager.jetpack.provider.CredentialCountInformation
import com.android.credentialmanager.jetpack.provider.CredentialEntry
-import com.android.credentialmanager.jetpack.provider.CreateEntry
import org.json.JSONObject
+private fun getAppLabel(
+ pm: PackageManager,
+ appPackageName: String
+): String? {
+ return try {
+ val pkgInfo = pm.getPackageInfo(appPackageName, PackageManager.PackageInfoFlags.of(0))
+ pkgInfo.applicationInfo.loadSafeLabel(
+ pm, 0f,
+ TextUtils.SAFE_STRING_FLAG_FIRST_LINE or TextUtils.SAFE_STRING_FLAG_TRIM
+ ).toString()
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.e(Constants.LOG_TAG, "Caller app not found", e)
+ null
+ }
+}
+
+private fun getServiceLabelAndIcon(
+ pm: PackageManager,
+ providerFlattenedComponentName: String
+): Pair<String, Drawable>? {
+ var providerLabel: String? = null
+ var providerIcon: Drawable? = null
+ val component = ComponentName.unflattenFromString(providerFlattenedComponentName)
+ if (component == null) {
+ // Test data has only package name not component name.
+ // TODO: remove once test data is removed
+ try {
+ val pkgInfo = pm.getPackageInfo(
+ providerFlattenedComponentName,
+ PackageManager.PackageInfoFlags.of(0)
+ )
+ providerLabel =
+ pkgInfo.applicationInfo.loadSafeLabel(
+ pm, 0f,
+ TextUtils.SAFE_STRING_FLAG_FIRST_LINE or TextUtils.SAFE_STRING_FLAG_TRIM
+ ).toString()
+ providerIcon = pkgInfo.applicationInfo.loadIcon(pm)
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.e(Constants.LOG_TAG, "Provider info not found", e)
+ }
+ } else {
+ try {
+ val si = pm.getServiceInfo(component, PackageManager.ComponentInfoFlags.of(0))
+ providerLabel = si.loadSafeLabel(
+ pm, 0f,
+ TextUtils.SAFE_STRING_FLAG_FIRST_LINE or TextUtils.SAFE_STRING_FLAG_TRIM
+ ).toString()
+ providerIcon = si.loadIcon(pm)
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.e(Constants.LOG_TAG, "Provider info not found", e)
+ }
+ }
+ return if (providerLabel == null || providerIcon == null) {
+ Log.d(
+ Constants.LOG_TAG,
+ "Failed to load provider label/icon for provider $providerFlattenedComponentName"
+ )
+ null
+ } else {
+ Pair(providerLabel, providerIcon)
+ }
+}
+
/** Utility functions for converting CredentialManager data structures to or from UI formats. */
class GetFlowUtils {
- companion object {
-
- fun toProviderList(
+ companion object {
+ // Returns the list (potentially empty) of enabled provider.
+ fun toProviderList(
providerDataList: List<GetCredentialProviderData>,
context: Context,
- ): List<ProviderInfo> {
- val packageManager = context.packageManager
- return providerDataList.map {
- val componentName = ComponentName.unflattenFromString(it.providerFlattenedComponentName)
- var packageName = componentName?.packageName
- if (componentName == null) {
- // TODO: Remove once test data is fixed
- packageName = it.providerFlattenedComponentName
+ ): List<ProviderInfo> {
+ val providerList: MutableList<ProviderInfo> = mutableListOf()
+ providerDataList.forEach {
+ val providerLabelAndIcon = getServiceLabelAndIcon(
+ context.packageManager,
+ it.providerFlattenedComponentName
+ ) ?: return@forEach
+ val (providerLabel, providerIcon) = providerLabelAndIcon
+ providerList.add(
+ ProviderInfo(
+ id = it.providerFlattenedComponentName,
+ icon = providerIcon,
+ displayName = providerLabel,
+ credentialEntryList = getCredentialOptionInfoList(
+ it.providerFlattenedComponentName, it.credentialEntries, context
+ ),
+ authenticationEntry = getAuthenticationEntry(
+ it.providerFlattenedComponentName,
+ providerLabel,
+ providerIcon,
+ it.authenticationEntry
+ ),
+ remoteEntry = getRemoteEntry(
+ it.providerFlattenedComponentName,
+ it.remoteEntry
+ ),
+ actionEntryList = getActionEntryList(
+ it.providerFlattenedComponentName, it.actionChips, providerIcon
+ ),
+ )
+ )
+ }
+ return providerList
}
- val pkgInfo = packageManager
- .getPackageInfo(packageName!!,
- PackageManager.PackageInfoFlags.of(0))
- val providerDisplayName = pkgInfo.applicationInfo.loadLabel(packageManager).toString()
- // TODO: decide what to do when failed to load a provider icon
- val providerIcon = pkgInfo.applicationInfo.loadIcon(packageManager)!!
- ProviderInfo(
- id = it.providerFlattenedComponentName,
- // TODO: decide what to do when failed to load a provider icon
- icon = providerIcon,
- displayName = providerDisplayName,
- credentialEntryList = getCredentialOptionInfoList(
- it.providerFlattenedComponentName, it.credentialEntries, context),
- authenticationEntry = getAuthenticationEntry(
- it.providerFlattenedComponentName,
- providerDisplayName,
- providerIcon,
- it.authenticationEntry),
- remoteEntry = getRemoteEntry(it.providerFlattenedComponentName, it.remoteEntry),
- actionEntryList = getActionEntryList(
- it.providerFlattenedComponentName, it.actionChips, providerIcon),
- )
- }
- }
-
- fun toRequestDisplayInfo(
+ fun toRequestDisplayInfo(
requestInfo: RequestInfo,
context: Context,
- ): com.android.credentialmanager.getflow.RequestDisplayInfo {
- val packageName = requestInfo.appPackageName
- val pkgInfo = context.packageManager.getPackageInfo(packageName,
- PackageManager.PackageInfoFlags.of(0))
- val appLabel = pkgInfo.applicationInfo.loadSafeLabel(context.packageManager, 0f,
- TextUtils.SAFE_STRING_FLAG_FIRST_LINE or TextUtils.SAFE_STRING_FLAG_TRIM)
- return com.android.credentialmanager.getflow.RequestDisplayInfo(
- appName = appLabel.toString()
- )
- }
+ ): com.android.credentialmanager.getflow.RequestDisplayInfo? {
+ return com.android.credentialmanager.getflow.RequestDisplayInfo(
+ appName = getAppLabel(context.packageManager, requestInfo.appPackageName)
+ ?: return null
+ )
+ }
- /* From service data structure to UI credential entry list representation. */
- private fun getCredentialOptionInfoList(
+ /* From service data structure to UI credential entry list representation. */
+ private fun getCredentialOptionInfoList(
providerId: String,
credentialEntries: List<Entry>,
context: Context,
- ): List<CredentialEntryInfo> {
- return credentialEntries.map {
- // TODO: handle NPE gracefully
- val credentialEntry = CredentialEntry.fromSlice(it.slice)!!
+ ): List<CredentialEntryInfo> {
+ return credentialEntries.map {
+ // TODO: handle NPE gracefully
+ val credentialEntry = CredentialEntry.fromSlice(it.slice)!!
- // Consider directly move the UI object into the class.
- return@map CredentialEntryInfo(
- providerId = providerId,
- entryKey = it.key,
- entrySubkey = it.subkey,
- pendingIntent = credentialEntry.pendingIntent,
- fillInIntent = it.frameworkExtrasIntent,
- credentialType = credentialEntry.type.toString(),
- credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
- userName = credentialEntry.username.toString(),
- displayName = credentialEntry.displayName?.toString(),
- // TODO: proper fallback
- icon = credentialEntry.icon?.loadDrawable(context),
- lastUsedTimeMillis = credentialEntry.lastUsedTimeMillis,
- )
- }
- }
+ // Consider directly move the UI object into the class.
+ return@map CredentialEntryInfo(
+ providerId = providerId,
+ entryKey = it.key,
+ entrySubkey = it.subkey,
+ pendingIntent = credentialEntry.pendingIntent,
+ fillInIntent = it.frameworkExtrasIntent,
+ credentialType = credentialEntry.type,
+ credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
+ userName = credentialEntry.username.toString(),
+ displayName = credentialEntry.displayName?.toString(),
+ // TODO: proper fallback
+ icon = credentialEntry.icon?.loadDrawable(context),
+ lastUsedTimeMillis = credentialEntry.lastUsedTimeMillis,
+ )
+ }
+ }
- private fun getAuthenticationEntry(
+ private fun getAuthenticationEntry(
providerId: String,
providerDisplayName: String,
providerIcon: Drawable,
authEntry: Entry?,
- ): AuthenticationEntryInfo? {
- if (authEntry == null) {
- return null
- }
- val authStructuredEntry = AuthenticationAction.fromSlice(
- authEntry!!.slice)
- if (authStructuredEntry == null) {
- return null
- }
+ ): AuthenticationEntryInfo? {
+ if (authEntry == null) {
+ return null
+ }
+ val authStructuredEntry = AuthenticationAction.fromSlice(
+ authEntry!!.slice
+ )
+ if (authStructuredEntry == null) {
+ return null
+ }
- return AuthenticationEntryInfo(
- providerId = providerId,
- entryKey = authEntry.key,
- entrySubkey = authEntry.subkey,
- pendingIntent = authStructuredEntry.pendingIntent,
- fillInIntent = authEntry.frameworkExtrasIntent,
- title = providerDisplayName,
- icon = providerIcon,
- )
- }
+ return AuthenticationEntryInfo(
+ providerId = providerId,
+ entryKey = authEntry.key,
+ entrySubkey = authEntry.subkey,
+ pendingIntent = authStructuredEntry.pendingIntent,
+ fillInIntent = authEntry.frameworkExtrasIntent,
+ title = providerDisplayName,
+ icon = providerIcon,
+ )
+ }
- private fun getRemoteEntry(providerId: String, remoteEntry: Entry?): RemoteEntryInfo? {
- // TODO: should also call fromSlice after getting the official jetpack code.
- if (remoteEntry == null) {
- return null
- }
- return RemoteEntryInfo(
- providerId = providerId,
- entryKey = remoteEntry.key,
- entrySubkey = remoteEntry.subkey,
- pendingIntent = remoteEntry.pendingIntent,
- fillInIntent = remoteEntry.frameworkExtrasIntent,
- )
- }
+ private fun getRemoteEntry(providerId: String, remoteEntry: Entry?): RemoteEntryInfo? {
+ // TODO: should also call fromSlice after getting the official jetpack code.
+ if (remoteEntry == null) {
+ return null
+ }
+ return RemoteEntryInfo(
+ providerId = providerId,
+ entryKey = remoteEntry.key,
+ entrySubkey = remoteEntry.subkey,
+ pendingIntent = remoteEntry.pendingIntent,
+ fillInIntent = remoteEntry.frameworkExtrasIntent,
+ )
+ }
- private fun getActionEntryList(
+ private fun getActionEntryList(
providerId: String,
actionEntries: List<Entry>,
providerIcon: Drawable,
- ): List<ActionEntryInfo> {
- return actionEntries.map {
- // TODO: handle NPE gracefully
- val actionEntryUi = Action.fromSlice(it.slice)!!
+ ): List<ActionEntryInfo> {
+ return actionEntries.map {
+ // TODO: handle NPE gracefully
+ val actionEntryUi = Action.fromSlice(it.slice)!!
- return@map ActionEntryInfo(
- providerId = providerId,
- entryKey = it.key,
- entrySubkey = it.subkey,
- pendingIntent = actionEntryUi.pendingIntent,
- fillInIntent = it.frameworkExtrasIntent,
- title = actionEntryUi.title.toString(),
- // TODO: gracefully fail
- icon = providerIcon,
- subTitle = actionEntryUi.subTitle?.toString(),
- )
- }
+ return@map ActionEntryInfo(
+ providerId = providerId,
+ entryKey = it.key,
+ entrySubkey = it.subkey,
+ pendingIntent = actionEntryUi.pendingIntent,
+ fillInIntent = it.frameworkExtrasIntent,
+ title = actionEntryUi.title.toString(),
+ // TODO: gracefully fail
+ icon = providerIcon,
+ subTitle = actionEntryUi.subTitle?.toString(),
+ )
+ }
+ }
}
- }
}
class CreateFlowUtils {
- companion object {
-
- fun toEnabledProviderList(
+ companion object {
+ // Returns the list (potentially empty) of enabled provider.
+ fun toEnabledProviderList(
providerDataList: List<CreateCredentialProviderData>,
context: Context,
- ): List<EnabledProviderInfo> {
- // TODO: get from the actual service info
- val packageManager = context.packageManager
-
- return providerDataList.map {
- val componentName = ComponentName.unflattenFromString(it.providerFlattenedComponentName)
- var packageName = componentName?.packageName
- if (componentName == null) {
- // TODO: Remove once test data is fixed
- packageName = it.providerFlattenedComponentName
+ ): List<EnabledProviderInfo> {
+ val providerList: MutableList<EnabledProviderInfo> = mutableListOf()
+ providerDataList.forEach {
+ val providerLabelAndIcon = getServiceLabelAndIcon(
+ context.packageManager,
+ it.providerFlattenedComponentName
+ ) ?: return@forEach
+ val (providerLabel, providerIcon) = providerLabelAndIcon
+ providerList.add(EnabledProviderInfo(
+ id = it.providerFlattenedComponentName,
+ displayName = providerLabel,
+ icon = providerIcon,
+ createOptions = toCreationOptionInfoList(
+ it.providerFlattenedComponentName, it.saveEntries, context
+ ),
+ remoteEntry = toRemoteInfo(it.providerFlattenedComponentName, it.remoteEntry),
+ ))
+ }
+ return providerList
}
- val pkgInfo = packageManager
- .getPackageInfo(packageName!!,
- PackageManager.PackageInfoFlags.of(0))
- EnabledProviderInfo(
- // TODO: decide what to do when failed to load a provider icon
- icon = pkgInfo.applicationInfo.loadIcon(packageManager)!!,
- name = it.providerFlattenedComponentName,
- displayName = pkgInfo.applicationInfo.loadLabel(packageManager).toString(),
- createOptions = toCreationOptionInfoList(
- it.providerFlattenedComponentName, it.saveEntries, context),
- remoteEntry = toRemoteInfo(it.providerFlattenedComponentName, it.remoteEntry),
- )
- }
- }
-
- fun toDisabledProviderList(
+ // Returns the list (potentially empty) of disabled provider.
+ fun toDisabledProviderList(
providerDataList: List<DisabledProviderData>?,
context: Context,
- ): List<DisabledProviderInfo>? {
- // TODO: get from the actual service info
- val packageManager = context.packageManager
- return providerDataList?.map {
- val componentName = ComponentName.unflattenFromString(it.providerFlattenedComponentName)
- var packageName = componentName?.packageName
- if (componentName == null) {
- // TODO: Remove once test data is fixed
- packageName = it.providerFlattenedComponentName
+ ): List<DisabledProviderInfo> {
+ val providerList: MutableList<DisabledProviderInfo> = mutableListOf()
+ providerDataList?.forEach {
+ val providerLabelAndIcon = getServiceLabelAndIcon(
+ context.packageManager,
+ it.providerFlattenedComponentName
+ ) ?: return@forEach
+ val (providerLabel, providerIcon) = providerLabelAndIcon
+ providerList.add(DisabledProviderInfo(
+ icon = providerIcon,
+ id = it.providerFlattenedComponentName,
+ displayName = providerLabel,
+ ))
+ }
+ return providerList
}
- val pkgInfo = packageManager
- .getPackageInfo(packageName!!,
- PackageManager.PackageInfoFlags.of(0))
- DisabledProviderInfo(
- icon = pkgInfo.applicationInfo.loadIcon(packageManager)!!,
- name = it.providerFlattenedComponentName,
- displayName = pkgInfo.applicationInfo.loadLabel(packageManager).toString(),
- )
- }
- }
- fun toRequestDisplayInfo(
+ fun toRequestDisplayInfo(
requestInfo: RequestInfo,
context: Context,
- ): RequestDisplayInfo {
- val packageName = requestInfo.appPackageName
- val pkgInfo = context.packageManager.getPackageInfo(packageName,
- PackageManager.PackageInfoFlags.of(0))
- val appLabel = pkgInfo.applicationInfo.loadSafeLabel(context.packageManager, 0f,
- TextUtils.SAFE_STRING_FLAG_FIRST_LINE or TextUtils.SAFE_STRING_FLAG_TRIM)
- val createCredentialRequest = requestInfo.createCredentialRequest
- val createCredentialRequestJetpack = createCredentialRequest?.let {
- CreateCredentialRequest.createFrom(
- it.type, it.credentialData, it.candidateQueryData, it.isSystemProviderRequired()
- )
- }
- when (createCredentialRequestJetpack) {
- is CreatePasswordRequest -> {
- return RequestDisplayInfo(
- createCredentialRequestJetpack.id,
- createCredentialRequestJetpack.password,
- createCredentialRequestJetpack.type,
- appLabel.toString(),
- context.getDrawable(R.drawable.ic_password)!!
- )
+ ): RequestDisplayInfo? {
+ val appLabel = getAppLabel(context.packageManager, requestInfo.appPackageName)
+ ?: return null
+ val createCredentialRequest = requestInfo.createCredentialRequest
+ val createCredentialRequestJetpack = createCredentialRequest?.let {
+ CreateCredentialRequest.createFrom(
+ it.type, it.credentialData, it.candidateQueryData, it.isSystemProviderRequired
+ )
+ }
+ when (createCredentialRequestJetpack) {
+ is CreatePasswordRequest -> {
+ return RequestDisplayInfo(
+ createCredentialRequestJetpack.id,
+ createCredentialRequestJetpack.password,
+ createCredentialRequestJetpack.type,
+ appLabel,
+ context.getDrawable(R.drawable.ic_password)!!
+ )
+ }
+ is CreatePublicKeyCredentialRequest -> {
+ val requestJson = createCredentialRequestJetpack.requestJson
+ val json = JSONObject(requestJson)
+ var name = ""
+ var displayName = ""
+ if (json.has("user")) {
+ val user: JSONObject = json.getJSONObject("user")
+ name = user.getString("name")
+ displayName = user.getString("displayName")
+ }
+ return RequestDisplayInfo(
+ name,
+ displayName,
+ createCredentialRequestJetpack.type,
+ appLabel,
+ context.getDrawable(R.drawable.ic_passkey)!!
+ )
+ }
+ // TODO: correctly parsing for other sign-ins
+ else -> {
+ return RequestDisplayInfo(
+ "beckett-bakert@gmail.com",
+ "Elisa Beckett",
+ "other-sign-ins",
+ appLabel.toString(),
+ context.getDrawable(R.drawable.ic_other_sign_in)!!
+ )
+ }
+ }
}
- is CreatePublicKeyCredentialRequest -> {
- val requestJson = createCredentialRequestJetpack.requestJson
- val json = JSONObject(requestJson)
- var name = ""
- var displayName = ""
- if (json.has("user")) {
- val user: JSONObject = json.getJSONObject("user")
- name = user.getString("name")
- displayName = user.getString("displayName")
- }
- return RequestDisplayInfo(
- name,
- displayName,
- createCredentialRequestJetpack.type,
- appLabel.toString(),
- context.getDrawable(R.drawable.ic_passkey)!!)
- }
- // TODO: correctly parsing for other sign-ins
- else -> {
- return RequestDisplayInfo(
- "beckett-bakert@gmail.com",
- "Elisa Beckett",
- "other-sign-ins",
- appLabel.toString(),
- context.getDrawable(R.drawable.ic_other_sign_in)!!)
- }
- }
- }
- fun toCreateCredentialUiState(
+ fun toCreateCredentialUiState(
enabledProviders: List<EnabledProviderInfo>,
disabledProviders: List<DisabledProviderInfo>?,
defaultProviderId: String?,
requestDisplayInfo: RequestDisplayInfo,
isOnPasskeyIntroStateAlready: Boolean,
isPasskeyFirstUse: Boolean,
- ): CreateCredentialUiState {
- var lastSeenProviderWithNonEmptyCreateOptions: EnabledProviderInfo? = null
- var remoteEntry: RemoteInfo? = null
- var defaultProvider: EnabledProviderInfo? = null
- var createOptionsPairs:
- MutableList<Pair<CreateOptionInfo, EnabledProviderInfo>> = mutableListOf()
- enabledProviders.forEach {
- enabledProvider ->
- if (defaultProviderId != null) {
- if (enabledProvider.id == defaultProviderId) {
- defaultProvider = enabledProvider
- }
+ ): CreateCredentialUiState? {
+ var lastSeenProviderWithNonEmptyCreateOptions: EnabledProviderInfo? = null
+ var remoteEntry: RemoteInfo? = null
+ var defaultProvider: EnabledProviderInfo? = null
+ var createOptionsPairs:
+ MutableList<Pair<CreateOptionInfo, EnabledProviderInfo>> = mutableListOf()
+ enabledProviders.forEach { enabledProvider ->
+ if (defaultProviderId != null) {
+ if (enabledProvider.id == defaultProviderId) {
+ defaultProvider = enabledProvider
+ }
+ }
+ if (enabledProvider.createOptions.isNotEmpty()) {
+ lastSeenProviderWithNonEmptyCreateOptions = enabledProvider
+ enabledProvider.createOptions.forEach {
+ createOptionsPairs.add(Pair(it, enabledProvider))
+ }
+ }
+ if (enabledProvider.remoteEntry != null) {
+ remoteEntry = enabledProvider.remoteEntry!!
+ }
+ }
+ val initialScreenState = toCreateScreenState(
+ /*createOptionSize=*/createOptionsPairs.size,
+ /*isOnPasskeyIntroStateAlready=*/isOnPasskeyIntroStateAlready,
+ /*requestDisplayInfo=*/requestDisplayInfo,
+ /*defaultProvider=*/defaultProvider, /*remoteEntry=*/remoteEntry,
+ /*isPasskeyFirstUse=*/isPasskeyFirstUse
+ )
+ if (initialScreenState == null) {
+ return null
+ }
+ return CreateCredentialUiState(
+ enabledProviders = enabledProviders,
+ disabledProviders = disabledProviders,
+ currentScreenState = initialScreenState,
+ requestDisplayInfo = requestDisplayInfo,
+ sortedCreateOptionsPairs = createOptionsPairs.sortedWith(
+ compareByDescending { it.first.lastUsedTimeMillis }
+ ),
+ hasDefaultProvider = defaultProvider != null,
+ activeEntry = toActiveEntry(
+ /*defaultProvider=*/defaultProvider,
+ /*createOptionSize=*/createOptionsPairs.size,
+ /*lastSeenProviderWithNonEmptyCreateOptions=*/
+ lastSeenProviderWithNonEmptyCreateOptions,
+ /*remoteEntry=*/remoteEntry
+ ),
+ )
}
- if (enabledProvider.createOptions.isNotEmpty()) {
- lastSeenProviderWithNonEmptyCreateOptions = enabledProvider
- enabledProvider.createOptions.forEach {
- createOptionsPairs.add(Pair(it, enabledProvider))
- }
- }
- if (enabledProvider.remoteEntry != null) {
- remoteEntry = enabledProvider.remoteEntry!!
- }
- }
- return CreateCredentialUiState(
- enabledProviders = enabledProviders,
- disabledProviders = disabledProviders,
- toCreateScreenState(
- /*createOptionSize=*/createOptionsPairs.size,
- /*isOnPasskeyIntroStateAlready=*/isOnPasskeyIntroStateAlready,
- /*requestDisplayInfo=*/requestDisplayInfo,
- /*defaultProvider=*/defaultProvider, /*remoteEntry=*/remoteEntry,
- /*isPasskeyFirstUse=*/isPasskeyFirstUse),
- requestDisplayInfo,
- createOptionsPairs.sortedWith(compareByDescending{ it.first.lastUsedTimeMillis }),
- defaultProvider != null,
- toActiveEntry(
- /*defaultProvider=*/defaultProvider,
- /*createOptionSize=*/createOptionsPairs.size,
- /*lastSeenProviderWithNonEmptyCreateOptions=*/
- lastSeenProviderWithNonEmptyCreateOptions,
- /*remoteEntry=*/remoteEntry),
- )
- }
- private fun toCreateScreenState(
+ private fun toCreateScreenState(
createOptionSize: Int,
isOnPasskeyIntroStateAlready: Boolean,
requestDisplayInfo: RequestDisplayInfo,
defaultProvider: EnabledProviderInfo?,
remoteEntry: RemoteInfo?,
isPasskeyFirstUse: Boolean,
- ): CreateScreenState {
- return if (
- isPasskeyFirstUse && requestDisplayInfo
- .type == TYPE_PUBLIC_KEY_CREDENTIAL && !isOnPasskeyIntroStateAlready) {
- CreateScreenState.PASSKEY_INTRO
- } else if (
- (defaultProvider == null || defaultProvider.createOptions.isEmpty()
- ) && createOptionSize > 1) {
- CreateScreenState.PROVIDER_SELECTION
- } else if (
- ((defaultProvider == null || defaultProvider.createOptions.isEmpty()
- ) && createOptionSize == 1) || (
- defaultProvider != null && defaultProvider.createOptions.isNotEmpty())) {
- CreateScreenState.CREATION_OPTION_SELECTION
- } else if (createOptionSize == 0 && remoteEntry != null) {
- CreateScreenState.EXTERNAL_ONLY_SELECTION
- } else {
- // TODO: properly handle error and gracefully finish itself
- throw java.lang.IllegalStateException("Empty provider list.")
- }
- }
+ ): CreateScreenState? {
+ return if (isPasskeyFirstUse && requestDisplayInfo.type ==
+ TYPE_PUBLIC_KEY_CREDENTIAL && !isOnPasskeyIntroStateAlready) {
+ CreateScreenState.PASSKEY_INTRO
+ } else if ((defaultProvider == null || defaultProvider.createOptions.isEmpty()) &&
+ createOptionSize > 1) {
+ CreateScreenState.PROVIDER_SELECTION
+ } else if (((defaultProvider == null || defaultProvider.createOptions.isEmpty()) &&
+ createOptionSize == 1) || (defaultProvider != null &&
+ defaultProvider.createOptions.isNotEmpty())) {
+ CreateScreenState.CREATION_OPTION_SELECTION
+ } else if (createOptionSize == 0 && remoteEntry != null) {
+ CreateScreenState.EXTERNAL_ONLY_SELECTION
+ } else {
+ Log.d(
+ Constants.LOG_TAG,
+ "Unexpected failure: the screen state failed to instantiate" +
+ " because the provider list is empty."
+ )
+ null
+ }
+ }
- private fun toActiveEntry(
+ private fun toActiveEntry(
defaultProvider: EnabledProviderInfo?,
createOptionSize: Int,
lastSeenProviderWithNonEmptyCreateOptions: EnabledProviderInfo?,
remoteEntry: RemoteInfo?,
- ): ActiveEntry? {
- return if (
- defaultProvider != null && defaultProvider.createOptions.isEmpty() &&
- remoteEntry != null) {
- ActiveEntry(defaultProvider, remoteEntry)
- } else if (
- defaultProvider != null && defaultProvider.createOptions.isNotEmpty()
- ) {
- ActiveEntry(defaultProvider, defaultProvider.createOptions.first())
- } else if (createOptionSize == 1) {
- ActiveEntry(lastSeenProviderWithNonEmptyCreateOptions!!,
- lastSeenProviderWithNonEmptyCreateOptions.createOptions.first())
- } else null
- }
+ ): ActiveEntry? {
+ return if (
+ defaultProvider != null && defaultProvider.createOptions.isEmpty() &&
+ remoteEntry != null
+ ) {
+ ActiveEntry(defaultProvider, remoteEntry)
+ } else if (
+ defaultProvider != null && defaultProvider.createOptions.isNotEmpty()
+ ) {
+ ActiveEntry(defaultProvider, defaultProvider.createOptions.first())
+ } else if (createOptionSize == 1) {
+ ActiveEntry(
+ lastSeenProviderWithNonEmptyCreateOptions!!,
+ lastSeenProviderWithNonEmptyCreateOptions.createOptions.first()
+ )
+ } else null
+ }
- private fun toCreationOptionInfoList(
+ private fun toCreationOptionInfoList(
providerId: String,
creationEntries: List<Entry>,
context: Context,
- ): List<CreateOptionInfo> {
- return creationEntries.map {
- // TODO: handle NPE gracefully
- val createEntry = CreateEntry.fromSlice(it.slice)!!
+ ): List<CreateOptionInfo> {
+ return creationEntries.map {
+ // TODO: handle NPE gracefully
+ val createEntry = CreateEntry.fromSlice(it.slice)!!
- return@map CreateOptionInfo(
- // TODO: remove fallbacks
- providerId = providerId,
- entryKey = it.key,
- entrySubkey = it.subkey,
- pendingIntent = createEntry.pendingIntent,
- fillInIntent = it.frameworkExtrasIntent,
- userProviderDisplayName = createEntry.accountName.toString(),
- profileIcon = createEntry.icon?.loadDrawable(context),
- passwordCount = CredentialCountInformation.getPasswordCount(
- createEntry.credentialCountInformationList) ?: 0,
- passkeyCount = CredentialCountInformation.getPasskeyCount(
- createEntry.credentialCountInformationList) ?: 0,
- totalCredentialCount = CredentialCountInformation.getTotalCount(
- createEntry.credentialCountInformationList) ?: 0,
- lastUsedTimeMillis = createEntry.lastUsedTimeMillis ?: 0,
- footerDescription = createEntry.footerDescription?.toString()
- )
- }
- }
+ return@map CreateOptionInfo(
+ // TODO: remove fallbacks
+ providerId = providerId,
+ entryKey = it.key,
+ entrySubkey = it.subkey,
+ pendingIntent = createEntry.pendingIntent,
+ fillInIntent = it.frameworkExtrasIntent,
+ userProviderDisplayName = createEntry.accountName.toString(),
+ profileIcon = createEntry.icon?.loadDrawable(context),
+ passwordCount = CredentialCountInformation.getPasswordCount(
+ createEntry.credentialCountInformationList
+ ) ?: 0,
+ passkeyCount = CredentialCountInformation.getPasskeyCount(
+ createEntry.credentialCountInformationList
+ ) ?: 0,
+ totalCredentialCount = CredentialCountInformation.getTotalCount(
+ createEntry.credentialCountInformationList
+ ) ?: 0,
+ lastUsedTimeMillis = createEntry.lastUsedTimeMillis ?: 0,
+ footerDescription = createEntry.footerDescription?.toString()
+ )
+ }
+ }
- private fun toRemoteInfo(
+ private fun toRemoteInfo(
providerId: String,
remoteEntry: Entry?,
- ): RemoteInfo? {
- // TODO: should also call fromSlice after getting the official jetpack code.
- return if (remoteEntry != null) {
- RemoteInfo(
- providerId = providerId,
- entryKey = remoteEntry.key,
- entrySubkey = remoteEntry.subkey,
- pendingIntent = remoteEntry.pendingIntent,
- fillInIntent = remoteEntry.frameworkExtrasIntent,
- )
- } else null
+ ): RemoteInfo? {
+ // TODO: should also call fromSlice after getting the official jetpack code.
+ return if (remoteEntry != null) {
+ RemoteInfo(
+ providerId = providerId,
+ entryKey = remoteEntry.key,
+ entrySubkey = remoteEntry.subkey,
+ pendingIntent = remoteEntry.pendingIntent,
+ fillInIntent = remoteEntry.frameworkExtrasIntent,
+ )
+ } else null
+ }
}
- }
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt
new file mode 100644
index 0000000..37e21a8
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/Constants.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.credentialmanager.common
+
+class Constants {
+ companion object Constants {
+ const val LOG_TAG = "CredentialSelector"
+ }
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt
index d3cf241..01318b1 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialViewModel.kt
@@ -25,6 +25,7 @@
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
+import com.android.credentialmanager.common.Constants
import com.android.credentialmanager.CreateFlowUtils
import com.android.credentialmanager.CredentialManagerRepo
import com.android.credentialmanager.UserConfigRepo
@@ -32,35 +33,16 @@
import com.android.credentialmanager.common.ProviderActivityResult
import com.android.credentialmanager.common.ProviderActivityState
-data class CreateCredentialUiState(
- val enabledProviders: List<EnabledProviderInfo>,
- val disabledProviders: List<DisabledProviderInfo>? = null,
- val currentScreenState: CreateScreenState,
- val requestDisplayInfo: RequestDisplayInfo,
- val sortedCreateOptionsPairs: List<Pair<CreateOptionInfo, EnabledProviderInfo>>,
- // Should not change with the real time update of default provider, only determine whether
- // we're showing provider selection page at the beginning
- val hasDefaultProvider: Boolean,
- val activeEntry: ActiveEntry? = null,
- val selectedEntry: EntryInfo? = null,
- val providerActivityState: ProviderActivityState =
- ProviderActivityState.NOT_APPLICABLE,
- val isFromProviderSelection: Boolean? = null,
- val dialogState: DialogState = DialogState.ACTIVE,
-)
class CreateCredentialViewModel(
private val credManRepo: CredentialManagerRepo,
+ private val providerEnableListUiState: List<EnabledProviderInfo>,
+ private val providerDisableListUiState: List<DisabledProviderInfo>,
+ private val requestDisplayInfoUiState: RequestDisplayInfo,
userConfigRepo: UserConfigRepo = UserConfigRepo.getInstance(),
) : ViewModel() {
- val providerEnableListUiState = credManRepo.getCreateProviderEnableListInitialUiState()
-
- val providerDisableListUiState = credManRepo.getCreateProviderDisableListInitialUiState()
-
- val requestDisplayInfoUiState = credManRepo.getCreateRequestDisplayInfoInitialUiState()
val defaultProviderId = userConfigRepo.getDefaultProviderId()
-
val isPasskeyFirstUse = userConfigRepo.getIsPasskeyFirstUse()
var uiState by mutableStateOf(
@@ -70,13 +52,18 @@
defaultProviderId,
requestDisplayInfoUiState,
false,
- isPasskeyFirstUse))
+ isPasskeyFirstUse)!!)
private set
fun onConfirmIntro() {
- uiState = CreateFlowUtils.toCreateCredentialUiState(
+ val newUiState = CreateFlowUtils.toCreateCredentialUiState(
providerEnableListUiState, providerDisableListUiState, defaultProviderId,
requestDisplayInfoUiState, true, isPasskeyFirstUse)
+ if (newUiState == null) {
+ onInternalError()
+ return
+ }
+ uiState = newUiState
UserConfigRepo.getInstance().setIsPasskeyFirstUse(false)
}
@@ -143,6 +130,14 @@
uiState = uiState.copy(dialogState = DialogState.CANCELED_FOR_SETTINGS)
}
+ // When the view model runs into unexpected illegal state, reports the error back and close
+ // the activity gracefully.
+ private fun onInternalError() {
+ Log.w(Constants.LOG_TAG, "UI closed due to illegal internal state")
+ credManRepo.onParsingFailureCancel()
+ uiState = uiState.copy(dialogState = DialogState.COMPLETE)
+ }
+
fun onCancel() {
credManRepo.onUserCancel()
uiState = uiState.copy(dialogState = DialogState.COMPLETE)
@@ -171,11 +166,11 @@
fun onDefaultChanged(providerId: String?) {
if (providerId != null) {
Log.d(
- "Account Selector", "Default provider changed to: " +
+ Constants.LOG_TAG, "Default provider changed to: " +
" {provider=$providerId")
UserConfigRepo.getInstance().setDefaultProvider(providerId)
} else {
- Log.w("Account Selector", "Null provider is being changed")
+ Log.w(Constants.LOG_TAG, "Null provider is being changed")
}
}
@@ -184,7 +179,7 @@
val entryKey = selectedEntry.entryKey
val entrySubkey = selectedEntry.entrySubkey
Log.d(
- "Account Selector", "Option selected for entry: " +
+ Constants.LOG_TAG, "Option selected for entry: " +
" {provider=$providerId, key=$entryKey, subkey=$entrySubkey")
if (selectedEntry.pendingIntent != null) {
uiState = uiState.copy(
@@ -211,7 +206,8 @@
.setFillInIntent(entry.fillInIntent).build()
launcher.launch(intentSenderRequest)
} else {
- Log.w("Account Selector", "No provider UI to launch")
+ Log.d(Constants.LOG_TAG, "Unexpected: no provider UI to launch")
+ onInternalError()
}
}
@@ -220,9 +216,9 @@
if (selectedEntry != null) {
onEntrySelected(selectedEntry)
} else {
- Log.w("Account Selector",
- "Illegal state: confirm is pressed but activeEntry isn't set.")
- uiState = uiState.copy(dialogState = DialogState.COMPLETE)
+ Log.d(Constants.LOG_TAG,
+ "Unexpected: confirm is pressed but no active entry exists.")
+ onInternalError()
}
}
@@ -232,7 +228,7 @@
val resultData = providerActivityResult.data
if (resultCode == Activity.RESULT_CANCELED) {
// Re-display the CredMan UI if the user canceled from the provider UI.
- Log.d("Account Selector", "The provider activity was cancelled," +
+ Log.d(Constants.LOG_TAG, "The provider activity was cancelled," +
" re-displaying our UI.")
uiState = uiState.copy(
selectedEntry = null,
@@ -241,18 +237,44 @@
} else {
if (entry != null) {
val providerId = entry.providerId
- Log.d("Account Selector", "Got provider activity result: {provider=" +
+ Log.d(Constants.LOG_TAG, "Got provider activity result: {provider=" +
"$providerId, key=${entry.entryKey}, subkey=${entry.entrySubkey}, " +
"resultCode=$resultCode, resultData=$resultData}"
)
credManRepo.onOptionSelected(
providerId, entry.entryKey, entry.entrySubkey, resultCode, resultData,
)
+ uiState = uiState.copy(dialogState = DialogState.COMPLETE)
} else {
- Log.w("Account Selector",
+ Log.d(Constants.LOG_TAG,
"Illegal state: received a provider result but found no matching entry.")
+ onInternalError()
}
- uiState = uiState.copy(dialogState = DialogState.COMPLETE)
+ }
+ }
+
+ companion object Factory {
+ // Validates the input and returns null if the input is invalid.
+ fun newInstance(
+ credManRepo: CredentialManagerRepo,
+ providerEnableListUiState: List<EnabledProviderInfo>,
+ providerDisableListUiState: List<DisabledProviderInfo>,
+ requestDisplayInfoUiState: RequestDisplayInfo?,
+ ): CreateCredentialViewModel? {
+ if (providerEnableListUiState.isEmpty() || requestDisplayInfoUiState == null) {
+ return null
+ }
+ return try {
+ val result = CreateCredentialViewModel(
+ credManRepo = credManRepo,
+ providerEnableListUiState = providerEnableListUiState,
+ providerDisableListUiState = providerDisableListUiState,
+ requestDisplayInfoUiState = requestDisplayInfoUiState
+ )
+ result
+ } catch (e: Exception) {
+ null
+ }
}
}
}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
index 957488f..12a5085 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
@@ -19,6 +19,25 @@
import android.app.PendingIntent
import android.content.Intent
import android.graphics.drawable.Drawable
+import com.android.credentialmanager.common.DialogState
+import com.android.credentialmanager.common.ProviderActivityState
+
+data class CreateCredentialUiState(
+ val enabledProviders: List<EnabledProviderInfo>,
+ val disabledProviders: List<DisabledProviderInfo>? = null,
+ val currentScreenState: CreateScreenState,
+ val requestDisplayInfo: RequestDisplayInfo,
+ val sortedCreateOptionsPairs: List<Pair<CreateOptionInfo, EnabledProviderInfo>>,
+ // Should not change with the real time update of default provider, only determine whether
+ // we're showing provider selection page at the beginning
+ val hasDefaultProvider: Boolean,
+ val activeEntry: ActiveEntry? = null,
+ val selectedEntry: EntryInfo? = null,
+ val providerActivityState: ProviderActivityState =
+ ProviderActivityState.NOT_APPLICABLE,
+ val isFromProviderSelection: Boolean? = null,
+ val dialogState: DialogState = DialogState.ACTIVE,
+)
open class ProviderInfo(
val icon: Drawable,
@@ -28,17 +47,17 @@
class EnabledProviderInfo(
icon: Drawable,
- name: String,
+ id: String,
displayName: String,
var createOptions: List<CreateOptionInfo>,
var remoteEntry: RemoteInfo?,
-) : ProviderInfo(icon, name, displayName)
+) : ProviderInfo(icon, id, displayName)
class DisabledProviderInfo(
icon: Drawable,
- name: String,
+ id: String,
displayName: String,
-) : ProviderInfo(icon, name, displayName)
+) : ProviderInfo(icon, id, displayName)
open class EntryInfo (
val providerId: String,
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt
index 065a2de..7d2f0da 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialViewModel.kt
@@ -26,6 +26,7 @@
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import com.android.credentialmanager.CredentialManagerRepo
+import com.android.credentialmanager.common.Constants
import com.android.credentialmanager.common.DialogState
import com.android.credentialmanager.common.ProviderActivityResult
import com.android.credentialmanager.common.ProviderActivityState
@@ -45,13 +46,16 @@
val dialogState: DialogState = DialogState.ACTIVE,
)
-class GetCredentialViewModel(private val credManRepo: CredentialManagerRepo) : ViewModel() {
+class GetCredentialViewModel(
+ private val credManRepo: CredentialManagerRepo,
+ initialUiState: GetCredentialUiState,
+) : ViewModel() {
- var uiState by mutableStateOf(credManRepo.getCredentialInitialUiState())
+ var uiState by mutableStateOf(initialUiState)
private set
fun onEntrySelected(entry: EntryInfo) {
- Log.d("Account Selector", "credential selected: {provider=${entry.providerId}" +
+ Log.d(Constants.LOG_TAG, "credential selected: {provider=${entry.providerId}" +
", key=${entry.entryKey}, subkey=${entry.entrySubkey}}")
if (entry.pendingIntent != null) {
uiState = uiState.copy(
@@ -69,9 +73,9 @@
if (activeEntry != null) {
onEntrySelected(activeEntry)
} else {
- Log.w("Account Selector",
+ Log.d(Constants.LOG_TAG,
"Illegal state: confirm is pressed but activeEntry isn't set.")
- uiState = uiState.copy(dialogState = DialogState.COMPLETE)
+ onInternalError()
}
}
@@ -80,23 +84,32 @@
) {
val entry = uiState.selectedEntry
if (entry != null && entry.pendingIntent != null) {
- Log.d("credentials", "Launching provider activity")
+ Log.d(Constants.LOG_TAG, "Launching provider activity")
uiState = uiState.copy(providerActivityState = ProviderActivityState.PENDING)
val intentSenderRequest = IntentSenderRequest.Builder(entry.pendingIntent)
.setFillInIntent(entry.fillInIntent).build()
launcher.launch(intentSenderRequest)
} else {
- Log.w("Account Selector", "No provider UI to launch")
+ Log.d(Constants.LOG_TAG, "No provider UI to launch")
+ onInternalError()
}
}
+ // When the view model runs into unexpected illegal state, reports the error back and close
+ // the activity gracefully.
+ private fun onInternalError() {
+ Log.w(Constants.LOG_TAG, "UI closed due to illegal internal state")
+ credManRepo.onParsingFailureCancel()
+ uiState = uiState.copy(dialogState = DialogState.COMPLETE)
+ }
+
fun onProviderActivityResult(providerActivityResult: ProviderActivityResult) {
val entry = uiState.selectedEntry
val resultCode = providerActivityResult.resultCode
val resultData = providerActivityResult.data
if (resultCode == Activity.RESULT_CANCELED) {
// Re-display the CredMan UI if the user canceled from the provider UI.
- Log.d("Account Selector", "The provider activity was cancelled," +
+ Log.d(Constants.LOG_TAG, "The provider activity was cancelled," +
" re-displaying our UI.")
uiState = uiState.copy(
selectedEntry = null,
@@ -104,7 +117,8 @@
)
} else {
if (entry != null) {
- Log.d("Account Selector", "Got provider activity result: {provider=" +
+ Log.d(
+ Constants.LOG_TAG, "Got provider activity result: {provider=" +
"${entry.providerId}, key=${entry.entryKey}, subkey=${entry.entrySubkey}" +
", resultCode=$resultCode, resultData=$resultData}"
)
@@ -112,23 +126,24 @@
entry.providerId, entry.entryKey, entry.entrySubkey,
resultCode, resultData,
)
+ uiState = uiState.copy(dialogState = DialogState.COMPLETE)
} else {
- Log.w("Account Selector",
+ Log.w(Constants.LOG_TAG,
"Illegal state: received a provider result but found no matching entry.")
+ onInternalError()
}
- uiState = uiState.copy(dialogState = DialogState.COMPLETE)
}
}
fun onMoreOptionSelected() {
- Log.d("Account Selector", "More Option selected")
+ Log.d(Constants.LOG_TAG, "More Option selected")
uiState = uiState.copy(
currentScreenState = GetScreenState.ALL_SIGN_IN_OPTIONS
)
}
fun onMoreOptionOnSnackBarSelected(isNoAccount: Boolean) {
- Log.d("Account Selector", "More Option on snackBar selected")
+ Log.d(Constants.LOG_TAG, "More Option on snackBar selected")
uiState = uiState.copy(
currentScreenState = GetScreenState.ALL_SIGN_IN_OPTIONS,
isNoAccount = isNoAccount,
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
index 4e96dda..cfc38df 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
@@ -33,8 +33,8 @@
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.LocalContentColor
-import androidx.compose.material3.LocalMinimumTouchTargetEnforcement
import androidx.compose.material3.contentColorFor
+import androidx.compose.material3.minimumInteractiveComponentSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
@@ -65,21 +65,17 @@
import androidx.compose.ui.graphics.drawscope.scale
import androidx.compose.ui.layout.boundsInRoot
import androidx.compose.ui.layout.findRootCoordinates
-import androidx.compose.ui.layout.layout
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewTreeLifecycleOwner
import androidx.lifecycle.ViewTreeViewModelStoreOwner
-import com.android.compose.runtime.movableContentOf
import com.android.systemui.animation.Expandable
import com.android.systemui.animation.LaunchAnimator
import kotlin.math.max
import kotlin.math.min
-import kotlin.math.roundToInt
/**
* Create an expandable shape that can launch into an Activity or a Dialog.
@@ -220,21 +216,8 @@
// If this expandable is expanded when it's being directly clicked on, let's ensure that it has
// the minimum interactive size followed by all M3 components (48.dp).
val minInteractiveSizeModifier =
- if (onClick != null && LocalMinimumTouchTargetEnforcement.current) {
- // TODO(b/242040009): Replace this by Modifier.minimumInteractiveComponentSize() once
- // http://aosp/2305511 is available.
- val minTouchSize = LocalViewConfiguration.current.minimumTouchTargetSize
- Modifier.layout { measurable, constraints ->
- // Copied from androidx.compose.material3.InteractiveComponentSize.kt
- val placeable = measurable.measure(constraints)
- val width = maxOf(placeable.width, minTouchSize.width.roundToPx())
- val height = maxOf(placeable.height, minTouchSize.height.roundToPx())
- layout(width, height) {
- val centerX = ((width - placeable.width) / 2f).roundToInt()
- val centerY = ((height - placeable.height) / 2f).roundToInt()
- placeable.place(centerX, centerY)
- }
- }
+ if (onClick != null) {
+ Modifier.minimumInteractiveComponentSize()
} else {
Modifier
}
diff --git a/packages/SystemUI/docs/device-entry/quickaffordance.md b/packages/SystemUI/docs/device-entry/quickaffordance.md
index ccb35fa..79d5718 100644
--- a/packages/SystemUI/docs/device-entry/quickaffordance.md
+++ b/packages/SystemUI/docs/device-entry/quickaffordance.md
@@ -52,6 +52,10 @@
* Unselect an already-selected quick affordance from a slot
* Unselect all already-selected quick affordances from a slot
+## Testing
+* Add a unit test for your implementation of `KeyguardQuickAffordanceConfig`
+* Manually verify that your implementation works in multi-user environments from both the main user and a secondary user
+
## Debugging
To see the current state of the system, you can run `dumpsys`:
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
index db88b59..314c736 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
@@ -171,7 +171,7 @@
a1 = TonalSpec(HueSource(), ChromaConstant(36.0)),
a2 = TonalSpec(HueSource(), ChromaConstant(16.0)),
a3 = TonalSpec(HueAdd(60.0), ChromaConstant(24.0)),
- n1 = TonalSpec(HueSource(), ChromaConstant(6.0)),
+ n1 = TonalSpec(HueSource(), ChromaConstant(4.0)),
n2 = TonalSpec(HueSource(), ChromaConstant(8.0))
)),
VIBRANT(CoreSpec(
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher.xml b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher.xml
index 2cac9c7..90851e2 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher.xml
@@ -45,7 +45,7 @@
android:id="@+id/user_switcher_header"
android:textDirection="locale"
android:layout_width="@dimen/bouncer_user_switcher_width"
- android:layout_height="wrap_content" />
+ android:layout_height="match_parent" />
</com.android.keyguard.KeyguardUserSwitcherAnchor>
</LinearLayout>
diff --git a/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml b/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml
index a1068c6..6c8db91 100644
--- a/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml
@@ -25,9 +25,6 @@
<!-- Margin around the various security views -->
<dimen name="keyguard_security_view_top_margin">12dp</dimen>
- <!-- Padding for the lock icon on the keyguard -->
- <dimen name="lock_icon_padding">16dp</dimen>
-
<!-- Overload default clock widget parameters -->
<dimen name="widget_big_font_size">100dp</dimen>
<dimen name="widget_label_font_size">18sp</dimen>
diff --git a/packages/SystemUI/res/layout/clipboard_overlay_legacy.xml b/packages/SystemUI/res/layout/clipboard_overlay_legacy.xml
deleted file mode 100644
index 1a1fc75..0000000
--- a/packages/SystemUI/res/layout/clipboard_overlay_legacy.xml
+++ /dev/null
@@ -1,160 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2021 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<com.android.systemui.screenshot.DraggableConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/clipboard_ui"
- android:theme="@style/FloatingOverlay"
- android:alpha="0"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:contentDescription="@string/clipboard_overlay_window_name">
- <ImageView
- android:id="@+id/actions_container_background"
- android:visibility="gone"
- android:layout_height="0dp"
- android:layout_width="0dp"
- android:elevation="4dp"
- android:background="@drawable/action_chip_container_background"
- android:layout_marginStart="@dimen/overlay_action_container_margin_horizontal"
- app:layout_constraintBottom_toBottomOf="@+id/actions_container"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="@+id/actions_container"
- app:layout_constraintEnd_toEndOf="@+id/actions_container"/>
- <HorizontalScrollView
- android:id="@+id/actions_container"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginEnd="@dimen/overlay_action_container_margin_horizontal"
- android:paddingEnd="@dimen/overlay_action_container_padding_right"
- android:paddingVertical="@dimen/overlay_action_container_padding_vertical"
- android:elevation="4dp"
- android:scrollbars="none"
- android:layout_marginBottom="4dp"
- app:layout_constraintHorizontal_bias="0"
- app:layout_constraintWidth_percent="1.0"
- app:layout_constraintWidth_max="wrap"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@+id/preview_border"
- app:layout_constraintEnd_toEndOf="parent">
- <LinearLayout
- android:id="@+id/actions"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:animateLayoutChanges="true">
- <include layout="@layout/overlay_action_chip"
- android:id="@+id/share_chip"/>
- <include layout="@layout/overlay_action_chip"
- android:id="@+id/remote_copy_chip"/>
- <include layout="@layout/overlay_action_chip"
- android:id="@+id/edit_chip"/>
- </LinearLayout>
- </HorizontalScrollView>
- <View
- android:id="@+id/preview_border"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_marginStart="@dimen/overlay_offset_x"
- android:layout_marginBottom="12dp"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- android:elevation="7dp"
- app:layout_constraintEnd_toEndOf="@id/clipboard_preview_end"
- app:layout_constraintTop_toTopOf="@id/clipboard_preview_top"
- android:background="@drawable/overlay_border"/>
- <androidx.constraintlayout.widget.Barrier
- android:id="@+id/clipboard_preview_end"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- app:barrierMargin="@dimen/overlay_border_width"
- app:barrierDirection="end"
- app:constraint_referenced_ids="clipboard_preview"/>
- <androidx.constraintlayout.widget.Barrier
- android:id="@+id/clipboard_preview_top"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- app:barrierDirection="top"
- app:barrierMargin="@dimen/overlay_border_width_neg"
- app:constraint_referenced_ids="clipboard_preview"/>
- <FrameLayout
- android:id="@+id/clipboard_preview"
- android:elevation="7dp"
- android:background="@drawable/overlay_preview_background"
- android:clipChildren="true"
- android:clipToOutline="true"
- android:clipToPadding="true"
- android:layout_width="@dimen/clipboard_preview_size"
- android:layout_margin="@dimen/overlay_border_width"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- app:layout_constraintBottom_toBottomOf="@id/preview_border"
- app:layout_constraintStart_toStartOf="@id/preview_border"
- app:layout_constraintEnd_toEndOf="@id/preview_border"
- app:layout_constraintTop_toTopOf="@id/preview_border">
- <TextView android:id="@+id/text_preview"
- android:textFontWeight="500"
- android:padding="8dp"
- android:gravity="center|start"
- android:ellipsize="end"
- android:autoSizeTextType="uniform"
- android:autoSizeMinTextSize="@dimen/clipboard_overlay_min_font"
- android:autoSizeMaxTextSize="@dimen/clipboard_overlay_max_font"
- android:textColor="?attr/overlayButtonTextColor"
- android:textColorLink="?attr/overlayButtonTextColor"
- android:background="?androidprv:attr/colorAccentSecondary"
- android:layout_width="@dimen/clipboard_preview_size"
- android:layout_height="@dimen/clipboard_preview_size"/>
- <ImageView
- android:id="@+id/image_preview"
- android:scaleType="fitCenter"
- android:adjustViewBounds="true"
- android:contentDescription="@string/clipboard_image_preview"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
- <TextView
- android:id="@+id/hidden_preview"
- android:visibility="gone"
- android:textFontWeight="500"
- android:padding="8dp"
- android:gravity="center"
- android:textSize="14sp"
- android:textColor="?attr/overlayButtonTextColor"
- android:background="?androidprv:attr/colorAccentSecondary"
- android:layout_width="@dimen/clipboard_preview_size"
- android:layout_height="@dimen/clipboard_preview_size"/>
- </FrameLayout>
- <FrameLayout
- android:id="@+id/dismiss_button"
- android:layout_width="@dimen/overlay_dismiss_button_tappable_size"
- android:layout_height="@dimen/overlay_dismiss_button_tappable_size"
- android:elevation="10dp"
- android:visibility="gone"
- android:alpha="0"
- app:layout_constraintStart_toEndOf="@id/clipboard_preview"
- app:layout_constraintEnd_toEndOf="@id/clipboard_preview"
- app:layout_constraintTop_toTopOf="@id/clipboard_preview"
- app:layout_constraintBottom_toTopOf="@id/clipboard_preview"
- android:contentDescription="@string/clipboard_dismiss_description">
- <ImageView
- android:id="@+id/dismiss_image"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_margin="@dimen/overlay_dismiss_button_margin"
- android:src="@drawable/overlay_cancel"/>
- </FrameLayout>
-</com.android.systemui.screenshot.DraggableConstraintLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 3c860a9..a11ffcd 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -141,7 +141,7 @@
android:id="@+id/lock_icon_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@drawable/fingerprint_bg"
+ android:src="@drawable/fingerprint_bg"
android:visibility="invisible"/>
<ImageView
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
index ef2247f..0cbf1db 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSampler.kt
@@ -114,7 +114,25 @@
/** Dump region sampler */
fun dump(pw: PrintWriter) {
- regionSampler?.dump(pw)
+ pw.println("[RegionSampler]")
+ pw.println("regionSamplingEnabled: $regionSamplingEnabled")
+ pw.println("regionDarkness: $regionDarkness")
+ pw.println("lightForegroundColor: ${Integer.toHexString(lightForegroundColor)}")
+ pw.println("darkForegroundColor:${Integer.toHexString(darkForegroundColor)}")
+ pw.println("passed-in sampledView: $sampledView")
+ pw.println("calculated samplingBounds: $samplingBounds")
+ pw.println(
+ "sampledView width: ${sampledView?.width}, sampledView height: ${sampledView?.height}"
+ )
+ pw.println("screen width: ${displaySize.x}, screen height: ${displaySize.y}")
+ pw.println(
+ "sampledRegionWithOffset: ${convertBounds(calculateSampledRegion(sampledView!!))}"
+ )
+ pw.println(
+ "initialSampling for lockscreen: " +
+ "${wallpaperManager?.getWallpaperColors(WallpaperManager.FLAG_LOCK)}"
+ )
+ // TODO(b/265969235): add initialSampling dump for HS smartspace
}
fun calculateSampledRegion(sampledView: View): RectF {
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 1680b47..b1ce54e 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -28,10 +28,12 @@
import androidx.annotation.VisibleForTesting
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags.DOZING_MIGRATION_1
import com.android.systemui.flags.Flags.REGION_SAMPLING
@@ -77,8 +79,9 @@
@Background private val bgExecutor: Executor,
@KeyguardSmallClockLog private val smallLogBuffer: LogBuffer?,
@KeyguardLargeClockLog private val largeLogBuffer: LogBuffer?,
- private val featureFlags: FeatureFlags
-) {
+ private val featureFlags: FeatureFlags,
+ private val dumpManager: DumpManager
+) : Dumpable {
var clock: ClockController? = null
set(value) {
field = value
@@ -275,6 +278,7 @@
configurationController.addCallback(configListener)
batteryController.addCallback(batteryCallback)
keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
+ dumpManager.registerDumpable(this)
disposableHandle = parent.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.STARTED) {
listenForDozing(this)
@@ -300,6 +304,7 @@
batteryController.removeCallback(batteryCallback)
keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
regionSampler?.stopRegionSampler()
+ dumpManager.unregisterDumpable(javaClass.simpleName)
}
private fun updateFontSizes() {
@@ -312,7 +317,7 @@
/**
* Dump information for debugging
*/
- fun dump(pw: PrintWriter) {
+ override fun dump(pw: PrintWriter, args: Array<out String>) {
pw.println(this)
clock?.dump(pw)
regionSampler?.dump(pw)
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 5fd2fab..9f07a20 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -92,6 +92,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.settingslib.Utils;
+import com.android.settingslib.drawable.CircleFramedDrawable;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
@@ -999,8 +1000,10 @@
private Drawable findUserIcon(int userId) {
Bitmap userIcon = UserManager.get(mView.getContext()).getUserIcon(userId);
if (userIcon != null) {
- return new BitmapDrawable(userIcon);
+ return CircleFramedDrawable.getInstance(mView.getContext(),
+ userIcon);
}
+
return UserIcons.getDefaultUserIcon(mResources, userId, false);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 9eb7e2cd..afa9ef6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -929,7 +929,7 @@
@Override
public void run() {
mLogger.logRetryAfterFpHwUnavailable(mHardwareFingerprintUnavailableRetryCount);
- if (mFpm.isHardwareDetected()) {
+ if (!mFingerprintSensorProperties.isEmpty()) {
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
} else if (mHardwareFingerprintUnavailableRetryCount < HAL_ERROR_RETRY_MAX) {
mHardwareFingerprintUnavailableRetryCount++;
@@ -1938,6 +1938,11 @@
}
}
mGoingToSleep = true;
+ // Resetting assistant visibility state as the device is going to sleep now.
+ // TaskStackChangeListener gets triggered a little late when we transition to AoD,
+ // which results in face auth running once on AoD.
+ mAssistantVisible = false;
+ mLogger.d("Started going to sleep, mGoingToSleep=true, mAssistantVisible=false");
updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE, FACE_AUTH_UPDATED_GOING_TO_SLEEP);
}
@@ -2341,14 +2346,13 @@
}
private void updateFaceEnrolled(int userId) {
- mIsFaceEnrolled = whitelistIpcs(
- () -> mFaceManager != null && mFaceManager.isHardwareDetected()
- && mBiometricEnabledForUser.get(userId))
+ mIsFaceEnrolled = mFaceManager != null && !mFaceSensorProperties.isEmpty()
+ && mBiometricEnabledForUser.get(userId)
&& mAuthController.isFaceAuthEnrolled(userId);
}
public boolean isFaceSupported() {
- return mFaceManager != null && mFaceManager.isHardwareDetected();
+ return mFaceManager != null && !mFaceSensorProperties.isEmpty();
}
/**
@@ -2967,7 +2971,8 @@
@VisibleForTesting
boolean isUnlockWithFingerprintPossible(int userId) {
// TODO (b/242022358), make this rely on onEnrollmentChanged event and update it only once.
- mIsUnlockWithFingerprintPossible.put(userId, mFpm != null && mFpm.isHardwareDetected()
+ mIsUnlockWithFingerprintPossible.put(userId, mFpm != null
+ && !mFingerprintSensorProperties.isEmpty()
&& !isFingerprintDisabled(userId) && mFpm.hasEnrolledTemplates(userId));
return mIsUnlockWithFingerprintPossible.get(userId);
}
@@ -3332,7 +3337,8 @@
/**
* Handle {@link #MSG_KEYGUARD_RESET}
*/
- private void handleKeyguardReset() {
+ @VisibleForTesting
+ protected void handleKeyguardReset() {
mLogger.d("handleKeyguardReset");
updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE,
FACE_AUTH_UPDATED_KEYGUARD_RESET);
@@ -3887,7 +3893,7 @@
for (int subId : mServiceStates.keySet()) {
pw.println(" " + subId + "=" + mServiceStates.get(subId));
}
- if (mFpm != null && mFpm.isHardwareDetected()) {
+ if (mFpm != null && !mFingerprintSensorProperties.isEmpty()) {
final int userId = mUserTracker.getUserId();
final int strongAuthFlags = mStrongAuthTracker.getStrongAuthForUser(userId);
BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId);
@@ -3936,7 +3942,7 @@
mFingerprintListenBuffer.toList()
).printTableData(pw);
}
- if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
+ if (mFaceManager != null && !mFaceSensorProperties.isEmpty()) {
final int userId = mUserTracker.getUserId();
final int strongAuthFlags = mStrongAuthTracker.getStrongAuthForUser(userId);
BiometricAuthenticated face = mUserFaceAuthenticated.get(userId);
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconView.java b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
index 34a5ef7..abad0be 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconView.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
@@ -88,7 +88,9 @@
Utils.getColorAttrDefaultColor(getContext(), android.R.attr.textColorPrimary),
Color.WHITE,
mDozeAmount);
- mBgView.setBackground(getContext().getDrawable(R.drawable.fingerprint_bg));
+ int backgroundColor = Utils.getColorAttrDefaultColor(getContext(),
+ com.android.internal.R.attr.colorSurface);
+ mBgView.setImageTintList(ColorStateList.valueOf(backgroundColor));
mBgView.setAlpha(1f - mDozeAmount);
mBgView.setVisibility(View.VISIBLE);
} else {
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 1bf63e5..413a3ca 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -431,6 +431,7 @@
pw.println(" mStatusBarState: " + StatusBarState.toString(mStatusBarState));
pw.println(" mInterpolatedDarkAmount: " + mInterpolatedDarkAmount);
pw.println(" mSensorTouchLocation: " + mSensorTouchLocation);
+ pw.println(" mDefaultPaddingPx: " + mDefaultPaddingPx);
if (mView != null) {
mView.dump(pw, args);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index 4b57d45..04a2689 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -55,11 +55,11 @@
private val fadeDuration = 83L
private val retractDuration = 400L
private var alphaInDuration: Long = 0
- private var unlockedRippleInProgress: Boolean = false
private val dwellShader = DwellRippleShader()
private val dwellPaint = Paint()
private val rippleShader = RippleShader()
private val ripplePaint = Paint()
+ private var unlockedRippleAnimator: AnimatorSet? = null
private var fadeDwellAnimator: Animator? = null
private var retractDwellAnimator: Animator? = null
private var dwellPulseOutAnimator: Animator? = null
@@ -205,7 +205,7 @@
* Plays a ripple animation that grows to the dwellRadius with distortion.
*/
fun startDwellRipple(isDozing: Boolean) {
- if (unlockedRippleInProgress || dwellPulseOutAnimator?.isRunning == true) {
+ if (unlockedRippleAnimator?.isRunning == true || dwellPulseOutAnimator?.isRunning == true) {
return
}
@@ -262,9 +262,7 @@
* Ripple that bursts outwards from the position of the sensor to the edges of the screen
*/
fun startUnlockedRipple(onAnimationEnd: Runnable?) {
- if (unlockedRippleInProgress) {
- return // Ignore if ripple effect is already playing
- }
+ unlockedRippleAnimator?.cancel()
val rippleAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
interpolator = Interpolators.LINEAR_OUT_SLOW_IN
@@ -289,14 +287,13 @@
}
}
- val animatorSet = AnimatorSet().apply {
+ unlockedRippleAnimator = AnimatorSet().apply {
playTogether(
rippleAnimator,
alphaInAnimator
)
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator?) {
- unlockedRippleInProgress = true
rippleShader.rippleFill = false
drawRipple = true
visibility = VISIBLE
@@ -304,13 +301,13 @@
override fun onAnimationEnd(animation: Animator?) {
onAnimationEnd?.run()
- unlockedRippleInProgress = false
drawRipple = false
visibility = GONE
+ unlockedRippleAnimator = null
}
})
}
- animatorSet.start()
+ unlockedRippleAnimator?.start()
}
fun resetRippleAlpha() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
index 6f594d5..c799e91 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
@@ -54,12 +54,18 @@
import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.recents.OverviewProxyService
import com.android.systemui.util.concurrency.DelayableExecutor
import java.io.PrintWriter
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
private const val TAG = "SideFpsController"
@@ -79,6 +85,9 @@
displayManager: DisplayManager,
@Main private val mainExecutor: DelayableExecutor,
@Main private val handler: Handler,
+ private val alternateBouncerInteractor: AlternateBouncerInteractor,
+ @Application private val scope: CoroutineScope,
+ private val featureFlags: FeatureFlags,
dumpManager: DumpManager
) : Dumpable {
val requests: HashSet<SideFpsUiRequestSource> = HashSet()
@@ -168,9 +177,26 @@
}
)
overviewProxyService.addCallback(overviewProxyListener)
+ listenForAlternateBouncerVisibility()
+
dumpManager.registerDumpable(this)
}
+ private fun listenForAlternateBouncerVisibility() {
+ alternateBouncerInteractor.setAlternateBouncerUIAvailable(true)
+ if (featureFlags.isEnabled(Flags.MODERN_ALTERNATE_BOUNCER)) {
+ scope.launch {
+ alternateBouncerInteractor.isVisible.collect { isVisible: Boolean ->
+ if (isVisible) {
+ show(SideFpsUiRequestSource.ALTERNATE_BOUNCER)
+ } else {
+ hide(SideFpsUiRequestSource.ALTERNATE_BOUNCER)
+ }
+ }
+ }
+ }
+ }
+
/** Shows the side fps overlay if not already shown. */
fun show(request: SideFpsUiRequestSource) {
requests.add(request)
@@ -423,4 +449,5 @@
AUTO_SHOW,
/** Pin, pattern or password bouncer */
PRIMARY_BOUNCER,
+ ALTERNATE_BOUNCER
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index b4b3fae..6680787 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -262,7 +262,9 @@
}
REASON_AUTH_KEYGUARD -> {
UdfpsKeyguardViewController(
- view.addUdfpsView(R.layout.udfps_keyguard_view),
+ view.addUdfpsView(R.layout.udfps_keyguard_view) {
+ updateSensorLocation(sensorBounds)
+ },
statusBarStateController,
shadeExpansionStateManager,
statusBarKeyguardViewManager,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
index 4017665..c82e6e1 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
@@ -68,10 +68,7 @@
mEnrollHelper = enrollHelper;
mView.setEnrollHelper(mEnrollHelper);
mView.setProgressBarRadius(mEnrollProgressBarRadius);
-
- if (featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
- mView.mUseExpandedOverlay = true;
- }
+ mView.mUseExpandedOverlay = featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
index 339b8ca..ee9081c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
+import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.MathUtils;
@@ -34,6 +35,7 @@
import android.widget.ImageView;
import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
@@ -65,6 +67,7 @@
private AnimatorSet mBackgroundInAnimator = new AnimatorSet();
private int mAlpha; // 0-255
private float mScaleFactor = 1;
+ private Rect mSensorBounds = new Rect();
// AOD anti-burn-in offsets
private final int mMaxBurnInOffsetX;
@@ -76,8 +79,6 @@
private int mAnimationType = ANIMATION_NONE;
private boolean mFullyInflated;
- private LayoutParams mParams;
-
public UdfpsKeyguardView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mFingerprintDrawable = new UdfpsFpDrawable(context);
@@ -88,10 +89,7 @@
.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
}
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
+ public void startIconAsyncInflate() {
// inflate Lottie views on a background thread in case it takes a while to inflate
AsyncLayoutInflater inflater = new AsyncLayoutInflater(mContext);
inflater.inflate(R.layout.udfps_keyguard_view_internal, this,
@@ -242,20 +240,8 @@
updateAlpha();
}
- @Override
- void onSensorRectUpdated(RectF bounds) {
- super.onSensorRectUpdated(bounds);
-
- if (mUseExpandedOverlay) {
- mParams = new LayoutParams((int) bounds.width(), (int) bounds.height());
- RectF converted = getBoundsRelativeToView(bounds);
- mParams.setMargins(
- (int) converted.left,
- (int) converted.top,
- (int) converted.right,
- (int) converted.bottom
- );
- }
+ void updateSensorLocation(@NonNull Rect sensorBounds) {
+ mSensorBounds.set(sensorBounds);
}
/**
@@ -313,7 +299,17 @@
updateAlpha();
if (mUseExpandedOverlay) {
- parent.addView(view, mParams);
+ final LayoutParams lp = (LayoutParams) view.getLayoutParams();
+ lp.width = mSensorBounds.width();
+ lp.height = mSensorBounds.height();
+ RectF relativeToView = getBoundsRelativeToView(new RectF(mSensorBounds));
+ lp.setMargins(
+ (int) relativeToView.left,
+ (int) relativeToView.top,
+ (int) relativeToView.right,
+ (int) relativeToView.bottom
+ );
+ parent.addView(view, lp);
} else {
parent.addView(view);
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
index d072ec7..9bccafb 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
@@ -310,6 +310,7 @@
lockScreenShadeTransitionController.udfpsKeyguardViewController = this
activityLaunchAnimator.addListener(activityLaunchAnimatorListener)
view.mUseExpandedOverlay = useExpandedOverlay
+ view.startIconAsyncInflate()
}
override fun onViewDetached() {
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
index 805a20a..1c26841 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
@@ -18,7 +18,6 @@
import static android.content.ClipDescription.CLASSIFICATION_COMPLETE;
-import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_ENABLED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_UPDATED;
import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_TOAST_SHOWN;
@@ -29,7 +28,6 @@
import android.content.ClipboardManager;
import android.content.Context;
import android.os.SystemProperties;
-import android.provider.DeviceConfig;
import android.provider.Settings;
import android.util.Log;
@@ -37,9 +35,6 @@
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.CoreStartable;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
-import com.android.systemui.util.DeviceConfigProxy;
import javax.inject.Inject;
import javax.inject.Provider;
@@ -59,42 +54,28 @@
"com.android.systemui.SUPPRESS_CLIPBOARD_OVERLAY";
private final Context mContext;
- private final DeviceConfigProxy mDeviceConfig;
private final Provider<ClipboardOverlayController> mOverlayProvider;
- private final ClipboardOverlayControllerLegacyFactory mOverlayFactory;
private final ClipboardToast mClipboardToast;
private final ClipboardManager mClipboardManager;
private final UiEventLogger mUiEventLogger;
- private final FeatureFlags mFeatureFlags;
- private boolean mUsingNewOverlay;
private ClipboardOverlay mClipboardOverlay;
@Inject
- public ClipboardListener(Context context, DeviceConfigProxy deviceConfigProxy,
+ public ClipboardListener(Context context,
Provider<ClipboardOverlayController> clipboardOverlayControllerProvider,
- ClipboardOverlayControllerLegacyFactory overlayFactory,
ClipboardToast clipboardToast,
ClipboardManager clipboardManager,
- UiEventLogger uiEventLogger,
- FeatureFlags featureFlags) {
+ UiEventLogger uiEventLogger) {
mContext = context;
- mDeviceConfig = deviceConfigProxy;
mOverlayProvider = clipboardOverlayControllerProvider;
- mOverlayFactory = overlayFactory;
mClipboardToast = clipboardToast;
mClipboardManager = clipboardManager;
mUiEventLogger = uiEventLogger;
- mFeatureFlags = featureFlags;
-
- mUsingNewOverlay = mFeatureFlags.isEnabled(Flags.CLIPBOARD_OVERLAY_REFACTOR);
}
@Override
public void start() {
- if (mDeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED, true)) {
- mClipboardManager.addPrimaryClipChangedListener(this);
- }
+ mClipboardManager.addPrimaryClipChangedListener(this);
}
@Override
@@ -120,14 +101,8 @@
return;
}
- boolean enabled = mFeatureFlags.isEnabled(Flags.CLIPBOARD_OVERLAY_REFACTOR);
- if (mClipboardOverlay == null || enabled != mUsingNewOverlay) {
- mUsingNewOverlay = enabled;
- if (enabled) {
- mClipboardOverlay = mOverlayProvider.get();
- } else {
- mClipboardOverlay = mOverlayFactory.create(mContext);
- }
+ if (mClipboardOverlay == null) {
+ mClipboardOverlay = mOverlayProvider.get();
mUiEventLogger.log(CLIPBOARD_OVERLAY_ENTERED, 0, clipSource);
} else {
mUiEventLogger.log(CLIPBOARD_OVERLAY_UPDATED, 0, clipSource);
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerLegacy.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerLegacy.java
deleted file mode 100644
index 3a040829..0000000
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerLegacy.java
+++ /dev/null
@@ -1,963 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.clipboardoverlay;
-
-import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS;
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
-
-import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_SHOW_ACTIONS;
-import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_SHOW_EDIT_BUTTON;
-import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_TAPPED;
-import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_DISMISSED_OTHER;
-import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_DISMISS_TAPPED;
-import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_EDIT_TAPPED;
-import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_REMOTE_COPY_TAPPED;
-import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SHARE_TAPPED;
-import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SWIPE_DISMISSED;
-import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_TAP_OUTSIDE;
-import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_TIMED_OUT;
-
-import static java.util.Objects.requireNonNull;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
-import android.annotation.MainThread;
-import android.app.ICompatCameraControlCallback;
-import android.app.RemoteAction;
-import android.content.BroadcastReceiver;
-import android.content.ClipData;
-import android.content.ClipDescription;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Insets;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.graphics.drawable.Icon;
-import android.hardware.display.DisplayManager;
-import android.hardware.input.InputManager;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Looper;
-import android.provider.DeviceConfig;
-import android.text.TextUtils;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.MathUtils;
-import android.util.Size;
-import android.util.TypedValue;
-import android.view.Display;
-import android.view.DisplayCutout;
-import android.view.Gravity;
-import android.view.InputEvent;
-import android.view.InputEventReceiver;
-import android.view.InputMonitor;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewRootImpl;
-import android.view.ViewTreeObserver;
-import android.view.WindowInsets;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityManager;
-import android.view.animation.LinearInterpolator;
-import android.view.animation.PathInterpolator;
-import android.view.textclassifier.TextClassification;
-import android.view.textclassifier.TextClassificationManager;
-import android.view.textclassifier.TextClassifier;
-import android.view.textclassifier.TextLinks;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.core.view.ViewCompat;
-import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
-
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.policy.PhoneWindow;
-import com.android.systemui.R;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.broadcast.BroadcastSender;
-import com.android.systemui.screenshot.DraggableConstraintLayout;
-import com.android.systemui.screenshot.FloatingWindowUtil;
-import com.android.systemui.screenshot.OverlayActionChip;
-import com.android.systemui.screenshot.TimeoutHandler;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-/**
- * Controls state and UI for the overlay that appears when something is added to the clipboard
- */
-public class ClipboardOverlayControllerLegacy implements ClipboardListener.ClipboardOverlay {
- private static final String TAG = "ClipboardOverlayCtrlr";
- private static final String REMOTE_COPY_ACTION = "android.intent.action.REMOTE_COPY";
-
- /** Constants for screenshot/copy deconflicting */
- public static final String SCREENSHOT_ACTION = "com.android.systemui.SCREENSHOT";
- public static final String SELF_PERMISSION = "com.android.systemui.permission.SELF";
- public static final String COPY_OVERLAY_ACTION = "com.android.systemui.COPY";
-
- private static final String EXTRA_EDIT_SOURCE_CLIPBOARD = "edit_source_clipboard";
-
- private static final int CLIPBOARD_DEFAULT_TIMEOUT_MILLIS = 6000;
- private static final int SWIPE_PADDING_DP = 12; // extra padding around views to allow swipe
- private static final int FONT_SEARCH_STEP_PX = 4;
-
- private final Context mContext;
- private final ClipboardLogger mClipboardLogger;
- private final BroadcastDispatcher mBroadcastDispatcher;
- private final DisplayManager mDisplayManager;
- private final DisplayMetrics mDisplayMetrics;
- private final WindowManager mWindowManager;
- private final WindowManager.LayoutParams mWindowLayoutParams;
- private final PhoneWindow mWindow;
- private final TimeoutHandler mTimeoutHandler;
- private final AccessibilityManager mAccessibilityManager;
- private final TextClassifier mTextClassifier;
-
- private final DraggableConstraintLayout mView;
- private final View mClipboardPreview;
- private final ImageView mImagePreview;
- private final TextView mTextPreview;
- private final TextView mHiddenPreview;
- private final View mPreviewBorder;
- private final OverlayActionChip mEditChip;
- private final OverlayActionChip mShareChip;
- private final OverlayActionChip mRemoteCopyChip;
- private final View mActionContainerBackground;
- private final View mDismissButton;
- private final LinearLayout mActionContainer;
- private final ArrayList<OverlayActionChip> mActionChips = new ArrayList<>();
-
- private Runnable mOnSessionCompleteListener;
-
- private InputMonitor mInputMonitor;
- private InputEventReceiver mInputEventReceiver;
-
- private BroadcastReceiver mCloseDialogsReceiver;
- private BroadcastReceiver mScreenshotReceiver;
-
- private boolean mBlockAttach = false;
- private Animator mExitAnimator;
- private Animator mEnterAnimator;
- private final int mOrientation;
- private boolean mKeyboardVisible;
-
-
- public ClipboardOverlayControllerLegacy(Context context,
- BroadcastDispatcher broadcastDispatcher,
- BroadcastSender broadcastSender,
- TimeoutHandler timeoutHandler, UiEventLogger uiEventLogger) {
- mBroadcastDispatcher = broadcastDispatcher;
- mDisplayManager = requireNonNull(context.getSystemService(DisplayManager.class));
- final Context displayContext = context.createDisplayContext(getDefaultDisplay());
- mContext = displayContext.createWindowContext(TYPE_SCREENSHOT, null);
-
- mClipboardLogger = new ClipboardLogger(uiEventLogger);
-
- mAccessibilityManager = AccessibilityManager.getInstance(mContext);
- mTextClassifier = requireNonNull(context.getSystemService(TextClassificationManager.class))
- .getTextClassifier();
-
- mWindowManager = mContext.getSystemService(WindowManager.class);
-
- mDisplayMetrics = new DisplayMetrics();
- mContext.getDisplay().getRealMetrics(mDisplayMetrics);
-
- mTimeoutHandler = timeoutHandler;
- mTimeoutHandler.setDefaultTimeoutMillis(CLIPBOARD_DEFAULT_TIMEOUT_MILLIS);
-
- // Setup the window that we are going to use
- mWindowLayoutParams = FloatingWindowUtil.getFloatingWindowParams();
- mWindowLayoutParams.setTitle("ClipboardOverlay");
-
- mWindow = FloatingWindowUtil.getFloatingWindow(mContext);
- mWindow.setWindowManager(mWindowManager, null, null);
-
- setWindowFocusable(false);
-
- mView = (DraggableConstraintLayout)
- LayoutInflater.from(mContext).inflate(R.layout.clipboard_overlay_legacy, null);
- mActionContainerBackground =
- requireNonNull(mView.findViewById(R.id.actions_container_background));
- mActionContainer = requireNonNull(mView.findViewById(R.id.actions));
- mClipboardPreview = requireNonNull(mView.findViewById(R.id.clipboard_preview));
- mImagePreview = requireNonNull(mView.findViewById(R.id.image_preview));
- mTextPreview = requireNonNull(mView.findViewById(R.id.text_preview));
- mHiddenPreview = requireNonNull(mView.findViewById(R.id.hidden_preview));
- mPreviewBorder = requireNonNull(mView.findViewById(R.id.preview_border));
- mEditChip = requireNonNull(mView.findViewById(R.id.edit_chip));
- mShareChip = requireNonNull(mView.findViewById(R.id.share_chip));
- mRemoteCopyChip = requireNonNull(mView.findViewById(R.id.remote_copy_chip));
- mEditChip.setAlpha(1);
- mShareChip.setAlpha(1);
- mRemoteCopyChip.setAlpha(1);
- mDismissButton = requireNonNull(mView.findViewById(R.id.dismiss_button));
-
- mShareChip.setContentDescription(mContext.getString(com.android.internal.R.string.share));
- mView.setCallbacks(new DraggableConstraintLayout.SwipeDismissCallbacks() {
- @Override
- public void onInteraction() {
- mTimeoutHandler.resetTimeout();
- }
-
- @Override
- public void onSwipeDismissInitiated(Animator animator) {
- mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_SWIPE_DISMISSED);
- mExitAnimator = animator;
- }
-
- @Override
- public void onDismissComplete() {
- hideImmediate();
- }
- });
-
- mTextPreview.getViewTreeObserver().addOnPreDrawListener(() -> {
- int availableHeight = mTextPreview.getHeight()
- - (mTextPreview.getPaddingTop() + mTextPreview.getPaddingBottom());
- mTextPreview.setMaxLines(availableHeight / mTextPreview.getLineHeight());
- return true;
- });
-
- mDismissButton.setOnClickListener(view -> {
- mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISS_TAPPED);
- animateOut();
- });
-
- mEditChip.setIcon(Icon.createWithResource(mContext, R.drawable.ic_screenshot_edit), true);
- mRemoteCopyChip.setIcon(
- Icon.createWithResource(mContext, R.drawable.ic_baseline_devices_24), true);
- mShareChip.setIcon(Icon.createWithResource(mContext, R.drawable.ic_screenshot_share), true);
- mOrientation = mContext.getResources().getConfiguration().orientation;
-
- attachWindow();
- withWindowAttached(() -> {
- mWindow.setContentView(mView);
- WindowInsets insets = mWindowManager.getCurrentWindowMetrics().getWindowInsets();
- mKeyboardVisible = insets.isVisible(WindowInsets.Type.ime());
- updateInsets(insets);
- mWindow.peekDecorView().getViewTreeObserver().addOnGlobalLayoutListener(
- new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- WindowInsets insets =
- mWindowManager.getCurrentWindowMetrics().getWindowInsets();
- boolean keyboardVisible = insets.isVisible(WindowInsets.Type.ime());
- if (keyboardVisible != mKeyboardVisible) {
- mKeyboardVisible = keyboardVisible;
- updateInsets(insets);
- }
- }
- });
- mWindow.peekDecorView().getViewRootImpl().setActivityConfigCallback(
- new ViewRootImpl.ActivityConfigCallback() {
- @Override
- public void onConfigurationChanged(Configuration overrideConfig,
- int newDisplayId) {
- if (mContext.getResources().getConfiguration().orientation
- != mOrientation) {
- mClipboardLogger.logSessionComplete(
- CLIPBOARD_OVERLAY_DISMISSED_OTHER);
- hideImmediate();
- }
- }
-
- @Override
- public void requestCompatCameraControl(
- boolean showControl, boolean transformationApplied,
- ICompatCameraControlCallback callback) {
- Log.w(TAG, "unexpected requestCompatCameraControl call");
- }
- });
- });
-
- mTimeoutHandler.setOnTimeoutRunnable(() -> {
- mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_TIMED_OUT);
- animateOut();
- });
-
- mCloseDialogsReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
- mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
- animateOut();
- }
- }
- };
-
- mBroadcastDispatcher.registerReceiver(mCloseDialogsReceiver,
- new IntentFilter(ACTION_CLOSE_SYSTEM_DIALOGS));
- mScreenshotReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (SCREENSHOT_ACTION.equals(intent.getAction())) {
- mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_DISMISSED_OTHER);
- animateOut();
- }
- }
- };
-
- mBroadcastDispatcher.registerReceiver(mScreenshotReceiver,
- new IntentFilter(SCREENSHOT_ACTION), null, null, Context.RECEIVER_EXPORTED,
- SELF_PERMISSION);
- monitorOutsideTouches();
-
- Intent copyIntent = new Intent(COPY_OVERLAY_ACTION);
- // Set package name so the system knows it's safe
- copyIntent.setPackage(mContext.getPackageName());
- broadcastSender.sendBroadcast(copyIntent, SELF_PERMISSION);
- }
-
- @Override // ClipboardListener.ClipboardOverlay
- public void setClipData(ClipData clipData, String clipSource) {
- if (mExitAnimator != null && mExitAnimator.isRunning()) {
- mExitAnimator.cancel();
- }
- reset();
- String accessibilityAnnouncement;
-
- boolean isSensitive = clipData != null && clipData.getDescription().getExtras() != null
- && clipData.getDescription().getExtras()
- .getBoolean(ClipDescription.EXTRA_IS_SENSITIVE);
- if (clipData == null || clipData.getItemCount() == 0) {
- showTextPreview(
- mContext.getResources().getString(R.string.clipboard_overlay_text_copied),
- mTextPreview);
- accessibilityAnnouncement = mContext.getString(R.string.clipboard_content_copied);
- } else if (!TextUtils.isEmpty(clipData.getItemAt(0).getText())) {
- ClipData.Item item = clipData.getItemAt(0);
- if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
- CLIPBOARD_OVERLAY_SHOW_ACTIONS, false)) {
- if (item.getTextLinks() != null) {
- AsyncTask.execute(() -> classifyText(clipData.getItemAt(0), clipSource));
- }
- }
- if (isSensitive) {
- showEditableText(
- mContext.getResources().getString(R.string.clipboard_asterisks), true);
- } else {
- showEditableText(item.getText(), false);
- }
- showShareChip(clipData);
- accessibilityAnnouncement = mContext.getString(R.string.clipboard_text_copied);
- } else if (clipData.getItemAt(0).getUri() != null) {
- if (tryShowEditableImage(clipData.getItemAt(0).getUri(), isSensitive)) {
- showShareChip(clipData);
- accessibilityAnnouncement = mContext.getString(R.string.clipboard_image_copied);
- } else {
- accessibilityAnnouncement = mContext.getString(R.string.clipboard_content_copied);
- }
- } else {
- showTextPreview(
- mContext.getResources().getString(R.string.clipboard_overlay_text_copied),
- mTextPreview);
- accessibilityAnnouncement = mContext.getString(R.string.clipboard_content_copied);
- }
- Intent remoteCopyIntent = IntentCreator.getRemoteCopyIntent(clipData, mContext);
- // Only show remote copy if it's available.
- PackageManager packageManager = mContext.getPackageManager();
- if (packageManager.resolveActivity(
- remoteCopyIntent, PackageManager.ResolveInfoFlags.of(0)) != null) {
- mRemoteCopyChip.setContentDescription(
- mContext.getString(R.string.clipboard_send_nearby_description));
- mRemoteCopyChip.setVisibility(View.VISIBLE);
- mRemoteCopyChip.setOnClickListener((v) -> {
- mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_REMOTE_COPY_TAPPED);
- mContext.startActivity(remoteCopyIntent);
- animateOut();
- });
- mActionContainerBackground.setVisibility(View.VISIBLE);
- } else {
- mRemoteCopyChip.setVisibility(View.GONE);
- }
- withWindowAttached(() -> {
- if (mEnterAnimator == null || !mEnterAnimator.isRunning()) {
- mView.post(this::animateIn);
- }
- mView.announceForAccessibility(accessibilityAnnouncement);
- });
- mTimeoutHandler.resetTimeout();
- }
-
- @Override // ClipboardListener.ClipboardOverlay
- public void setOnSessionCompleteListener(Runnable runnable) {
- mOnSessionCompleteListener = runnable;
- }
-
- private void classifyText(ClipData.Item item, String source) {
- ArrayList<RemoteAction> actions = new ArrayList<>();
- for (TextLinks.TextLink link : item.getTextLinks().getLinks()) {
- TextClassification classification = mTextClassifier.classifyText(
- item.getText(), link.getStart(), link.getEnd(), null);
- actions.addAll(classification.getActions());
- }
- mView.post(() -> {
- resetActionChips();
- if (actions.size() > 0) {
- mActionContainerBackground.setVisibility(View.VISIBLE);
- for (RemoteAction action : actions) {
- Intent targetIntent = action.getActionIntent().getIntent();
- ComponentName component = targetIntent.getComponent();
- if (component != null && !TextUtils.equals(source,
- component.getPackageName())) {
- OverlayActionChip chip = constructActionChip(action);
- mActionContainer.addView(chip);
- mActionChips.add(chip);
- break; // only show at most one action chip
- }
- }
- }
- });
- }
-
- private void showShareChip(ClipData clip) {
- mShareChip.setVisibility(View.VISIBLE);
- mActionContainerBackground.setVisibility(View.VISIBLE);
- mShareChip.setOnClickListener((v) -> shareContent(clip));
- }
-
- private OverlayActionChip constructActionChip(RemoteAction action) {
- OverlayActionChip chip = (OverlayActionChip) LayoutInflater.from(mContext).inflate(
- R.layout.overlay_action_chip, mActionContainer, false);
- chip.setText(action.getTitle());
- chip.setContentDescription(action.getTitle());
- chip.setIcon(action.getIcon(), false);
- chip.setPendingIntent(action.getActionIntent(), () -> {
- mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_ACTION_TAPPED);
- animateOut();
- });
- chip.setAlpha(1);
- return chip;
- }
-
- private void monitorOutsideTouches() {
- InputManager inputManager = mContext.getSystemService(InputManager.class);
- mInputMonitor = inputManager.monitorGestureInput("clipboard overlay", 0);
- mInputEventReceiver = new InputEventReceiver(mInputMonitor.getInputChannel(),
- Looper.getMainLooper()) {
- @Override
- public void onInputEvent(InputEvent event) {
- if (event instanceof MotionEvent) {
- MotionEvent motionEvent = (MotionEvent) event;
- if (motionEvent.getActionMasked() == MotionEvent.ACTION_DOWN) {
- Region touchRegion = new Region();
-
- final Rect tmpRect = new Rect();
- mPreviewBorder.getBoundsOnScreen(tmpRect);
- tmpRect.inset(
- (int) FloatingWindowUtil.dpToPx(mDisplayMetrics, -SWIPE_PADDING_DP),
- (int) FloatingWindowUtil.dpToPx(mDisplayMetrics,
- -SWIPE_PADDING_DP));
- touchRegion.op(tmpRect, Region.Op.UNION);
- mActionContainerBackground.getBoundsOnScreen(tmpRect);
- tmpRect.inset(
- (int) FloatingWindowUtil.dpToPx(mDisplayMetrics, -SWIPE_PADDING_DP),
- (int) FloatingWindowUtil.dpToPx(mDisplayMetrics,
- -SWIPE_PADDING_DP));
- touchRegion.op(tmpRect, Region.Op.UNION);
- mDismissButton.getBoundsOnScreen(tmpRect);
- touchRegion.op(tmpRect, Region.Op.UNION);
- if (!touchRegion.contains(
- (int) motionEvent.getRawX(), (int) motionEvent.getRawY())) {
- mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_TAP_OUTSIDE);
- animateOut();
- }
- }
- }
- finishInputEvent(event, true /* handled */);
- }
- };
- }
-
- private void editImage(Uri uri) {
- mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_EDIT_TAPPED);
- mContext.startActivity(IntentCreator.getImageEditIntent(uri, mContext));
- animateOut();
- }
-
- private void editText() {
- mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_EDIT_TAPPED);
- mContext.startActivity(IntentCreator.getTextEditorIntent(mContext));
- animateOut();
- }
-
- private void shareContent(ClipData clip) {
- mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_SHARE_TAPPED);
- mContext.startActivity(IntentCreator.getShareIntent(clip, mContext));
- animateOut();
- }
-
- private void showSinglePreview(View v) {
- mTextPreview.setVisibility(View.GONE);
- mImagePreview.setVisibility(View.GONE);
- mHiddenPreview.setVisibility(View.GONE);
- v.setVisibility(View.VISIBLE);
- }
-
- private void showTextPreview(CharSequence text, TextView textView) {
- showSinglePreview(textView);
- final CharSequence truncatedText = text.subSequence(0, Math.min(500, text.length()));
- textView.setText(truncatedText);
- updateTextSize(truncatedText, textView);
-
- textView.addOnLayoutChangeListener(
- (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
- if (right - left != oldRight - oldLeft) {
- updateTextSize(truncatedText, textView);
- }
- });
- mEditChip.setVisibility(View.GONE);
- }
-
- private void updateTextSize(CharSequence text, TextView textView) {
- Paint paint = new Paint(textView.getPaint());
- Resources res = textView.getResources();
- float minFontSize = res.getDimensionPixelSize(R.dimen.clipboard_overlay_min_font);
- float maxFontSize = res.getDimensionPixelSize(R.dimen.clipboard_overlay_max_font);
- if (isOneWord(text) && fitsInView(text, textView, paint, minFontSize)) {
- // If the text is a single word and would fit within the TextView at the min font size,
- // find the biggest font size that will fit.
- float fontSizePx = minFontSize;
- while (fontSizePx + FONT_SEARCH_STEP_PX < maxFontSize
- && fitsInView(text, textView, paint, fontSizePx + FONT_SEARCH_STEP_PX)) {
- fontSizePx += FONT_SEARCH_STEP_PX;
- }
- // Need to turn off autosizing, otherwise setTextSize is a no-op.
- textView.setAutoSizeTextTypeWithDefaults(TextView.AUTO_SIZE_TEXT_TYPE_NONE);
- // It's possible to hit the max font size and not fill the width, so centering
- // horizontally looks better in this case.
- textView.setGravity(Gravity.CENTER);
- textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, (int) fontSizePx);
- } else {
- // Otherwise just stick with autosize.
- textView.setAutoSizeTextTypeUniformWithConfiguration((int) minFontSize,
- (int) maxFontSize, FONT_SEARCH_STEP_PX, TypedValue.COMPLEX_UNIT_PX);
- textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
- }
- }
-
- private static boolean fitsInView(CharSequence text, TextView textView, Paint paint,
- float fontSizePx) {
- paint.setTextSize(fontSizePx);
- float size = paint.measureText(text.toString());
- float availableWidth = textView.getWidth() - textView.getPaddingLeft()
- - textView.getPaddingRight();
- return size < availableWidth;
- }
-
- private static boolean isOneWord(CharSequence text) {
- return text.toString().split("\\s+", 2).length == 1;
- }
-
- private void showEditableText(CharSequence text, boolean hidden) {
- TextView textView = hidden ? mHiddenPreview : mTextPreview;
- showTextPreview(text, textView);
- View.OnClickListener listener = v -> editText();
- setAccessibilityActionToEdit(textView);
- if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
- CLIPBOARD_OVERLAY_SHOW_EDIT_BUTTON, false)) {
- mEditChip.setVisibility(View.VISIBLE);
- mActionContainerBackground.setVisibility(View.VISIBLE);
- mEditChip.setContentDescription(
- mContext.getString(R.string.clipboard_edit_text_description));
- mEditChip.setOnClickListener(listener);
- }
- textView.setOnClickListener(listener);
- }
-
- private boolean tryShowEditableImage(Uri uri, boolean isSensitive) {
- View.OnClickListener listener = v -> editImage(uri);
- ContentResolver resolver = mContext.getContentResolver();
- String mimeType = resolver.getType(uri);
- boolean isEditableImage = mimeType != null && mimeType.startsWith("image");
- if (isSensitive) {
- mHiddenPreview.setText(mContext.getString(R.string.clipboard_text_hidden));
- showSinglePreview(mHiddenPreview);
- if (isEditableImage) {
- mHiddenPreview.setOnClickListener(listener);
- setAccessibilityActionToEdit(mHiddenPreview);
- }
- } else if (isEditableImage) { // if the MIMEtype is image, try to load
- try {
- int size = mContext.getResources().getDimensionPixelSize(R.dimen.overlay_x_scale);
- // The width of the view is capped, height maintains aspect ratio, so allow it to be
- // taller if needed.
- Bitmap thumbnail = resolver.loadThumbnail(uri, new Size(size, size * 4), null);
- showSinglePreview(mImagePreview);
- mImagePreview.setImageBitmap(thumbnail);
- mImagePreview.setOnClickListener(listener);
- setAccessibilityActionToEdit(mImagePreview);
- } catch (IOException e) {
- Log.e(TAG, "Thumbnail loading failed", e);
- showTextPreview(
- mContext.getResources().getString(R.string.clipboard_overlay_text_copied),
- mTextPreview);
- isEditableImage = false;
- }
- } else {
- showTextPreview(
- mContext.getResources().getString(R.string.clipboard_overlay_text_copied),
- mTextPreview);
- }
- if (isEditableImage && DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_SHOW_EDIT_BUTTON, false)) {
- mEditChip.setVisibility(View.VISIBLE);
- mActionContainerBackground.setVisibility(View.VISIBLE);
- mEditChip.setOnClickListener(listener);
- mEditChip.setContentDescription(
- mContext.getString(R.string.clipboard_edit_image_description));
- }
- return isEditableImage;
- }
-
- private void setAccessibilityActionToEdit(View view) {
- ViewCompat.replaceAccessibilityAction(view,
- AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK,
- mContext.getString(R.string.clipboard_edit), null);
- }
-
- private void animateIn() {
- if (mAccessibilityManager.isEnabled()) {
- mDismissButton.setVisibility(View.VISIBLE);
- }
- mEnterAnimator = getEnterAnimation();
- mEnterAnimator.start();
- }
-
- private void animateOut() {
- if (mExitAnimator != null && mExitAnimator.isRunning()) {
- return;
- }
- Animator anim = getExitAnimation();
- anim.addListener(new AnimatorListenerAdapter() {
- private boolean mCancelled;
-
- @Override
- public void onAnimationCancel(Animator animation) {
- super.onAnimationCancel(animation);
- mCancelled = true;
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- if (!mCancelled) {
- hideImmediate();
- }
- }
- });
- mExitAnimator = anim;
- anim.start();
- }
-
- private Animator getEnterAnimation() {
- TimeInterpolator linearInterpolator = new LinearInterpolator();
- TimeInterpolator scaleInterpolator = new PathInterpolator(0, 0, 0, 1f);
- AnimatorSet enterAnim = new AnimatorSet();
-
- ValueAnimator rootAnim = ValueAnimator.ofFloat(0, 1);
- rootAnim.setInterpolator(linearInterpolator);
- rootAnim.setDuration(66);
- rootAnim.addUpdateListener(animation -> {
- mView.setAlpha(animation.getAnimatedFraction());
- });
-
- ValueAnimator scaleAnim = ValueAnimator.ofFloat(0, 1);
- scaleAnim.setInterpolator(scaleInterpolator);
- scaleAnim.setDuration(333);
- scaleAnim.addUpdateListener(animation -> {
- float previewScale = MathUtils.lerp(.9f, 1f, animation.getAnimatedFraction());
- mClipboardPreview.setScaleX(previewScale);
- mClipboardPreview.setScaleY(previewScale);
- mPreviewBorder.setScaleX(previewScale);
- mPreviewBorder.setScaleY(previewScale);
-
- float pivotX = mClipboardPreview.getWidth() / 2f + mClipboardPreview.getX();
- mActionContainerBackground.setPivotX(pivotX - mActionContainerBackground.getX());
- mActionContainer.setPivotX(pivotX - ((View) mActionContainer.getParent()).getX());
- float actionsScaleX = MathUtils.lerp(.7f, 1f, animation.getAnimatedFraction());
- float actionsScaleY = MathUtils.lerp(.9f, 1f, animation.getAnimatedFraction());
- mActionContainer.setScaleX(actionsScaleX);
- mActionContainer.setScaleY(actionsScaleY);
- mActionContainerBackground.setScaleX(actionsScaleX);
- mActionContainerBackground.setScaleY(actionsScaleY);
- });
-
- ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1);
- alphaAnim.setInterpolator(linearInterpolator);
- alphaAnim.setDuration(283);
- alphaAnim.addUpdateListener(animation -> {
- float alpha = animation.getAnimatedFraction();
- mClipboardPreview.setAlpha(alpha);
- mPreviewBorder.setAlpha(alpha);
- mDismissButton.setAlpha(alpha);
- mActionContainer.setAlpha(alpha);
- });
-
- mActionContainer.setAlpha(0);
- mPreviewBorder.setAlpha(0);
- mClipboardPreview.setAlpha(0);
- enterAnim.play(rootAnim).with(scaleAnim);
- enterAnim.play(alphaAnim).after(50).after(rootAnim);
-
- enterAnim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- mView.setAlpha(1);
- mTimeoutHandler.resetTimeout();
- }
- });
- return enterAnim;
- }
-
- private Animator getExitAnimation() {
- TimeInterpolator linearInterpolator = new LinearInterpolator();
- TimeInterpolator scaleInterpolator = new PathInterpolator(.3f, 0, 1f, 1f);
- AnimatorSet exitAnim = new AnimatorSet();
-
- ValueAnimator rootAnim = ValueAnimator.ofFloat(0, 1);
- rootAnim.setInterpolator(linearInterpolator);
- rootAnim.setDuration(100);
- rootAnim.addUpdateListener(anim -> mView.setAlpha(1 - anim.getAnimatedFraction()));
-
- ValueAnimator scaleAnim = ValueAnimator.ofFloat(0, 1);
- scaleAnim.setInterpolator(scaleInterpolator);
- scaleAnim.setDuration(250);
- scaleAnim.addUpdateListener(animation -> {
- float previewScale = MathUtils.lerp(1f, .9f, animation.getAnimatedFraction());
- mClipboardPreview.setScaleX(previewScale);
- mClipboardPreview.setScaleY(previewScale);
- mPreviewBorder.setScaleX(previewScale);
- mPreviewBorder.setScaleY(previewScale);
-
- float pivotX = mClipboardPreview.getWidth() / 2f + mClipboardPreview.getX();
- mActionContainerBackground.setPivotX(pivotX - mActionContainerBackground.getX());
- mActionContainer.setPivotX(pivotX - ((View) mActionContainer.getParent()).getX());
- float actionScaleX = MathUtils.lerp(1f, .8f, animation.getAnimatedFraction());
- float actionScaleY = MathUtils.lerp(1f, .9f, animation.getAnimatedFraction());
- mActionContainer.setScaleX(actionScaleX);
- mActionContainer.setScaleY(actionScaleY);
- mActionContainerBackground.setScaleX(actionScaleX);
- mActionContainerBackground.setScaleY(actionScaleY);
- });
-
- ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1);
- alphaAnim.setInterpolator(linearInterpolator);
- alphaAnim.setDuration(166);
- alphaAnim.addUpdateListener(animation -> {
- float alpha = 1 - animation.getAnimatedFraction();
- mClipboardPreview.setAlpha(alpha);
- mPreviewBorder.setAlpha(alpha);
- mDismissButton.setAlpha(alpha);
- mActionContainer.setAlpha(alpha);
- });
-
- exitAnim.play(alphaAnim).with(scaleAnim);
- exitAnim.play(rootAnim).after(150).after(alphaAnim);
- return exitAnim;
- }
-
- private void hideImmediate() {
- // Note this may be called multiple times if multiple dismissal events happen at the same
- // time.
- mTimeoutHandler.cancelTimeout();
- final View decorView = mWindow.peekDecorView();
- if (decorView != null && decorView.isAttachedToWindow()) {
- mWindowManager.removeViewImmediate(decorView);
- }
- if (mCloseDialogsReceiver != null) {
- mBroadcastDispatcher.unregisterReceiver(mCloseDialogsReceiver);
- mCloseDialogsReceiver = null;
- }
- if (mScreenshotReceiver != null) {
- mBroadcastDispatcher.unregisterReceiver(mScreenshotReceiver);
- mScreenshotReceiver = null;
- }
- if (mInputEventReceiver != null) {
- mInputEventReceiver.dispose();
- mInputEventReceiver = null;
- }
- if (mInputMonitor != null) {
- mInputMonitor.dispose();
- mInputMonitor = null;
- }
- if (mOnSessionCompleteListener != null) {
- mOnSessionCompleteListener.run();
- }
- }
-
- private void resetActionChips() {
- for (OverlayActionChip chip : mActionChips) {
- mActionContainer.removeView(chip);
- }
- mActionChips.clear();
- }
-
- private void reset() {
- mView.setTranslationX(0);
- mView.setAlpha(0);
- mActionContainerBackground.setVisibility(View.GONE);
- mShareChip.setVisibility(View.GONE);
- mEditChip.setVisibility(View.GONE);
- mRemoteCopyChip.setVisibility(View.GONE);
- resetActionChips();
- mTimeoutHandler.cancelTimeout();
- mClipboardLogger.reset();
- }
-
- @MainThread
- private void attachWindow() {
- View decorView = mWindow.getDecorView();
- if (decorView.isAttachedToWindow() || mBlockAttach) {
- return;
- }
- mBlockAttach = true;
- mWindowManager.addView(decorView, mWindowLayoutParams);
- decorView.requestApplyInsets();
- mView.requestApplyInsets();
- decorView.getViewTreeObserver().addOnWindowAttachListener(
- new ViewTreeObserver.OnWindowAttachListener() {
- @Override
- public void onWindowAttached() {
- mBlockAttach = false;
- }
-
- @Override
- public void onWindowDetached() {
- }
- }
- );
- }
-
- private void withWindowAttached(Runnable action) {
- View decorView = mWindow.getDecorView();
- if (decorView.isAttachedToWindow()) {
- action.run();
- } else {
- decorView.getViewTreeObserver().addOnWindowAttachListener(
- new ViewTreeObserver.OnWindowAttachListener() {
- @Override
- public void onWindowAttached() {
- mBlockAttach = false;
- decorView.getViewTreeObserver().removeOnWindowAttachListener(this);
- action.run();
- }
-
- @Override
- public void onWindowDetached() {
- }
- });
- }
- }
-
- private void updateInsets(WindowInsets insets) {
- int orientation = mContext.getResources().getConfiguration().orientation;
- FrameLayout.LayoutParams p = (FrameLayout.LayoutParams) mView.getLayoutParams();
- if (p == null) {
- return;
- }
- DisplayCutout cutout = insets.getDisplayCutout();
- Insets navBarInsets = insets.getInsets(WindowInsets.Type.navigationBars());
- Insets imeInsets = insets.getInsets(WindowInsets.Type.ime());
- if (cutout == null) {
- p.setMargins(0, 0, 0, Math.max(imeInsets.bottom, navBarInsets.bottom));
- } else {
- Insets waterfall = cutout.getWaterfallInsets();
- if (orientation == ORIENTATION_PORTRAIT) {
- p.setMargins(
- waterfall.left,
- Math.max(cutout.getSafeInsetTop(), waterfall.top),
- waterfall.right,
- Math.max(imeInsets.bottom,
- Math.max(cutout.getSafeInsetBottom(),
- Math.max(navBarInsets.bottom, waterfall.bottom))));
- } else {
- p.setMargins(
- waterfall.left,
- waterfall.top,
- waterfall.right,
- Math.max(imeInsets.bottom,
- Math.max(navBarInsets.bottom, waterfall.bottom)));
- }
- }
- mView.setLayoutParams(p);
- mView.requestLayout();
- }
-
- private Display getDefaultDisplay() {
- return mDisplayManager.getDisplay(DEFAULT_DISPLAY);
- }
-
- /**
- * Updates the window focusability. If the window is already showing, then it updates the
- * window immediately, otherwise the layout params will be applied when the window is next
- * shown.
- */
- private void setWindowFocusable(boolean focusable) {
- int flags = mWindowLayoutParams.flags;
- if (focusable) {
- mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- } else {
- mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- }
- if (mWindowLayoutParams.flags == flags) {
- return;
- }
- final View decorView = mWindow.peekDecorView();
- if (decorView != null && decorView.isAttachedToWindow()) {
- mWindowManager.updateViewLayout(decorView, mWindowLayoutParams);
- }
- }
-
- static class ClipboardLogger {
- private final UiEventLogger mUiEventLogger;
- private boolean mGuarded = false;
-
- ClipboardLogger(UiEventLogger uiEventLogger) {
- mUiEventLogger = uiEventLogger;
- }
-
- void logSessionComplete(@NonNull UiEventLogger.UiEventEnum event) {
- if (!mGuarded) {
- mGuarded = true;
- mUiEventLogger.log(event);
- }
- }
-
- void reset() {
- mGuarded = false;
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerLegacyFactory.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerLegacyFactory.java
deleted file mode 100644
index 0d989a7..0000000
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerLegacyFactory.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.clipboardoverlay;
-
-import android.content.Context;
-
-import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.broadcast.BroadcastSender;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.screenshot.TimeoutHandler;
-
-import javax.inject.Inject;
-
-/**
- * A factory that churns out ClipboardOverlayControllerLegacys on demand.
- */
-@SysUISingleton
-public class ClipboardOverlayControllerLegacyFactory {
-
- private final UiEventLogger mUiEventLogger;
- private final BroadcastDispatcher mBroadcastDispatcher;
- private final BroadcastSender mBroadcastSender;
-
- @Inject
- public ClipboardOverlayControllerLegacyFactory(BroadcastDispatcher broadcastDispatcher,
- BroadcastSender broadcastSender, UiEventLogger uiEventLogger) {
- this.mBroadcastDispatcher = broadcastDispatcher;
- this.mBroadcastSender = broadcastSender;
- this.mUiEventLogger = uiEventLogger;
- }
-
- /**
- * One new ClipboardOverlayControllerLegacy, coming right up!
- */
- public ClipboardOverlayControllerLegacy create(Context context) {
- return new ClipboardOverlayControllerLegacy(context, mBroadcastDispatcher, mBroadcastSender,
- new TimeoutHandler(context), mUiEventLogger);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
index 54587b2..3808e73 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
@@ -189,9 +189,9 @@
authorizedPanelsRepository.addAuthorizedPanels(
setOf(serviceInfo.componentName.packageName)
)
- animateExitAndFinish()
val selected = SelectedItem.PanelItem(appName, componentName)
controlsController.setPreferredSelection(selected)
+ animateExitAndFinish()
openControlsOrigin()
}
dialog = null
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 966dbf1..9e71bef 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -25,6 +25,7 @@
import android.content.ComponentName
import android.content.Context
import android.content.Intent
+import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.service.controls.Control
@@ -38,6 +39,7 @@
import android.view.animation.DecelerateInterpolator
import android.widget.AdapterView
import android.widget.ArrayAdapter
+import android.widget.BaseAdapter
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
@@ -90,6 +92,7 @@
class ControlsUiControllerImpl @Inject constructor (
val controlsController: Lazy<ControlsController>,
val context: Context,
+ private val packageManager: PackageManager,
@Main val uiExecutor: DelayableExecutor,
@Background val bgExecutor: DelayableExecutor,
val controlsListingController: Lazy<ControlsListingController>,
@@ -113,6 +116,11 @@
private const val PREF_IS_PANEL = "controls_is_panel"
private const val FADE_IN_MILLIS = 200L
+
+ private const val OPEN_APP_ID = 0L
+ private const val ADD_CONTROLS_ID = 1L
+ private const val ADD_APP_ID = 2L
+ private const val EDIT_CONTROLS_ID = 3L
}
private var selectedItem: SelectedItem = SelectedItem.EMPTY_SELECTION
@@ -140,6 +148,9 @@
it.getTitle()
}
+ private var openAppIntent: Intent? = null
+ private var overflowMenuAdapter: BaseAdapter? = null
+
private val onSeedingComplete = Consumer<Boolean> {
accepted ->
if (accepted) {
@@ -216,6 +227,8 @@
this.parent = parent
this.onDismiss = onDismiss
this.activityContext = activityContext
+ this.openAppIntent = null
+ this.overflowMenuAdapter = null
hidden = false
retainCache = false
@@ -306,6 +319,12 @@
startTargetedActivity(si, ControlsEditingActivity::class.java)
}
+ private fun startDefaultActivity() {
+ openAppIntent?.let {
+ startActivity(it, animateExtra = false)
+ }
+ }
+
private fun startTargetedActivity(si: StructureInfo, klazz: Class<*>) {
val i = Intent(activityContext, klazz)
putIntentExtras(i, si)
@@ -329,9 +348,11 @@
startActivity(i)
}
- private fun startActivity(intent: Intent) {
+ private fun startActivity(intent: Intent, animateExtra: Boolean = true) {
// Force animations when transitioning from a dialog to an activity
- intent.putExtra(ControlsUiController.EXTRA_ANIMATE, true)
+ if (animateExtra) {
+ intent.putExtra(ControlsUiController.EXTRA_ANIMATE, true)
+ }
if (keyguardStateController.isShowing()) {
activityStarter.postStartActivityDismissingKeyguard(intent, 0 /* delay */)
@@ -383,8 +404,31 @@
Log.w(ControlsUiController.TAG, "Not TaskViewFactory to display panel $selectionItem")
}
+ bgExecutor.execute {
+ val intent = Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_LAUNCHER)
+ .setPackage(selectionItem.componentName.packageName)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or
+ Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
+ val intents = packageManager
+ .queryIntentActivities(intent, PackageManager.ResolveInfoFlags.of(0L))
+ intents.firstOrNull { it.activityInfo.exported }?.let { resolved ->
+ intent.setPackage(null)
+ intent.setComponent(resolved.activityInfo.componentName)
+ openAppIntent = intent
+ parent.post {
+ // This will call show on the PopupWindow in the same thread, so make sure this
+ // happens in the view thread.
+ overflowMenuAdapter?.notifyDataSetChanged()
+ }
+ }
+ }
createDropDown(panelsAndStructures, selectionItem)
- createMenu()
+
+ val currentApps = panelsAndStructures.map { it.componentName }.toSet()
+ val allApps = controlsListingController.get()
+ .getCurrentServices().map { it.componentName }.toSet()
+ createMenu(extraApps = (allApps - currentApps).isNotEmpty())
}
private fun createPanelView(componentName: ComponentName) {
@@ -423,28 +467,41 @@
}
}
- private fun createMenu() {
+ private fun createMenu(extraApps: Boolean) {
val isPanel = selectedItem is SelectedItem.PanelItem
val selectedStructure = (selectedItem as? SelectedItem.StructureItem)?.structure
?: EMPTY_STRUCTURE
val newFlows = featureFlags.isEnabled(Flags.CONTROLS_MANAGEMENT_NEW_FLOWS)
- val addControlsId = if (newFlows || isPanel) {
- R.string.controls_menu_add_another_app
- } else {
- R.string.controls_menu_add
+
+ val items = buildList {
+ add(OverflowMenuAdapter.MenuItem(
+ context.getText(R.string.controls_open_app),
+ OPEN_APP_ID
+ ))
+ if (newFlows || isPanel) {
+ if (extraApps) {
+ add(OverflowMenuAdapter.MenuItem(
+ context.getText(R.string.controls_menu_add_another_app),
+ ADD_APP_ID
+ ))
+ }
+ } else {
+ add(OverflowMenuAdapter.MenuItem(
+ context.getText(R.string.controls_menu_add),
+ ADD_CONTROLS_ID
+ ))
+ }
+ if (!isPanel) {
+ add(OverflowMenuAdapter.MenuItem(
+ context.getText(R.string.controls_menu_edit),
+ EDIT_CONTROLS_ID
+ ))
+ }
}
- val items = if (isPanel) {
- arrayOf(
- context.resources.getString(addControlsId),
- )
- } else {
- arrayOf(
- context.resources.getString(addControlsId),
- context.resources.getString(R.string.controls_menu_edit)
- )
+ val adapter = OverflowMenuAdapter(context, R.layout.controls_more_item, items) { position ->
+ getItemId(position) != OPEN_APP_ID || openAppIntent != null
}
- var adapter = ArrayAdapter<String>(context, R.layout.controls_more_item, items)
val anchor = parent.requireViewById<ImageView>(R.id.controls_more)
anchor.setOnClickListener(object : View.OnClickListener {
@@ -462,25 +519,21 @@
pos: Int,
id: Long
) {
- when (pos) {
- // 0: Add Control
- 0 -> {
- if (isPanel || newFlows) {
- startProviderSelectorActivity()
- } else {
- startFavoritingActivity(selectedStructure)
- }
- }
- // 1: Edit controls
- 1 -> startEditingActivity(selectedStructure)
+ when (id) {
+ OPEN_APP_ID -> startDefaultActivity()
+ ADD_APP_ID -> startProviderSelectorActivity()
+ ADD_CONTROLS_ID -> startFavoritingActivity(selectedStructure)
+ EDIT_CONTROLS_ID -> startEditingActivity(selectedStructure)
}
dismiss()
}
})
show()
+ listView?.post { listView?.requestAccessibilityFocus() }
}
}
})
+ overflowMenuAdapter = adapter
}
private fun createDropDown(items: List<SelectionItem>, selected: SelectionItem) {
@@ -542,6 +595,7 @@
}
})
show()
+ listView?.post { listView?.requestAccessibilityFocus() }
}
}
})
@@ -631,7 +685,7 @@
.putString(PREF_COMPONENT, selectedItem.componentName.flattenToString())
.putString(PREF_STRUCTURE_OR_APP_NAME, selectedItem.name.toString())
.putBoolean(PREF_IS_PANEL, selectedItem is SelectedItem.PanelItem)
- .commit()
+ .apply()
}
private fun maybeUpdateSelectedItem(item: SelectionItem): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/OverflowMenuAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/OverflowMenuAdapter.kt
new file mode 100644
index 0000000..6b84e36
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/OverflowMenuAdapter.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.controls.ui
+
+import android.content.Context
+import android.widget.ArrayAdapter
+import androidx.annotation.LayoutRes
+
+open class OverflowMenuAdapter(
+ context: Context,
+ @LayoutRes layoutId: Int,
+ itemsWithIds: List<MenuItem>,
+ private val isEnabledInternal: OverflowMenuAdapter.(Int) -> Boolean
+) : ArrayAdapter<CharSequence>(context, layoutId, itemsWithIds.map(MenuItem::text)) {
+
+ private val ids = itemsWithIds.map(MenuItem::id)
+
+ override fun getItemId(position: Int): Long {
+ return ids[position]
+ }
+
+ override fun isEnabled(position: Int): Boolean {
+ return isEnabledInternal(position)
+ }
+
+ data class MenuItem(val text: CharSequence, val id: Long)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index c882f8a..c3bd5d9 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -182,6 +182,18 @@
}
}
+ /**
+ * Ends the dream content and dream overlay animations, if they're currently running.
+ * @see [AnimatorSet.end]
+ */
+ fun endAnimations() {
+ mAnimator =
+ mAnimator?.let {
+ it.end()
+ null
+ }
+ }
+
private fun blurAnimator(
view: View,
fromBlurRadius: Float,
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
index 539d2ca..50cfb6a 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
@@ -142,6 +142,23 @@
}
};
+ /**
+ * If true, overlay entry animations should be skipped once.
+ *
+ * This is turned on when exiting low light and should be turned off once the entry animations
+ * are skipped once.
+ */
+ private boolean mSkipEntryAnimations;
+
+ private final DreamOverlayStateController.Callback
+ mDreamOverlayStateCallback =
+ new DreamOverlayStateController.Callback() {
+ @Override
+ public void onExitLowLight() {
+ mSkipEntryAnimations = true;
+ }
+ };
+
@Inject
public DreamOverlayContainerViewController(
DreamOverlayContainerView containerView,
@@ -187,6 +204,7 @@
@Override
protected void onInit() {
+ mStateController.addCallback(mDreamOverlayStateCallback);
mStatusBarViewController.init();
mComplicationHostViewController.init();
mDreamOverlayAnimationsController.init(mView);
@@ -202,6 +220,13 @@
// Start dream entry animations. Skip animations for low light clock.
if (!mStateController.isLowLightActive()) {
mDreamOverlayAnimationsController.startEntryAnimations();
+
+ if (mSkipEntryAnimations) {
+ // If we're transitioning from the low light dream back to the user dream, skip the
+ // overlay animations and show immediately.
+ mDreamOverlayAnimationsController.endAnimations();
+ mSkipEntryAnimations = false;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
index ccfdd096..2c7ecb1 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
@@ -83,6 +83,12 @@
*/
default void onAvailableComplicationTypesChanged() {
}
+
+ /**
+ * Called when the low light dream is exiting and transitioning back to the user dream.
+ */
+ default void onExitLowLight() {
+ }
}
private final Executor mExecutor;
@@ -278,6 +284,10 @@
* @param active {@code true} if low light mode is active, {@code false} otherwise.
*/
public void setLowLightActive(boolean active) {
+ if (isLowLightActive() && !active) {
+ // Notify that we're exiting low light only on the transition from active to not active.
+ mCallbacks.forEach(Callback::onExitLowLight);
+ }
modifyState(active ? OP_SET_STATE : OP_CLEAR_STATE, STATE_LOW_LIGHT_ACTIVE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugStartable.kt b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugStartable.kt
index b94d781..dc7fc28 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebugStartable.kt
@@ -21,6 +21,7 @@
import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.commandline.CommandRegistry
+import com.android.systemui.util.InitializationChecker
import dagger.Binds
import dagger.Module
import dagger.multibindings.ClassKey
@@ -34,7 +35,8 @@
private val commandRegistry: CommandRegistry,
private val flagCommand: FlagCommand,
private val featureFlags: FeatureFlagsDebug,
- private val broadcastSender: BroadcastSender
+ private val broadcastSender: BroadcastSender,
+ private val initializationChecker: InitializationChecker
) : CoreStartable {
init {
@@ -46,8 +48,11 @@
override fun start() {
featureFlags.init()
commandRegistry.registerCommand(FlagCommand.FLAG_COMMAND) { flagCommand }
- val intent = Intent(FlagManager.ACTION_SYSUI_STARTED)
- broadcastSender.sendBroadcast(intent)
+ if (initializationChecker.initializeComponents()) {
+ // protected broadcast should only be sent for the main process
+ val intent = Intent(FlagManager.ACTION_SYSUI_STARTED)
+ broadcastSender.sendBroadcast(intent)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 95dd2d0..a6977e1 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -199,8 +199,7 @@
/** A different path for unocclusion transitions back to keyguard */
// TODO(b/262859270): Tracking Bug
- @JvmField
- val UNOCCLUSION_TRANSITION = unreleasedFlag(223, "unocclusion_transition", teamfood = true)
+ @JvmField val UNOCCLUSION_TRANSITION = releasedFlag(223, "unocclusion_transition")
// flag for controlling auto pin confirmation and material u shapes in bouncer
@JvmField
@@ -452,6 +451,12 @@
val ENABLE_PIP_SIZE_LARGE_SCREEN =
sysPropBooleanFlag(1114, "persist.wm.debug.enable_pip_size_large_screen", default = false)
+ // TODO(b/265998256): Tracking bug
+ @Keep
+ @JvmField
+ val ENABLE_PIP_APP_ICON_OVERLAY =
+ sysPropBooleanFlag(1115, "persist.wm.debug.enable_pip_app_icon_overlay", default = false)
+
// 1200 - predictive back
@Keep
@JvmField
@@ -529,7 +534,6 @@
releasedFlag(1600, "a11y_floating_menu_fling_spring_animations")
// 1700 - clipboard
- @JvmField val CLIPBOARD_OVERLAY_REFACTOR = releasedFlag(1700, "clipboard_overlay_refactor")
@JvmField val CLIPBOARD_REMOTE_BEHAVIOR = releasedFlag(1701, "clipboard_remote_behavior")
// 1800 - shade container
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt b/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
index 482138e..680c504 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
@@ -31,10 +31,12 @@
import android.util.Log
import com.android.systemui.SystemUIAppComponentFactoryBase
import com.android.systemui.SystemUIAppComponentFactoryBase.ContextAvailableCallback
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
import com.android.systemui.keyguard.ui.preview.KeyguardRemotePreviewManager
import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.runBlocking
class CustomizationProvider :
@@ -42,6 +44,7 @@
@Inject lateinit var interactor: KeyguardQuickAffordanceInteractor
@Inject lateinit var previewManager: KeyguardRemotePreviewManager
+ @Inject @Main lateinit var mainDispatcher: CoroutineDispatcher
private lateinit var contextAvailableCallback: ContextAvailableCallback
@@ -138,12 +141,14 @@
selectionArgs: Array<out String>?,
sortOrder: String?,
): Cursor? {
- return when (uriMatcher.match(uri)) {
- MATCH_CODE_ALL_AFFORDANCES -> runBlocking { queryAffordances() }
- MATCH_CODE_ALL_SLOTS -> querySlots()
- MATCH_CODE_ALL_SELECTIONS -> runBlocking { querySelections() }
- MATCH_CODE_ALL_FLAGS -> queryFlags()
- else -> null
+ return runBlocking(mainDispatcher) {
+ when (uriMatcher.match(uri)) {
+ MATCH_CODE_ALL_AFFORDANCES -> queryAffordances()
+ MATCH_CODE_ALL_SLOTS -> querySlots()
+ MATCH_CODE_ALL_SELECTIONS -> querySelections()
+ MATCH_CODE_ALL_FLAGS -> queryFlags()
+ else -> null
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt
index f6e6d6b..5a9f775 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt
@@ -19,6 +19,7 @@
import android.app.StatusBarManager
import android.content.Context
+import android.content.pm.PackageManager
import com.android.systemui.R
import com.android.systemui.animation.Expandable
import com.android.systemui.camera.CameraGestureHelper
@@ -26,7 +27,6 @@
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.statusbar.StatusBarState
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -37,6 +37,7 @@
@Inject
constructor(
@Application private val context: Context,
+ private val packageManager: PackageManager,
private val cameraGestureHelper: Lazy<CameraGestureHelper>,
) : KeyguardQuickAffordanceConfig {
@@ -79,6 +80,6 @@
}
private fun isLaunchable(): Boolean {
- return cameraGestureHelper.get().canCameraGestureBeLaunched(StatusBarState.KEYGUARD)
+ return packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
index 08edbc6..b3a9cf5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
@@ -22,14 +22,18 @@
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.stateIn
/** Encapsulates state about device entry fingerprint auth mechanism. */
interface DeviceEntryFingerprintAuthRepository {
/** Whether the device entry fingerprint auth is locked out. */
- val isLockedOut: Flow<Boolean>
+ val isLockedOut: StateFlow<Boolean>
}
/**
@@ -44,29 +48,34 @@
@Inject
constructor(
val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+ @Application scope: CoroutineScope,
) : DeviceEntryFingerprintAuthRepository {
- override val isLockedOut: Flow<Boolean> = conflatedCallbackFlow {
- val sendLockoutUpdate =
- fun() {
- trySendWithFailureLogging(
- keyguardUpdateMonitor.isFingerprintLockedOut,
- TAG,
- "onLockedOutStateChanged"
- )
- }
- val callback =
- object : KeyguardUpdateMonitorCallback() {
- override fun onLockedOutStateChanged(biometricSourceType: BiometricSourceType?) {
- if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
- sendLockoutUpdate()
+ override val isLockedOut: StateFlow<Boolean> =
+ conflatedCallbackFlow {
+ val sendLockoutUpdate =
+ fun() {
+ trySendWithFailureLogging(
+ keyguardUpdateMonitor.isFingerprintLockedOut,
+ TAG,
+ "onLockedOutStateChanged"
+ )
}
- }
+ val callback =
+ object : KeyguardUpdateMonitorCallback() {
+ override fun onLockedOutStateChanged(
+ biometricSourceType: BiometricSourceType?
+ ) {
+ if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
+ sendLockoutUpdate()
+ }
+ }
+ }
+ keyguardUpdateMonitor.registerCallback(callback)
+ sendLockoutUpdate()
+ awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
}
- keyguardUpdateMonitor.registerCallback(callback)
- sendLockoutUpdate()
- awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
- }
+ .stateIn(scope, started = SharingStarted.Eagerly, initialValue = false)
companion object {
const val TAG = "DeviceEntryFingerprintAuthRepositoryImpl"
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
index 4639597..cc99eb7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt
@@ -32,4 +32,9 @@
fun lightRevealScrimRepository(impl: LightRevealScrimRepositoryImpl): LightRevealScrimRepository
@Binds fun biometricRepository(impl: BiometricRepositoryImpl): BiometricRepository
+
+ @Binds
+ fun deviceEntryFingerprintAuthRepository(
+ impl: DeviceEntryFingerprintAuthRepositoryImpl
+ ): DeviceEntryFingerprintAuthRepository
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
index 28c0b28..6020ef8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
@@ -21,6 +21,7 @@
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.BiometricRepository
+import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager.LegacyAlternateBouncer
import com.android.systemui.util.time.SystemClock
@@ -34,6 +35,7 @@
constructor(
private val bouncerRepository: KeyguardBouncerRepository,
private val biometricRepository: BiometricRepository,
+ private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
private val systemClock: SystemClock,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
featureFlags: FeatureFlags,
@@ -99,7 +101,8 @@
bouncerRepository.isAlternateBouncerUIAvailable.value &&
biometricRepository.isFingerprintEnrolled.value &&
biometricRepository.isStrongBiometricAllowed.value &&
- biometricRepository.isFingerprintEnabledByDevicePolicy.value
+ biometricRepository.isFingerprintEnabledByDevicePolicy.value &&
+ !deviceEntryFingerprintAuthRepository.isLockedOut.value
} else {
legacyAlternateBouncer != null &&
keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(true)
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index 08d1857..6bfe1a0 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -17,10 +17,12 @@
package com.android.systemui.notetask
import android.app.KeyguardManager
+import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager
import android.os.UserManager
+import android.util.Log
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.util.kotlin.getOrNull
@@ -57,7 +59,7 @@
* If the keyguard is locked, notes will open as a full screen experience. A locked device has
* no contextual information which let us use the whole screen space available.
*
- * If no in multi-window or the keyguard is unlocked, notes will open as a bubble OR it will be
+ * If not in multi-window or the keyguard is unlocked, notes will open as a bubble OR it will be
* collapsed if the notes bubble is already opened.
*
* That will let users open other apps in full screen, and take contextual notes.
@@ -68,16 +70,23 @@
val bubbles = optionalBubbles.getOrNull() ?: return
val keyguardManager = optionalKeyguardManager.getOrNull() ?: return
val userManager = optionalUserManager.getOrNull() ?: return
- val intent = intentResolver.resolveIntent() ?: return
// TODO(b/249954038): We should handle direct boot (isUserUnlocked). For now, we do nothing.
if (!userManager.isUserUnlocked) return
- if (isInMultiWindowMode || keyguardManager.isKeyguardLocked) {
- context.startActivity(intent)
- } else {
- // TODO(b/254606432): Should include Intent.EXTRA_FLOATING_WINDOW_MODE parameter.
- bubbles.showOrHideAppBubble(intent)
+ val intent = intentResolver.resolveIntent() ?: return
+
+ // TODO(b/266686199): We should handle when app not available. For now, we log.
+ try {
+ if (isInMultiWindowMode || keyguardManager.isKeyguardLocked) {
+ context.startActivity(intent)
+ } else {
+ bubbles.showOrHideAppBubble(intent)
+ }
+ } catch (e: ActivityNotFoundException) {
+ val message =
+ "Activity not found for action: ${NoteTaskIntentResolver.ACTION_CREATE_NOTE}."
+ Log.e(TAG, message, e)
}
}
@@ -106,6 +115,8 @@
}
companion object {
+ private val TAG = NoteTaskController::class.simpleName.orEmpty()
+
// TODO(b/254604589): Use final KeyEvent.KEYCODE_* instead.
const val NOTE_TASK_KEY_EVENT = 311
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt
index 4b10d69..11dc1d7 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskIntentResolver.kt
@@ -16,70 +16,39 @@
package com.android.systemui.notetask
-import android.content.ComponentName
+import android.app.role.RoleManager
+import android.content.Context
import android.content.Intent
-import android.content.pm.ActivityInfo
-import android.content.pm.PackageManager
-import android.content.pm.PackageManager.ResolveInfoFlags
-import com.android.systemui.notetask.NoteTaskIntentResolver.Companion.ACTION_CREATE_NOTE
import javax.inject.Inject
-/**
- * Class responsible to query all apps and find one that can handle the [ACTION_CREATE_NOTE]. If
- * found, an [Intent] ready for be launched will be returned. Otherwise, returns null.
- *
- * TODO(b/248274123): should be revisited once the notes role is implemented.
- */
internal class NoteTaskIntentResolver
@Inject
constructor(
- private val packageManager: PackageManager,
+ private val context: Context,
+ private val roleManager: RoleManager,
) {
fun resolveIntent(): Intent? {
- val intent = Intent(ACTION_CREATE_NOTE)
- val flags = ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY.toLong())
- val infoList = packageManager.queryIntentActivities(intent, flags)
+ val packageName = roleManager.getRoleHoldersAsUser(ROLE_NOTES, context.user).firstOrNull()
- for (info in infoList) {
- val packageName = info.activityInfo.applicationInfo.packageName ?: continue
- val activityName = resolveActivityNameForNotesAction(packageName) ?: continue
+ if (packageName.isNullOrEmpty()) return null
- return Intent(ACTION_CREATE_NOTE)
- .setPackage(packageName)
- .setComponent(ComponentName(packageName, activityName))
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- }
-
- return null
- }
-
- private fun resolveActivityNameForNotesAction(packageName: String): String? {
- val intent = Intent(ACTION_CREATE_NOTE).setPackage(packageName)
- val flags = ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY.toLong())
- val resolveInfo = packageManager.resolveActivity(intent, flags)
-
- val activityInfo = resolveInfo?.activityInfo ?: return null
- if (activityInfo.name.isNullOrBlank()) return null
- if (!activityInfo.exported) return null
- if (!activityInfo.enabled) return null
- if (!activityInfo.showWhenLocked) return null
- if (!activityInfo.turnScreenOn) return null
-
- return activityInfo.name
+ return Intent(ACTION_CREATE_NOTE)
+ .setPackage(packageName)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ // EXTRA_USE_STYLUS_MODE does not mean a stylus is in-use, but a stylus entrypoint was
+ // used to start it.
+ .putExtra(INTENT_EXTRA_USE_STYLUS_MODE, true)
}
companion object {
- // TODO(b/254606432): Use Intent.ACTION_CREATE_NOTE instead.
+ // TODO(b/265912743): Use Intent.ACTION_CREATE_NOTE instead.
const val ACTION_CREATE_NOTE = "android.intent.action.CREATE_NOTE"
// TODO(b/265912743): Use RoleManager.NOTES_ROLE instead.
- const val NOTE_ROLE = "android.app.role.NOTES"
+ const val ROLE_NOTES = "android.app.role.NOTES"
+
+ // TODO(b/265912743): Use Intent.INTENT_EXTRA_USE_STYLUS_MODE instead.
+ const val INTENT_EXTRA_USE_STYLUS_MODE = "android.intent.extra.USE_STYLUS_MODE"
}
}
-
-private val ActivityInfo.showWhenLocked: Boolean
- get() = flags and ActivityInfo.FLAG_SHOW_WHEN_LOCKED != 0
-
-private val ActivityInfo.turnScreenOn: Boolean
- get() = flags and ActivityInfo.FLAG_TURN_SCREEN_ON != 0
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
index 22ce121..ec6a16a 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
@@ -51,7 +51,7 @@
featureFlags: FeatureFlags,
roleManager: RoleManager,
): Boolean {
- val isRoleAvailable = roleManager.isRoleAvailable(NoteTaskIntentResolver.NOTE_ROLE)
+ val isRoleAvailable = roleManager.isRoleAvailable(NoteTaskIntentResolver.ROLE_NOTES)
val isFeatureEnabled = featureFlags.isEnabled(Flags.NOTE_TASKS)
return isRoleAvailable && isFeatureEnabled
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
index d1cf46c..464b6e7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
@@ -636,7 +636,8 @@
isRunning: Boolean
) {
synchronized(lock) {
- val userPackageKey = UserPackage(summary.sourceUserId, summary.sourcePackageName)
+ val userPackageKey = UserPackage(
+ UserHandle.getUserId(summary.callingUid), summary.callingPackageName)
if (isRunning) {
runningTaskIdentifiers
.getOrPut(userPackageKey) { StartTimeAndIdentifiers(systemClock) }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index daed286..edb13c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -36,10 +36,12 @@
import android.view.View
import android.view.ViewGroup
import com.android.settingslib.Utils
+import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.plugins.ActivityStarter
@@ -57,15 +59,14 @@
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.util.concurrency.Execution
import com.android.systemui.util.settings.SecureSettings
+import java.io.PrintWriter
import java.util.Optional
import java.util.concurrent.Executor
import javax.inject.Inject
/** Controller for managing the smartspace view on the lockscreen */
@SysUISingleton
-class LockscreenSmartspaceController
-@Inject
-constructor(
+class LockscreenSmartspaceController @Inject constructor(
private val context: Context,
private val featureFlags: FeatureFlags,
private val smartspaceManager: SmartspaceManager,
@@ -78,13 +79,14 @@
private val statusBarStateController: StatusBarStateController,
private val deviceProvisionedController: DeviceProvisionedController,
private val bypassController: KeyguardBypassController,
+ private val dumpManager: DumpManager,
private val execution: Execution,
@Main private val uiExecutor: Executor,
@Background private val bgExecutor: Executor,
@Main private val handler: Handler,
optionalPlugin: Optional<BcSmartspaceDataPlugin>,
optionalConfigPlugin: Optional<BcSmartspaceConfigPlugin>,
-) {
+ ) : Dumpable {
companion object {
private const val TAG = "LockscreenSmartspaceController"
}
@@ -202,6 +204,7 @@
init {
deviceProvisionedController.addCallback(deviceProvisionedListener)
+ dumpManager.registerDumpable(this)
}
fun isEnabled(): Boolean {
@@ -442,4 +445,11 @@
}
return null
}
+
+ override fun dump(pw: PrintWriter, args: Array<out String>) {
+ pw.println("Region Samplers: ${regionSamplers.size}")
+ regionSamplers.map { (_, sampler) ->
+ sampler.dump(pw)
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 24ad55d..11863627 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -501,7 +501,7 @@
@VisibleForTesting
protected StatusIconDisplayable addWifiIcon(int index, String slot, WifiIconState state) {
if (mStatusBarPipelineFlags.useNewWifiIcon()) {
- throw new IllegalStateException("Attempting to add a mobile icon while the new "
+ throw new IllegalStateException("Attempting to add a wifi icon while the new "
+ "icons are enabled is not supported");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
index d3ff357..491f3a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
@@ -97,15 +97,20 @@
)
}
- fun logOnCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
+ fun logOnCapabilitiesChanged(
+ network: Network,
+ networkCapabilities: NetworkCapabilities,
+ isDefaultNetworkCallback: Boolean,
+ ) {
buffer.log(
SB_LOGGING_TAG,
LogLevel.INFO,
{
+ bool1 = isDefaultNetworkCallback
int1 = network.getNetId()
str1 = networkCapabilities.toString()
},
- { "onCapabilitiesChanged: net=$int1 capabilities=$str1" }
+ { "onCapabilitiesChanged[default=$bool1]: net=$int1 capabilities=$str1" }
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
index d26499c..8669047 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
@@ -114,13 +114,17 @@
network: Network,
networkCapabilities: NetworkCapabilities
) {
+ logger.logOnCapabilitiesChanged(
+ network,
+ networkCapabilities,
+ isDefaultNetworkCallback = true,
+ )
+
// This method will always be called immediately after the network
// becomes the default, in addition to any time the capabilities change
// while the network is the default.
- // If this network contains valid wifi info, then wifi is the default
- // network.
- val wifiInfo = networkCapabilitiesToWifiInfo(networkCapabilities)
- trySend(wifiInfo != null)
+ // If this network is a wifi network, then wifi is the default network.
+ trySend(isWifiNetwork(networkCapabilities))
}
override fun onLost(network: Network) {
@@ -152,7 +156,11 @@
network: Network,
networkCapabilities: NetworkCapabilities
) {
- logger.logOnCapabilitiesChanged(network, networkCapabilities)
+ logger.logOnCapabilitiesChanged(
+ network,
+ networkCapabilities,
+ isDefaultNetworkCallback = false,
+ )
wifiNetworkChangeEvents.tryEmit(Unit)
@@ -253,16 +261,30 @@
networkCapabilities: NetworkCapabilities
): WifiInfo? {
return when {
- networkCapabilities.hasTransport(TRANSPORT_WIFI) ->
- networkCapabilities.transportInfo as WifiInfo?
networkCapabilities.hasTransport(TRANSPORT_CELLULAR) ->
// Sometimes, cellular networks can act as wifi networks (known as VCN --
// virtual carrier network). So, see if this cellular network has wifi info.
Utils.tryGetWifiInfoForVcn(networkCapabilities)
+ networkCapabilities.hasTransport(TRANSPORT_WIFI) ->
+ if (networkCapabilities.transportInfo is WifiInfo) {
+ networkCapabilities.transportInfo as WifiInfo
+ } else {
+ null
+ }
else -> null
}
}
+ /** True if these capabilities represent a wifi network. */
+ private fun isWifiNetwork(networkCapabilities: NetworkCapabilities): Boolean {
+ return when {
+ networkCapabilities.hasTransport(TRANSPORT_WIFI) -> true
+ networkCapabilities.hasTransport(TRANSPORT_CELLULAR) ->
+ Utils.tryGetWifiInfoForVcn(networkCapabilities) != null
+ else -> false
+ }
+ }
+
private fun createWifiNetworkModel(
wifiInfo: WifiInfo,
network: Network,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
index 9946b4b..5dcafb3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.policy;
import android.annotation.WorkerThread;
-import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
@@ -255,7 +254,6 @@
setTorchMode(enabled);
mSecureSettings.putInt(Settings.Secure.FLASHLIGHT_AVAILABLE, 1);
mSecureSettings.putInt(Secure.FLASHLIGHT_ENABLED, enabled ? 1 : 0);
- mBroadcastSender.sendBroadcast(new Intent(ACTION_FLASHLIGHT_CHANGED));
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index 00b2fbe..dbedba0 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -23,6 +23,7 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
@@ -86,6 +87,7 @@
@Mock private lateinit var smallLogBuffer: LogBuffer
@Mock private lateinit var largeLogBuffer: LogBuffer
private lateinit var underTest: ClockEventController
+ @Mock private lateinit var dumpManager: DumpManager
@Before
fun setUp() {
@@ -113,7 +115,8 @@
bgExecutor,
smallLogBuffer,
largeLogBuffer,
- featureFlags
+ featureFlags,
+ dumpManager
)
underTest.clock = clock
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index eaef959..4d95a22 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -695,7 +695,6 @@
setKeyguardBouncerVisibility(true);
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
- verify(mFaceManager).isHardwareDetected();
verify(mFaceManager, never()).hasEnrolledTemplates(anyInt());
}
@@ -854,6 +853,32 @@
}
@Test
+ public void faceUnlockDoesNotRunWhenDeviceIsGoingToSleepWithAssistantVisible() {
+ mKeyguardUpdateMonitor.setKeyguardShowing(true, true);
+ mKeyguardUpdateMonitor.setAssistantVisible(true);
+
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ mTestableLooper.processAllMessages();
+ clearInvocations(mFaceManager);
+
+ // Device going to sleep while assistant is visible
+ mKeyguardUpdateMonitor.handleStartedGoingToSleep(0);
+ mKeyguardUpdateMonitor.handleFinishedGoingToSleep(0);
+ mTestableLooper.moveTimeForward(DEFAULT_CANCEL_SIGNAL_TIMEOUT);
+ mTestableLooper.processAllMessages();
+
+ mKeyguardUpdateMonitor.handleKeyguardReset();
+
+ assertThat(mKeyguardUpdateMonitor.isFaceDetectionRunning()).isFalse();
+ verify(mFaceManager, never()).authenticate(any(),
+ any(),
+ any(),
+ any(),
+ anyInt(),
+ anyBoolean());
+ }
+
+ @Test
public void testIgnoresAuth_whenTrustAgentOnKeyguard_withoutBypass() {
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
index b92c5d0..fd931b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
@@ -51,14 +51,24 @@
import android.view.WindowMetrics
import androidx.test.filters.SmallTest
import com.airbnb.lottie.LottieAnimationView
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.ViewMediatorCallback
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestableContext
import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags.MODERN_ALTERNATE_BOUNCER
+import com.android.systemui.keyguard.data.repository.FakeBiometricRepository
+import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
+import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
+import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
+import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.recents.OverviewProxyService
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.TestCoroutineScope
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -101,6 +111,9 @@
@Captor lateinit var overlayCaptor: ArgumentCaptor<View>
@Captor lateinit var overlayViewParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
+ private lateinit var keyguardBouncerRepository: KeyguardBouncerRepository
+ private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
+ private val featureFlags = FakeFeatureFlags()
private val executor = FakeExecutor(FakeSystemClock())
private lateinit var overlayController: ISidefpsController
private lateinit var sideFpsController: SideFpsController
@@ -121,6 +134,24 @@
@Before
fun setup() {
+ featureFlags.set(MODERN_ALTERNATE_BOUNCER, true)
+ keyguardBouncerRepository =
+ KeyguardBouncerRepository(
+ mock(ViewMediatorCallback::class.java),
+ FakeSystemClock(),
+ TestCoroutineScope(),
+ mock(TableLogBuffer::class.java),
+ )
+ alternateBouncerInteractor =
+ AlternateBouncerInteractor(
+ keyguardBouncerRepository,
+ FakeBiometricRepository(),
+ FakeDeviceEntryFingerprintAuthRepository(),
+ FakeSystemClock(),
+ mock(KeyguardUpdateMonitor::class.java),
+ featureFlags,
+ )
+
context.addMockSystemService(DisplayManager::class.java, displayManager)
context.addMockSystemService(WindowManager::class.java, windowManager)
@@ -217,7 +248,10 @@
displayManager,
executor,
handler,
- dumpManager
+ alternateBouncerInteractor,
+ TestCoroutineScope(),
+ featureFlags,
+ dumpManager,
)
overlayController =
@@ -507,6 +541,26 @@
private fun verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible: Boolean) {
sideFpsController.overlayOffsets = sensorLocation
+ }
+
+ fun alternateBouncerVisibility_showAndHideSideFpsUI() = testWithDisplay {
+ // WHEN alternate bouncer is visible
+ keyguardBouncerRepository.setAlternateVisible(true)
+ executor.runAllReady()
+
+ // THEN side fps shows UI
+ verify(windowManager).addView(any(), any())
+ verify(windowManager, never()).removeView(any())
+
+ // WHEN alternate bouncer is no longer visible
+ keyguardBouncerRepository.setAlternateVisible(false)
+ executor.runAllReady()
+
+ // THEN side fps UI is hidden
+ verify(windowManager).removeView(any())
+ }
+
+ private fun hidesWithTaskbar(visible: Boolean) {
overlayController.show(SENSOR_ID, REASON_UNKNOWN)
executor.runAllReady()
@@ -515,7 +569,7 @@
verify(windowManager).addView(any(), any())
verify(windowManager, never()).removeView(any())
- verify(sideFpsView).visibility = if (sfpsViewVisible) View.VISIBLE else View.GONE
+ verify(sideFpsView).visibility = if (visible) View.VISIBLE else View.GONE
}
/**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
index b9a952a..36ed6d5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
@@ -105,6 +105,7 @@
@Mock private lateinit var udfpsController: UdfpsController
@Mock private lateinit var udfpsView: UdfpsView
@Mock private lateinit var udfpsEnrollView: UdfpsEnrollView
+ @Mock private lateinit var udfpsKeyguardView: UdfpsKeyguardView
@Mock private lateinit var activityLaunchAnimator: ActivityLaunchAnimator
@Mock private lateinit var featureFlags: FeatureFlags
@Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
@@ -125,7 +126,7 @@
whenever(inflater.inflate(R.layout.udfps_bp_view, null))
.thenReturn(mock(UdfpsBpView::class.java))
whenever(inflater.inflate(R.layout.udfps_keyguard_view, null))
- .thenReturn(mock(UdfpsKeyguardView::class.java))
+ .thenReturn(udfpsKeyguardView)
whenever(inflater.inflate(R.layout.udfps_fpm_empty_view, null))
.thenReturn(mock(UdfpsFpmEmptyView::class.java))
whenever(udfpsEnrollView.context).thenReturn(context)
@@ -152,7 +153,10 @@
fun showUdfpsOverlay_bp() = withReason(REASON_AUTH_BP) { showUdfpsOverlay() }
@Test
- fun showUdfpsOverlay_keyguard() = withReason(REASON_AUTH_KEYGUARD) { showUdfpsOverlay() }
+ fun showUdfpsOverlay_keyguard() = withReason(REASON_AUTH_KEYGUARD) {
+ showUdfpsOverlay()
+ verify(udfpsKeyguardView).updateSensorLocation(eq(overlayParams.sensorBounds))
+ }
@Test
fun showUdfpsOverlay_settings() = withReason(REASON_AUTH_SETTINGS) { showUdfpsOverlay() }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
index 9060922..81a6bc2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
@@ -27,6 +27,7 @@
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.BouncerView
import com.android.systemui.keyguard.data.repository.BiometricRepository
+import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor
@@ -91,6 +92,7 @@
AlternateBouncerInteractor(
keyguardBouncerRepository,
mock(BiometricRepository::class.java),
+ mock(DeviceEntryFingerprintAuthRepository::class.java),
mock(SystemClock::class.java),
mock(KeyguardUpdateMonitor::class.java),
mock(FeatureFlags::class.java)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java
index bdd496e..71c335e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java
@@ -16,8 +16,6 @@
package com.android.systemui.clipboardoverlay;
-import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_ENABLED;
-
import static com.google.android.setupcompat.util.WizardManagerHelper.SETTINGS_SECURE_USER_SETUP_COMPLETE;
import static org.junit.Assert.assertEquals;
@@ -33,7 +31,6 @@
import android.content.ClipDescription;
import android.content.ClipboardManager;
import android.os.PersistableBundle;
-import android.provider.DeviceConfig;
import android.provider.Settings;
import androidx.test.filters.SmallTest;
@@ -41,9 +38,6 @@
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
-import com.android.systemui.util.DeviceConfigProxyFake;
import org.junit.Before;
import org.junit.Test;
@@ -63,18 +57,11 @@
@Mock
private ClipboardManager mClipboardManager;
@Mock
- private ClipboardOverlayControllerLegacyFactory mClipboardOverlayControllerLegacyFactory;
- @Mock
- private ClipboardOverlayControllerLegacy mOverlayControllerLegacy;
- @Mock
private ClipboardOverlayController mOverlayController;
@Mock
private ClipboardToast mClipboardToast;
@Mock
private UiEventLogger mUiEventLogger;
- @Mock
- private FeatureFlags mFeatureFlags;
- private DeviceConfigProxyFake mDeviceConfigProxy;
private ClipData mSampleClipData;
private String mSampleSource = "Example source";
@@ -97,8 +84,6 @@
mOverlayControllerProvider = () -> mOverlayController;
MockitoAnnotations.initMocks(this);
- when(mClipboardOverlayControllerLegacyFactory.create(any()))
- .thenReturn(mOverlayControllerLegacy);
when(mClipboardManager.hasPrimaryClip()).thenReturn(true);
Settings.Secure.putInt(
mContext.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 1);
@@ -108,26 +93,13 @@
when(mClipboardManager.getPrimaryClip()).thenReturn(mSampleClipData);
when(mClipboardManager.getPrimaryClipSource()).thenReturn(mSampleSource);
- mDeviceConfigProxy = new DeviceConfigProxyFake();
-
- mClipboardListener = new ClipboardListener(getContext(), mDeviceConfigProxy,
- mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory,
- mClipboardToast, mClipboardManager, mUiEventLogger, mFeatureFlags);
+ mClipboardListener = new ClipboardListener(getContext(), mOverlayControllerProvider,
+ mClipboardToast, mClipboardManager, mUiEventLogger);
}
- @Test
- public void test_disabled() {
- mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
- "false", false);
- mClipboardListener.start();
- verifyZeroInteractions(mClipboardManager);
- verifyZeroInteractions(mUiEventLogger);
- }
@Test
- public void test_enabled() {
- mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
- "true", false);
+ public void test_initialization() {
mClipboardListener.start();
verify(mClipboardManager).addPrimaryClipChangedListener(any());
verifyZeroInteractions(mUiEventLogger);
@@ -135,45 +107,6 @@
@Test
public void test_consecutiveCopies() {
- when(mFeatureFlags.isEnabled(Flags.CLIPBOARD_OVERLAY_REFACTOR)).thenReturn(false);
-
- mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
- "true", false);
- mClipboardListener.start();
- mClipboardListener.onPrimaryClipChanged();
-
- verify(mClipboardOverlayControllerLegacyFactory).create(any());
-
- verify(mOverlayControllerLegacy).setClipData(
- mClipDataCaptor.capture(), mStringCaptor.capture());
-
- assertEquals(mSampleClipData, mClipDataCaptor.getValue());
- assertEquals(mSampleSource, mStringCaptor.getValue());
-
- verify(mOverlayControllerLegacy).setOnSessionCompleteListener(mRunnableCaptor.capture());
-
- // Should clear the overlay controller
- mRunnableCaptor.getValue().run();
-
- mClipboardListener.onPrimaryClipChanged();
-
- verify(mClipboardOverlayControllerLegacyFactory, times(2)).create(any());
-
- // Not calling the runnable here, just change the clip again and verify that the overlay is
- // NOT recreated.
-
- mClipboardListener.onPrimaryClipChanged();
-
- verify(mClipboardOverlayControllerLegacyFactory, times(2)).create(any());
- verifyZeroInteractions(mOverlayControllerProvider);
- }
-
- @Test
- public void test_consecutiveCopies_new() {
- when(mFeatureFlags.isEnabled(Flags.CLIPBOARD_OVERLAY_REFACTOR)).thenReturn(true);
-
- mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
- "true", false);
mClipboardListener.start();
mClipboardListener.onPrimaryClipChanged();
@@ -200,7 +133,6 @@
mClipboardListener.onPrimaryClipChanged();
verify(mOverlayControllerProvider, times(2)).get();
- verifyZeroInteractions(mClipboardOverlayControllerLegacyFactory);
}
@Test
@@ -231,23 +163,6 @@
@Test
public void test_logging_enterAndReenter() {
- when(mFeatureFlags.isEnabled(Flags.CLIPBOARD_OVERLAY_REFACTOR)).thenReturn(false);
-
- mClipboardListener.start();
-
- mClipboardListener.onPrimaryClipChanged();
- mClipboardListener.onPrimaryClipChanged();
-
- verify(mUiEventLogger, times(1)).log(
- ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED, 0, mSampleSource);
- verify(mUiEventLogger, times(1)).log(
- ClipboardOverlayEvent.CLIPBOARD_OVERLAY_UPDATED, 0, mSampleSource);
- }
-
- @Test
- public void test_logging_enterAndReenter_new() {
- when(mFeatureFlags.isEnabled(Flags.CLIPBOARD_OVERLAY_REFACTOR)).thenReturn(true);
-
mClipboardListener.start();
mClipboardListener.onPrimaryClipChanged();
@@ -271,6 +186,5 @@
ClipboardOverlayEvent.CLIPBOARD_TOAST_SHOWN, 0, mSampleSource);
verify(mClipboardToast, times(1)).showCopiedToast();
verifyZeroInteractions(mOverlayControllerProvider);
- verifyZeroInteractions(mClipboardOverlayControllerLegacyFactory);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
index ed40c90..85f9961 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
@@ -20,6 +20,7 @@
import android.content.ComponentName
import android.content.Context
import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager
import android.content.pm.ServiceInfo
import android.os.UserHandle
import android.service.controls.ControlsProviderService
@@ -95,6 +96,7 @@
@Mock lateinit var dumpManager: DumpManager
@Mock lateinit var authorizedPanelsRepository: AuthorizedPanelsRepository
@Mock lateinit var featureFlags: FeatureFlags
+ @Mock lateinit var packageManager: PackageManager
val sharedPreferences = FakeSharedPreferences()
lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
@@ -124,6 +126,7 @@
ControlsUiControllerImpl(
Lazy { controlsController },
context,
+ packageManager,
uiExecutor,
bgExecutor,
Lazy { controlsListingController },
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
new file mode 100644
index 0000000..dbaf94f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.controls.ui
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class OverflowMenuAdapterTest : SysuiTestCase() {
+
+ @Test
+ fun testGetItemId() {
+ val ids = listOf(27L, 73L)
+ val labels = listOf("first", "second")
+ val adapter =
+ OverflowMenuAdapter(
+ context,
+ layoutId = 0,
+ labels.zip(ids).map { OverflowMenuAdapter.MenuItem(it.first, it.second) }
+ ) { true }
+
+ ids.forEachIndexed { index, id -> assertThat(adapter.getItemId(index)).isEqualTo(id) }
+ }
+
+ @Test
+ fun testCheckEnabled() {
+ val ids = listOf(27L, 73L)
+ val labels = listOf("first", "second")
+ val adapter =
+ OverflowMenuAdapter(
+ context,
+ layoutId = 0,
+ labels.zip(ids).map { OverflowMenuAdapter.MenuItem(it.first, it.second) }
+ ) { position -> position == 0 }
+
+ assertThat(adapter.isEnabled(0)).isTrue()
+ assertThat(adapter.isEnabled(1)).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
index ebc408e..6b095ff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
@@ -214,6 +214,27 @@
}
@Test
+ public void testSkipEntryAnimationsWhenExitingLowLight() {
+ ArgumentCaptor<DreamOverlayStateController.Callback> callbackCaptor =
+ ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class);
+ when(mStateController.isLowLightActive()).thenReturn(false);
+
+ // Call onInit so that the callback is added.
+ mController.onInit();
+ verify(mStateController).addCallback(callbackCaptor.capture());
+
+ // Send the signal that low light is exiting
+ callbackCaptor.getValue().onExitLowLight();
+
+ // View is attached to trigger animations.
+ mController.onViewAttached();
+
+ // Entry animations should be started then immediately ended to skip to the end.
+ verify(mAnimationsController).startEntryAnimations();
+ verify(mAnimationsController).endAnimations();
+ }
+
+ @Test
public void testCancelDreamEntryAnimationsOnDetached() {
mController.onViewAttached();
mController.onViewDetached();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
index ee989d1..b7d0f29 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
@@ -251,6 +251,30 @@
}
@Test
+ public void testNotifyLowLightExit() {
+ final DreamOverlayStateController stateController =
+ new DreamOverlayStateController(mExecutor, true);
+
+ stateController.addCallback(mCallback);
+ mExecutor.runAllReady();
+ assertThat(stateController.isLowLightActive()).isFalse();
+
+ // Turn low light on then off to trigger the exiting callback.
+ stateController.setLowLightActive(true);
+ stateController.setLowLightActive(false);
+
+ // Callback was only called once, when
+ mExecutor.runAllReady();
+ verify(mCallback, times(1)).onExitLowLight();
+ assertThat(stateController.isLowLightActive()).isFalse();
+
+ // Set with false again, which should not cause the callback to trigger again.
+ stateController.setLowLightActive(false);
+ mExecutor.runAllReady();
+ verify(mCallback, times(1)).onExitLowLight();
+ }
+
+ @Test
public void testNotifyEntryAnimationsFinishedChanged() {
final DreamOverlayStateController stateController =
new DreamOverlayStateController(mExecutor, true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
index c0af0cb..fb54d6d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -62,6 +62,7 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -184,6 +185,7 @@
mainDispatcher = testDispatcher,
backgroundHandler = backgroundHandler,
)
+ underTest.mainDispatcher = UnconfinedTestDispatcher()
underTest.attachInfoForTesting(
context,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
index 8da4eae..58cdec4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
@@ -19,6 +19,7 @@
import android.app.StatusBarManager
import android.content.Context
+import android.content.pm.PackageManager
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.camera.CameraGestureHelper
@@ -32,7 +33,6 @@
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.Mock
-import org.mockito.Mockito.anyInt
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -43,16 +43,19 @@
@Mock private lateinit var cameraGestureHelper: CameraGestureHelper
@Mock private lateinit var context: Context
+ @Mock private lateinit var packageManager: PackageManager
private lateinit var underTest: CameraQuickAffordanceConfig
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
+ setLaunchable(true)
underTest =
CameraQuickAffordanceConfig(
context,
+ packageManager,
) {
cameraGestureHelper
}
@@ -86,6 +89,7 @@
}
private fun setLaunchable(isLaunchable: Boolean) {
- whenever(cameraGestureHelper.canCameraGestureBeLaunched(anyInt())).thenReturn(isLaunchable)
+ whenever(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY))
+ .thenReturn(isLaunchable)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
index c4ae2db..9203f05 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
@@ -55,7 +55,11 @@
MockitoAnnotations.initMocks(this)
testScope = TestScope()
- underTest = DeviceEntryFingerprintAuthRepositoryImpl(keyguardUpdateMonitor)
+ underTest =
+ DeviceEntryFingerprintAuthRepositoryImpl(
+ keyguardUpdateMonitor,
+ testScope.backgroundScope,
+ )
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
index 1da7241..68fff26 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt
@@ -23,6 +23,7 @@
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeBiometricRepository
+import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.KeyguardBouncerRepository
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.util.time.FakeSystemClock
@@ -46,6 +47,8 @@
private lateinit var underTest: AlternateBouncerInteractor
private lateinit var bouncerRepository: KeyguardBouncerRepository
private lateinit var biometricRepository: FakeBiometricRepository
+ private lateinit var deviceEntryFingerprintAuthRepository:
+ FakeDeviceEntryFingerprintAuthRepository
@Mock private lateinit var systemClock: SystemClock
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock private lateinit var bouncerLogger: TableLogBuffer
@@ -62,11 +65,13 @@
bouncerLogger,
)
biometricRepository = FakeBiometricRepository()
+ deviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
featureFlags = FakeFeatureFlags().apply { this.set(Flags.MODERN_ALTERNATE_BOUNCER, true) }
underTest =
AlternateBouncerInteractor(
bouncerRepository,
biometricRepository,
+ deviceEntryFingerprintAuthRepository,
systemClock,
keyguardUpdateMonitor,
featureFlags,
@@ -112,6 +117,14 @@
}
@Test
+ fun canShowAlternateBouncerForFingerprint_fingerprintLockedOut() {
+ givenCanShowAlternateBouncer()
+ deviceEntryFingerprintAuthRepository.setLockedOut(true)
+
+ assertFalse(underTest.canShowAlternateBouncerForFingerprint())
+ }
+
+ @Test
fun show_whenCanShow() {
givenCanShowAlternateBouncer()
@@ -148,6 +161,7 @@
biometricRepository.setFingerprintEnrolled(true)
biometricRepository.setStrongBiometricAllowed(true)
biometricRepository.setFingerprintEnabledByDevicePolicy(true)
+ deviceEntryFingerprintAuthRepository.setLockedOut(false)
}
private fun givenCannotShowAlternateBouncer() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskIntentResolverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskIntentResolverTest.kt
index bbe60f4..18be92b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskIntentResolverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskIntentResolverTest.kt
@@ -16,17 +16,14 @@
package com.android.systemui.notetask
-import android.content.ComponentName
+import android.app.role.RoleManager
import android.content.Intent
-import android.content.pm.ActivityInfo
-import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
-import android.content.pm.PackageManager.ResolveInfoFlags
-import android.content.pm.ResolveInfo
import android.test.suitebuilder.annotation.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.systemui.SysuiTestCase
import com.android.systemui.notetask.NoteTaskIntentResolver.Companion.ACTION_CREATE_NOTE
+import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import org.junit.Before
@@ -47,172 +44,39 @@
internal class NoteTaskIntentResolverTest : SysuiTestCase() {
@Mock lateinit var packageManager: PackageManager
+ @Mock lateinit var roleManager: RoleManager
- private lateinit var resolver: NoteTaskIntentResolver
+ private lateinit var underTest: NoteTaskIntentResolver
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- resolver = NoteTaskIntentResolver(packageManager)
- }
-
- private fun createResolveInfo(
- activityInfo: ActivityInfo? = createActivityInfo(),
- ): ResolveInfo {
- return ResolveInfo().apply { this.activityInfo = activityInfo }
- }
-
- private fun createActivityInfo(
- packageName: String = "PackageName",
- name: String? = "ActivityName",
- exported: Boolean = true,
- enabled: Boolean = true,
- showWhenLocked: Boolean = true,
- turnScreenOn: Boolean = true,
- ): ActivityInfo {
- return ActivityInfo().apply {
- this.name = name
- this.exported = exported
- this.enabled = enabled
- if (showWhenLocked) {
- flags = flags or ActivityInfo.FLAG_SHOW_WHEN_LOCKED
- }
- if (turnScreenOn) {
- flags = flags or ActivityInfo.FLAG_TURN_SCREEN_ON
- }
- this.applicationInfo = ApplicationInfo().apply { this.packageName = packageName }
- }
- }
-
- private fun givenQueryIntentActivities(block: () -> List<ResolveInfo>) {
- whenever(packageManager.queryIntentActivities(any(), any<ResolveInfoFlags>()))
- .thenReturn(block())
- }
-
- private fun givenResolveActivity(block: () -> ResolveInfo?) {
- whenever(packageManager.resolveActivity(any(), any<ResolveInfoFlags>())).thenReturn(block())
+ underTest = NoteTaskIntentResolver(context, roleManager)
}
@Test
- fun resolveIntent_shouldReturnNotesIntent() {
- givenQueryIntentActivities { listOf(createResolveInfo()) }
- givenResolveActivity { createResolveInfo(activityInfo = createActivityInfo()) }
+ fun resolveIntent_shouldReturnIntentInStylusMode() {
+ val packageName = "com.android.note.app"
+ whenever(roleManager.getRoleHoldersAsUser(NoteTaskIntentResolver.ROLE_NOTES, context.user))
+ .then { listOf(packageName) }
- val actual = resolver.resolveIntent()
+ val actual = underTest.resolveIntent()
- val expected =
- Intent(ACTION_CREATE_NOTE)
- .setPackage("PackageName")
- .setComponent(ComponentName("PackageName", "ActivityName"))
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- // Compares the string representation of both intents, as they are different instances.
- assertThat(actual.toString()).isEqualTo(expected.toString())
+ requireNotNull(actual) { "Intent must not be null" }
+ assertThat(actual.action).isEqualTo(ACTION_CREATE_NOTE)
+ assertThat(actual.`package`).isEqualTo(packageName)
+ val expectedExtra = actual.getExtra(NoteTaskIntentResolver.INTENT_EXTRA_USE_STYLUS_MODE)
+ assertThat(expectedExtra).isEqualTo(true)
+ val expectedFlag = actual.flags and Intent.FLAG_ACTIVITY_NEW_TASK
+ assertThat(expectedFlag).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
}
@Test
- fun resolveIntent_activityInfoEnabledIsFalse_shouldReturnNull() {
- givenQueryIntentActivities { listOf(createResolveInfo()) }
- givenResolveActivity {
- createResolveInfo(activityInfo = createActivityInfo(enabled = false))
- }
+ fun resolveIntent_noRoleHolderIsSet_shouldReturnNull() {
+ whenever(roleManager.getRoleHoldersAsUser(eq(NoteTaskIntentResolver.ROLE_NOTES), any()))
+ .then { listOf<String>() }
- val actual = resolver.resolveIntent()
-
- assertThat(actual).isNull()
- }
-
- @Test
- fun resolveIntent_activityInfoExportedIsFalse_shouldReturnNull() {
- givenQueryIntentActivities { listOf(createResolveInfo()) }
- givenResolveActivity {
- createResolveInfo(activityInfo = createActivityInfo(exported = false))
- }
-
- val actual = resolver.resolveIntent()
-
- assertThat(actual).isNull()
- }
-
- @Test
- fun resolveIntent_activityInfoShowWhenLockedIsFalse_shouldReturnNull() {
- givenQueryIntentActivities { listOf(createResolveInfo()) }
- givenResolveActivity {
- createResolveInfo(activityInfo = createActivityInfo(showWhenLocked = false))
- }
-
- val actual = resolver.resolveIntent()
-
- assertThat(actual).isNull()
- }
-
- @Test
- fun resolveIntent_activityInfoTurnScreenOnIsFalse_shouldReturnNull() {
- givenQueryIntentActivities { listOf(createResolveInfo()) }
- givenResolveActivity {
- createResolveInfo(activityInfo = createActivityInfo(turnScreenOn = false))
- }
-
- val actual = resolver.resolveIntent()
-
- assertThat(actual).isNull()
- }
-
- @Test
- fun resolveIntent_activityInfoNameIsBlank_shouldReturnNull() {
- givenQueryIntentActivities { listOf(createResolveInfo()) }
- givenResolveActivity { createResolveInfo(activityInfo = createActivityInfo(name = "")) }
-
- val actual = resolver.resolveIntent()
-
- assertThat(actual).isNull()
- }
-
- @Test
- fun resolveIntent_activityInfoNameIsNull_shouldReturnNull() {
- givenQueryIntentActivities { listOf(createResolveInfo()) }
- givenResolveActivity { createResolveInfo(activityInfo = createActivityInfo(name = null)) }
-
- val actual = resolver.resolveIntent()
-
- assertThat(actual).isNull()
- }
-
- @Test
- fun resolveIntent_activityInfoIsNull_shouldReturnNull() {
- givenQueryIntentActivities { listOf(createResolveInfo()) }
- givenResolveActivity { createResolveInfo(activityInfo = null) }
-
- val actual = resolver.resolveIntent()
-
- assertThat(actual).isNull()
- }
-
- @Test
- fun resolveIntent_resolveActivityIsNull_shouldReturnNull() {
- givenQueryIntentActivities { listOf(createResolveInfo()) }
- givenResolveActivity { null }
-
- val actual = resolver.resolveIntent()
-
- assertThat(actual).isNull()
- }
-
- @Test
- fun resolveIntent_packageNameIsBlank_shouldReturnNull() {
- givenQueryIntentActivities {
- listOf(createResolveInfo(createActivityInfo(packageName = "")))
- }
-
- val actual = resolver.resolveIntent()
-
- assertThat(actual).isNull()
- }
-
- @Test
- fun resolveIntent_activityNotFoundForAction_shouldReturnNull() {
- givenQueryIntentActivities { emptyList() }
-
- val actual = resolver.resolveIntent()
+ val actual = underTest.resolveIntent()
assertThat(actual).isNull()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/FgsManagerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/FgsManagerControllerTest.java
index bbd62c7..6f54f62 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/FgsManagerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/FgsManagerControllerTest.java
@@ -147,16 +147,25 @@
setUserProfiles(0);
setShowUserVisibleJobs(true);
- UserVisibleJobSummary j1 = new UserVisibleJobSummary(0, 0, "pkg1", null, 0);
- UserVisibleJobSummary j2 = new UserVisibleJobSummary(1, 0, "pkg2", null, 1);
+ UserVisibleJobSummary j1 = new UserVisibleJobSummary(0, "pkg1", 0, "pkg1", null, 0);
+ UserVisibleJobSummary j2 = new UserVisibleJobSummary(1, "pkg2", 0, "pkg2", null, 1);
+ // pkg2 is performing work on behalf of pkg3. Since pkg2 will show the notification
+ // It should be the one shown in TaskManager.
+ UserVisibleJobSummary j3 = new UserVisibleJobSummary(1, "pkg2", 0, "pkg3", null, 3);
Assert.assertEquals(0, mFmc.getNumRunningPackages());
mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j1, true);
Assert.assertEquals(1, mFmc.getNumRunningPackages());
mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j2, true);
Assert.assertEquals(2, mFmc.getNumRunningPackages());
+ // Job3 starts running. The source package (pkg3) shouldn't matter. Since pkg2 is
+ // already running, the running package count shouldn't increase.
+ mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j3, true);
+ Assert.assertEquals(2, mFmc.getNumRunningPackages());
mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j1, false);
Assert.assertEquals(1, mFmc.getNumRunningPackages());
mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j2, false);
+ Assert.assertEquals(1, mFmc.getNumRunningPackages());
+ mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j3, false);
Assert.assertEquals(0, mFmc.getNumRunningPackages());
}
@@ -167,8 +176,8 @@
Binder b1 = new Binder();
Binder b2 = new Binder();
- UserVisibleJobSummary j1 = new UserVisibleJobSummary(0, 0, "pkg1", null, 0);
- UserVisibleJobSummary j3 = new UserVisibleJobSummary(1, 0, "pkg3", null, 1);
+ UserVisibleJobSummary j1 = new UserVisibleJobSummary(0, "pkg1", 0, "pkg1", null, 0);
+ UserVisibleJobSummary j3 = new UserVisibleJobSummary(1, "pkg3", 0, "pkg3", null, 1);
Assert.assertEquals(0, mFmc.getNumRunningPackages());
mIForegroundServiceObserver.onForegroundStateChanged(b1, "pkg1", 0, true);
Assert.assertEquals(1, mFmc.getNumRunningPackages());
@@ -359,8 +368,8 @@
// pkg1 has only job
// pkg2 has both job and fgs
// pkg3 has only fgs
- UserVisibleJobSummary j1 = new UserVisibleJobSummary(0, 0, "pkg1", null, 0);
- UserVisibleJobSummary j2 = new UserVisibleJobSummary(1, 0, "pkg2", null, 1);
+ UserVisibleJobSummary j1 = new UserVisibleJobSummary(0, "pkg1", 0, "pkg1", null, 0);
+ UserVisibleJobSummary j2 = new UserVisibleJobSummary(1, "pkg2", 0, "pkg2", null, 1);
Binder b2 = new Binder();
Binder b3 = new Binder();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
index 43b6e41..cd6778e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
@@ -33,6 +33,7 @@
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.BcSmartspaceConfigPlugin
@@ -118,6 +119,9 @@
private lateinit var configPlugin: BcSmartspaceConfigPlugin
@Mock
+ private lateinit var dumpManager: DumpManager
+
+ @Mock
private lateinit var controllerListener: SmartspaceTargetListener
@Captor
@@ -206,6 +210,7 @@
statusBarStateController,
deviceProvisionedController,
keyguardBypassController,
+ dumpManager,
execution,
executor,
bgExecutor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt
index b32058f..3dccbbf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt
@@ -45,7 +45,7 @@
@Test
fun testLogNetworkCapsChange_bufferHasInfo() {
- logger.logOnCapabilitiesChanged(NET_1, NET_1_CAPS)
+ logger.logOnCapabilitiesChanged(NET_1, NET_1_CAPS, isDefaultNetworkCallback = true)
val stringWriter = StringWriter()
buffer.dump(PrintWriter(stringWriter), tailLength = 0)
@@ -54,6 +54,7 @@
val expectedNetId = NET_1_ID.toString()
val expectedCaps = NET_1_CAPS.toString()
+ assertThat(actualString).contains("true")
assertThat(actualString).contains(expectedNetId)
assertThat(actualString).contains(expectedCaps)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
index 87ce8fa..7099f1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
@@ -21,7 +21,10 @@
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
+import android.net.NetworkCapabilities.TRANSPORT_VPN
import android.net.NetworkCapabilities.TRANSPORT_WIFI
+import android.net.TransportInfo
+import android.net.VpnTransportInfo
import android.net.vcn.VcnTransportInfo
import android.net.wifi.WifiInfo
import android.net.wifi.WifiManager
@@ -243,6 +246,54 @@
job.cancel()
}
+ /** Regression test for b/266628069. */
+ @Test
+ fun isWifiDefault_transportInfoIsNotWifi_andNoWifiTransport_false() =
+ runBlocking(IMMEDIATE) {
+ val job = underTest.isWifiDefault.launchIn(this)
+
+ val transportInfo = VpnTransportInfo(
+ /* type= */ 0,
+ /* sessionId= */ "sessionId",
+ )
+ val networkCapabilities = mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_VPN)).thenReturn(true)
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(false)
+ whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
+ whenever(it.transportInfo).thenReturn(transportInfo)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, networkCapabilities)
+
+ assertThat(underTest.isWifiDefault.value).isFalse()
+
+ job.cancel()
+ }
+
+ /** Regression test for b/266628069. */
+ @Test
+ fun isWifiDefault_transportInfoIsNotWifi_butHasWifiTransport_true() =
+ runBlocking(IMMEDIATE) {
+ val job = underTest.isWifiDefault.launchIn(this)
+
+ val transportInfo = VpnTransportInfo(
+ /* type= */ 0,
+ /* sessionId= */ "sessionId",
+ )
+ val networkCapabilities = mock<NetworkCapabilities>().also {
+ whenever(it.hasTransport(TRANSPORT_VPN)).thenReturn(true)
+ whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
+ whenever(it.hasTransport(TRANSPORT_CELLULAR)).thenReturn(false)
+ whenever(it.transportInfo).thenReturn(transportInfo)
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, networkCapabilities)
+
+ assertThat(underTest.isWifiDefault.value).isTrue()
+
+ job.cancel()
+ }
+
@Test
fun isWifiDefault_cellularVcnNetwork_isTrue() = runBlocking(IMMEDIATE) {
val job = underTest.isWifiDefault.launchIn(this)
@@ -260,6 +311,24 @@
}
@Test
+ fun wifiNetwork_cellularAndWifiTransports_usesCellular_isTrue() =
+ runBlocking(IMMEDIATE) {
+ val job = underTest.isWifiDefault.launchIn(this)
+
+ val capabilities = mock<NetworkCapabilities>().apply {
+ whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
+ whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
+ whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO))
+ }
+
+ getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(underTest.isWifiDefault.value).isTrue()
+
+ job.cancel()
+ }
+
+ @Test
fun isWifiDefault_cellularNotVcnNetwork_isFalse() = runBlocking(IMMEDIATE) {
val job = underTest.isWifiDefault.launchIn(this)
@@ -467,6 +536,28 @@
job.cancel()
}
+ /** Regression test for b/266628069. */
+ @Test
+ fun wifiNetwork_transportInfoIsNotWifi_flowHasNoNetwork() =
+ runBlocking(IMMEDIATE) {
+ var latest: WifiNetworkModel? = null
+ val job = underTest
+ .wifiNetwork
+ .onEach { latest = it }
+ .launchIn(this)
+
+ val transportInfo = VpnTransportInfo(
+ /* type= */ 0,
+ /* sessionId= */ "sessionId",
+ )
+ getNetworkCallback()
+ .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(transportInfo))
+
+ assertThat(latest is WifiNetworkModel.Inactive).isTrue()
+
+ job.cancel()
+ }
+
@Test
fun wifiNetwork_cellularVcnNetworkAdded_flowHasNetwork() = runBlocking(IMMEDIATE) {
var latest: WifiNetworkModel? = null
@@ -535,6 +626,31 @@
}
@Test
+ fun wifiNetwork_cellularAndWifiTransports_usesCellular() =
+ runBlocking(IMMEDIATE) {
+ var latest: WifiNetworkModel? = null
+ val job = underTest
+ .wifiNetwork
+ .onEach { latest = it }
+ .launchIn(this)
+
+ val capabilities = mock<NetworkCapabilities>().apply {
+ whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true)
+ whenever(this.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
+ whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO))
+ }
+
+ getNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities)
+
+ assertThat(latest is WifiNetworkModel.Active).isTrue()
+ val latestActive = latest as WifiNetworkModel.Active
+ assertThat(latestActive.networkId).isEqualTo(NETWORK_ID)
+ assertThat(latestActive.ssid).isEqualTo(SSID)
+
+ job.cancel()
+ }
+
+ @Test
fun wifiNetwork_newPrimaryWifiNetwork_flowHasNewNetwork() = runBlocking(IMMEDIATE) {
var latest: WifiNetworkModel? = null
val job = underTest
@@ -870,12 +986,12 @@
}
private fun createWifiNetworkCapabilities(
- wifiInfo: WifiInfo,
+ transportInfo: TransportInfo,
isValidated: Boolean = true,
): NetworkCapabilities {
return mock<NetworkCapabilities>().also {
whenever(it.hasTransport(TRANSPORT_WIFI)).thenReturn(true)
- whenever(it.transportInfo).thenReturn(wifiInfo)
+ whenever(it.transportInfo).thenReturn(transportInfo)
whenever(it.hasCapability(NET_CAPABILITY_VALIDATED)).thenReturn(isValidated)
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt
new file mode 100644
index 0000000..5641832
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.keyguard.data.repository
+
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+class FakeDeviceEntryFingerprintAuthRepository : DeviceEntryFingerprintAuthRepository {
+ private val _isLockedOut = MutableStateFlow<Boolean>(false)
+ override val isLockedOut: StateFlow<Boolean> = _isLockedOut.asStateFlow()
+
+ fun setLockedOut(lockedOut: Boolean) {
+ _isLockedOut.value = lockedOut
+ }
+}
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 7db27ac..b68adab 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -199,8 +199,10 @@
intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true);
PendingIntent p = PendingIntent.getActivityAsUser(this, /* requestCode= */ 0,
- intent, PendingIntent.FLAG_MUTABLE, /* options= */ null,
- UserHandle.CURRENT);
+ intent,
+ PendingIntent.FLAG_MUTABLE
+ | PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT,
+ /* options= */ null, UserHandle.CURRENT);
if (sDebug) {
Slog.d(TAG, "startActivity add save UI restored with intent=" + intent);
}
diff --git a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncCallback.java b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncCallback.java
index 56e777f..7c339d2 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncCallback.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncCallback.java
@@ -22,4 +22,6 @@
abstract void processCallControlAction(int crossDeviceCallId, int callControlAction);
abstract void requestCrossDeviceSync(int userId);
+
+ abstract void updateStatus(int userId, boolean shouldSyncCallMetadata);
}
diff --git a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncInCallService.java b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncInCallService.java
index 97e70a4..ae4766a 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncInCallService.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncInCallService.java
@@ -39,6 +39,8 @@
@VisibleForTesting
final Map<Call, CrossDeviceCall> mCurrentCalls = new HashMap<>();
+ @VisibleForTesting
+ boolean mShouldSync;
final Call.Callback mTelecomCallback = new Call.Callback() {
@Override
public void onDetailsChanged(Call call, Call.Details details) {
@@ -92,12 +94,29 @@
@Override
void requestCrossDeviceSync(int userId) {
}
+
+ @Override
+ void updateStatus(int userId, boolean shouldSyncCallMetadata) {
+ if (userId == getUserId()) {
+ mShouldSync = shouldSyncCallMetadata;
+ if (shouldSyncCallMetadata) {
+ initializeCalls();
+ } else {
+ mCurrentCalls.clear();
+ }
+ }
+ }
};
@Override
public void onCreate() {
super.onCreate();
- if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)) {
+ initializeCalls();
+ }
+
+ private void initializeCalls() {
+ if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)
+ && mShouldSync) {
mCurrentCalls.putAll(getCalls().stream().collect(Collectors.toMap(call -> call,
call -> new CrossDeviceCall(getPackageManager(), call, getCallAudioState()))));
}
@@ -119,7 +138,8 @@
@Override
public void onCallAdded(Call call) {
- if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)) {
+ if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)
+ && mShouldSync) {
mCurrentCalls.put(call,
new CrossDeviceCall(getPackageManager(), call, getCallAudioState()));
}
@@ -127,21 +147,24 @@
@Override
public void onCallRemoved(Call call) {
- if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)) {
+ if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)
+ && mShouldSync) {
mCurrentCalls.remove(call);
}
}
@Override
public void onMuteStateChanged(boolean isMuted) {
- if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)) {
+ if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)
+ && mShouldSync) {
mCurrentCalls.values().forEach(call -> call.updateMuted(isMuted));
}
}
@Override
public void onSilenceRinger() {
- if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)) {
+ if (CompanionDeviceConfig.isEnabled(CompanionDeviceConfig.ENABLE_CONTEXT_SYNC_TELECOM)
+ && mShouldSync) {
mCurrentCalls.values().forEach(call -> call.updateSilencedIfRinging());
}
}
diff --git a/services/core/java/android/os/BatteryStatsInternal.java b/services/core/java/android/os/BatteryStatsInternal.java
index b70cbe3..9c2de65 100644
--- a/services/core/java/android/os/BatteryStatsInternal.java
+++ b/services/core/java/android/os/BatteryStatsInternal.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.net.Network;
import com.android.internal.os.BinderCallsStats;
import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
@@ -82,6 +83,15 @@
public abstract void noteJobsDeferred(int uid, int numDeferred, long sinceLast);
/**
+ * Informs battery stats of a data packet that woke up the CPU.
+ *
+ * @param network The network over which the packet arrived.
+ * @param elapsedMillis The time of the packet's arrival in elapsed timebase.
+ * @param uid The uid that received the packet.
+ */
+ public abstract void noteCpuWakingNetworkPacket(Network network, long elapsedMillis, int uid);
+
+ /**
* Informs battery stats of binder stats for the given work source UID.
*/
public abstract void noteBinderCallStats(int workSourceUid, long incrementalBinderCallCount,
diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java
index ecc303f..0cae1f5 100644
--- a/services/core/java/com/android/server/BinaryTransparencyService.java
+++ b/services/core/java/com/android/server/BinaryTransparencyService.java
@@ -278,16 +278,54 @@
+ " and is now updated to: " + currentTimeMs);
mMeasurementsLastRecordedMs = currentTimeMs;
- PackageManager pm = mContext.getPackageManager();
Set<String> packagesMeasured = new HashSet<>();
// measure all APEXs first
if (DEBUG) {
Slog.d(TAG, "Measuring APEXs...");
}
- for (PackageInfo packageInfo : getCurrentInstalledApexs()) {
- packagesMeasured.add(packageInfo.packageName);
+ List<IBinaryTransparencyService.ApexInfo> allApexInfo = collectAllApexInfo();
+ for (IBinaryTransparencyService.ApexInfo apexInfo : allApexInfo) {
+ packagesMeasured.add(apexInfo.packageName);
+ recordApexInfo(apexInfo);
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "Measured " + packagesMeasured.size()
+ + " packages after considering APEXs.");
+ }
+
+ // proceed with all preloaded apps
+ List<IBinaryTransparencyService.AppInfo> allUpdatedPreloadInfo =
+ collectAllUpdatedPreloadInfo(packagesMeasured);
+ for (IBinaryTransparencyService.AppInfo appInfo : allUpdatedPreloadInfo) {
+ packagesMeasured.add(appInfo.packageName);
+ writeAppInfoToLog(appInfo);
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "Measured " + packagesMeasured.size()
+ + " packages after considering preloads");
+ }
+
+ if (CompatChanges.isChangeEnabled(LOG_MBA_INFO)) {
+ // lastly measure all newly installed MBAs
+ List<IBinaryTransparencyService.AppInfo> allMbaInfo =
+ collectAllMbaInfo(packagesMeasured);
+ for (IBinaryTransparencyService.AppInfo appInfo : allUpdatedPreloadInfo) {
+ packagesMeasured.add(appInfo.packageName);
+ writeAppInfoToLog(appInfo);
+ }
+ }
+ if (DEBUG) {
+ long timeSpentMeasuring = System.currentTimeMillis() - currentTimeMs;
+ Slog.d(TAG, "Measured " + packagesMeasured.size()
+ + " packages altogether in " + timeSpentMeasuring + "ms");
+ }
+ }
+
+ private List<IBinaryTransparencyService.ApexInfo> collectAllApexInfo() {
+ var results = new ArrayList<IBinaryTransparencyService.ApexInfo>();
+ for (PackageInfo packageInfo : getCurrentInstalledApexs()) {
Bundle apexMeasurement = measurePackage(packageInfo);
var apexInfo = new IBinaryTransparencyService.ApexInfo();
@@ -299,22 +337,21 @@
apexInfo.signerDigests =
computePackageSignerSha256Digests(packageInfo.signingInfo);
- recordApexInfo(apexInfo);
+ results.add(apexInfo);
}
- if (DEBUG) {
- Slog.d(TAG, "Measured " + packagesMeasured.size()
- + " packages after considering APEXs.");
- }
+ return results;
+ }
- // proceed with all preloaded apps
+ private List<IBinaryTransparencyService.AppInfo> collectAllUpdatedPreloadInfo(
+ Set<String> packagesToSkip) {
+ var results = new ArrayList<IBinaryTransparencyService.AppInfo>();
+ PackageManager pm = mContext.getPackageManager();
for (PackageInfo packageInfo : pm.getInstalledPackages(
PackageManager.PackageInfoFlags.of(PackageManager.MATCH_FACTORY_ONLY
| PackageManager.GET_SIGNING_CERTIFICATES))) {
- if (packagesMeasured.contains(packageInfo.packageName)) {
+ if (packagesToSkip.contains(packageInfo.packageName)) {
continue;
}
- packagesMeasured.add(packageInfo.packageName);
-
int mbaStatus = MBA_STATUS_PRELOADED;
if (packageInfo.signingInfo == null) {
Slog.d(TAG, "Preload " + packageInfo.packageName + " at "
@@ -347,61 +384,53 @@
computePackageSignerSha256Digests(packageInfo.signingInfo);
appInfo.mbaStatus = mbaStatus;
- writeAppInfoToLog(appInfo);
+ results.add(appInfo);
}
}
- if (DEBUG) {
- Slog.d(TAG, "Measured " + packagesMeasured.size()
- + " packages after considering preloads");
- }
+ return results;
+ }
- if (CompatChanges.isChangeEnabled(LOG_MBA_INFO)) {
- // lastly measure all newly installed MBAs
- for (PackageInfo packageInfo : getNewlyInstalledMbas()) {
- if (packagesMeasured.contains(packageInfo.packageName)) {
- continue;
- }
- packagesMeasured.add(packageInfo.packageName);
-
- Bundle packageMeasurement = measurePackage(packageInfo);
-
- if (DEBUG) {
- Slog.d(TAG,
- "Extracting InstallSourceInfo for " + packageInfo.packageName);
- }
- var appInfo = new IBinaryTransparencyService.AppInfo();
- appInfo.packageName = packageInfo.packageName;
- appInfo.longVersion = packageInfo.getLongVersionCode();
- appInfo.digest = packageMeasurement.getByteArray(BUNDLE_CONTENT_DIGEST);
- appInfo.digestAlgorithm =
- packageMeasurement.getInt(BUNDLE_CONTENT_DIGEST_ALGORITHM);
- appInfo.signerDigests =
- computePackageSignerSha256Digests(packageInfo.signingInfo);
- appInfo.mbaStatus = MBA_STATUS_NEW_INSTALL;
-
- // extract package's InstallSourceInfo
- InstallSourceInfo installSourceInfo = getInstallSourceInfo(
- packageInfo.packageName);
- if (installSourceInfo != null) {
- appInfo.initiator = installSourceInfo.getInitiatingPackageName();
- SigningInfo initiatorSignerInfo =
- installSourceInfo.getInitiatingPackageSigningInfo();
- if (initiatorSignerInfo != null) {
- appInfo.initiatorSignerDigests =
- computePackageSignerSha256Digests(initiatorSignerInfo);
- }
- appInfo.installer = installSourceInfo.getInstallingPackageName();
- appInfo.originator = installSourceInfo.getOriginatingPackageName();
- }
-
- writeAppInfoToLog(appInfo);
+ private List<IBinaryTransparencyService.AppInfo> collectAllMbaInfo(
+ Set<String> packagesToSkip) {
+ var results = new ArrayList<IBinaryTransparencyService.AppInfo>();
+ for (PackageInfo packageInfo : getNewlyInstalledMbas()) {
+ if (packagesToSkip.contains(packageInfo.packageName)) {
+ continue;
}
+
+ Bundle packageMeasurement = measurePackage(packageInfo);
+ if (DEBUG) {
+ Slog.d(TAG,
+ "Extracting InstallSourceInfo for " + packageInfo.packageName);
+ }
+ var appInfo = new IBinaryTransparencyService.AppInfo();
+ appInfo.packageName = packageInfo.packageName;
+ appInfo.longVersion = packageInfo.getLongVersionCode();
+ appInfo.digest = packageMeasurement.getByteArray(BUNDLE_CONTENT_DIGEST);
+ appInfo.digestAlgorithm =
+ packageMeasurement.getInt(BUNDLE_CONTENT_DIGEST_ALGORITHM);
+ appInfo.signerDigests =
+ computePackageSignerSha256Digests(packageInfo.signingInfo);
+ appInfo.mbaStatus = MBA_STATUS_NEW_INSTALL;
+
+ // extract package's InstallSourceInfo
+ InstallSourceInfo installSourceInfo = getInstallSourceInfo(
+ packageInfo.packageName);
+ if (installSourceInfo != null) {
+ appInfo.initiator = installSourceInfo.getInitiatingPackageName();
+ SigningInfo initiatorSignerInfo =
+ installSourceInfo.getInitiatingPackageSigningInfo();
+ if (initiatorSignerInfo != null) {
+ appInfo.initiatorSignerDigests =
+ computePackageSignerSha256Digests(initiatorSignerInfo);
+ }
+ appInfo.installer = installSourceInfo.getInstallingPackageName();
+ appInfo.originator = installSourceInfo.getOriginatingPackageName();
+ }
+
+ results.add(appInfo);
}
- if (DEBUG) {
- long timeSpentMeasuring = System.currentTimeMillis() - currentTimeMs;
- Slog.d(TAG, "Measured " + packagesMeasured.size()
- + " packages altogether in " + timeSpentMeasuring + "ms");
- }
+ return results;
}
private void recordApexInfo(IBinaryTransparencyService.ApexInfo apexInfo) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 73bb8d7..f0b168d 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1272,7 +1272,8 @@
: (wasStartRequested || !r.getConnections().isEmpty()
? SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_HOT
: SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM),
- getShortProcessNameForStats(callingUid, callingProcessName));
+ getShortProcessNameForStats(callingUid, callingProcessName),
+ getShortServiceNameForStats(r));
if (r.startRequested && addToStarting) {
boolean first = smap.mStartingBackground.size() == 0;
@@ -1311,6 +1312,11 @@
return processName;
}
+ private @Nullable String getShortServiceNameForStats(@NonNull ServiceRecord r) {
+ final ComponentName cn = r.getComponentName();
+ return cn != null ? cn.getShortClassName() : null;
+ }
+
private void stopServiceLocked(ServiceRecord service, boolean enqueueOomAdj) {
try {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "stopServiceLocked()");
@@ -3488,7 +3494,8 @@
: (wasStartRequested || hadConnections
? SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_HOT
: SERVICE_REQUEST_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_WARM),
- getShortProcessNameForStats(callingUid, callerApp.processName));
+ getShortProcessNameForStats(callingUid, callerApp.processName),
+ getShortServiceNameForStats(s));
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
+ ": received=" + b.intent.received
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 0a73eaa..64662b5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -3830,9 +3830,11 @@
pw.println(" Print this help text.");
pw.println(" start-activity [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]");
pw.println(" [--sampling INTERVAL] [--streaming] [-R COUNT] [-S]");
- pw.println(" [--track-allocation] [--user <USER_ID> | current] <INTENT>");
+ pw.println(" [--track-allocation] [--user <USER_ID> | current] [--suspend]");
+ pw.println(" <INTENT>");
pw.println(" Start an Activity. Options are:");
pw.println(" -D: enable debugging");
+ pw.println(" --suspend: debugged app suspend threads at startup (only with -D)");
pw.println(" -N: enable native debugging");
pw.println(" -W: wait for launch to complete");
pw.println(" --start-profiler <FILE>: start profiler and send results to <FILE>");
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index dcc1592..f09622f 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -457,6 +457,11 @@
}
@Override
+ public void noteCpuWakingNetworkPacket(Network network, long elapsedMillis, int uid) {
+ Slog.d(TAG, "Wakeup due to incoming packet on network " + network + " to uid " + uid);
+ }
+
+ @Override
public void noteBinderCallStats(int workSourceUid, long incrementatCallCount,
Collection<BinderCallsStats.CallStat> callStats) {
synchronized (BatteryStatsService.this.mLock) {
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
index 7d9b272..a9a77bf 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
@@ -593,16 +593,19 @@
Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
assertCalledByPackageOwner(callingPackage);
- for (ClientRequest cr : mExistingClientRequests) {
- if (cr.getPackageName().equals(callingPackage)) {
- AmbientContextManagerPerUserService service =
- getAmbientContextManagerPerUserServiceForEventTypes(
- UserHandle.getCallingUserId(), cr.getRequest().getEventTypes());
- if (service != null) {
- service.onUnregisterObserver(callingPackage);
- } else {
- Slog.w(TAG, "onUnregisterObserver unavailable user_id: "
- + UserHandle.getCallingUserId());
+ synchronized (mLock) {
+ for (ClientRequest cr : mExistingClientRequests) {
+ if (cr.getPackageName().equals(callingPackage)) {
+ AmbientContextManagerPerUserService service =
+ getAmbientContextManagerPerUserServiceForEventTypes(
+ UserHandle.getCallingUserId(),
+ cr.getRequest().getEventTypes());
+ if (service != null) {
+ service.onUnregisterObserver(callingPackage);
+ } else {
+ Slog.w(TAG, "onUnregisterObserver unavailable user_id: "
+ + UserHandle.getCallingUserId());
+ }
}
}
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 21bd7bc..b001f3d 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -58,6 +58,7 @@
import com.android.server.utils.EventLogger;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
@@ -453,6 +454,48 @@
return device;
}
+ private static final int[] VALID_COMMUNICATION_DEVICE_TYPES = {
+ AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
+ AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
+ AudioDeviceInfo.TYPE_WIRED_HEADSET,
+ AudioDeviceInfo.TYPE_USB_HEADSET,
+ AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
+ AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
+ AudioDeviceInfo.TYPE_HEARING_AID,
+ AudioDeviceInfo.TYPE_BLE_HEADSET,
+ AudioDeviceInfo.TYPE_USB_DEVICE,
+ AudioDeviceInfo.TYPE_BLE_SPEAKER,
+ AudioDeviceInfo.TYPE_LINE_ANALOG,
+ AudioDeviceInfo.TYPE_HDMI,
+ AudioDeviceInfo.TYPE_AUX_LINE
+ };
+
+ /*package */ static boolean isValidCommunicationDevice(AudioDeviceInfo device) {
+ for (int type : VALID_COMMUNICATION_DEVICE_TYPES) {
+ if (device.getType() == type) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /* package */ static List<AudioDeviceInfo> getAvailableCommunicationDevices() {
+ ArrayList<AudioDeviceInfo> commDevices = new ArrayList<>();
+ AudioDeviceInfo[] allDevices =
+ AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS);
+ for (AudioDeviceInfo device : allDevices) {
+ if (isValidCommunicationDevice(device)) {
+ commDevices.add(device);
+ }
+ }
+ return commDevices;
+ }
+
+ private @Nullable AudioDeviceInfo getCommunicationDeviceOfType(int type) {
+ return getAvailableCommunicationDevices().stream().filter(d -> d.getType() == type)
+ .findFirst().orElse(null);
+ }
+
/**
* Returns the device currently requested for communication use case.
* @return AudioDeviceInfo the requested device for communication.
@@ -460,7 +503,29 @@
/* package */ AudioDeviceInfo getCommunicationDevice() {
synchronized (mDeviceStateLock) {
updateActiveCommunicationDevice();
- return mActiveCommunicationDevice;
+ AudioDeviceInfo device = mActiveCommunicationDevice;
+ // make sure we return a valid communication device (i.e. a device that is allowed by
+ // setCommunicationDevice()) for consistency.
+ if (device != null) {
+ // a digital dock is used instead of the speaker in speakerphone mode and should
+ // be reflected as such
+ if (device.getType() == AudioDeviceInfo.TYPE_DOCK) {
+ device = getCommunicationDeviceOfType(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
+ }
+ }
+ // Try to default to earpiece when current communication device is not valid. This can
+ // happen for instance if no call is active. If no earpiece device is available take the
+ // first valid communication device
+ if (device == null || !AudioDeviceBroker.isValidCommunicationDevice(device)) {
+ device = getCommunicationDeviceOfType(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE);
+ if (device == null) {
+ List<AudioDeviceInfo> commDevices = getAvailableCommunicationDevices();
+ if (!commDevices.isEmpty()) {
+ device = commDevices.get(0);
+ }
+ }
+ }
+ return device;
}
}
@@ -942,8 +1007,8 @@
@GuardedBy("mDeviceStateLock")
private void dispatchCommunicationDevice() {
- int portId = (mActiveCommunicationDevice == null) ? 0
- : mActiveCommunicationDevice.getId();
+ AudioDeviceInfo device = getCommunicationDevice();
+ int portId = device != null ? device.getId() : 0;
if (portId == mCurCommunicationPortId) {
return;
}
@@ -960,6 +1025,7 @@
mCommDevDispatchers.finishBroadcast();
}
+
//---------------------------------------------------------------------
// Communication with (to) AudioService
//TODO check whether the AudioService methods are candidates to move here
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 4eb6c7f..359a18a 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -6067,49 +6067,16 @@
restoreDeviceVolumeBehavior();
}
- private static final int[] VALID_COMMUNICATION_DEVICE_TYPES = {
- AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
- AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
- AudioDeviceInfo.TYPE_WIRED_HEADSET,
- AudioDeviceInfo.TYPE_USB_HEADSET,
- AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
- AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
- AudioDeviceInfo.TYPE_HEARING_AID,
- AudioDeviceInfo.TYPE_BLE_HEADSET,
- AudioDeviceInfo.TYPE_USB_DEVICE,
- AudioDeviceInfo.TYPE_BLE_SPEAKER,
- AudioDeviceInfo.TYPE_LINE_ANALOG,
- AudioDeviceInfo.TYPE_HDMI,
- AudioDeviceInfo.TYPE_AUX_LINE
- };
-
- private boolean isValidCommunicationDevice(AudioDeviceInfo device) {
- if (!device.isSink()) {
- return false;
- }
- for (int type : VALID_COMMUNICATION_DEVICE_TYPES) {
- if (device.getType() == type) {
- return true;
- }
- }
- return false;
- }
-
/** @see AudioManager#getAvailableCommunicationDevices(int) */
public int[] getAvailableCommunicationDeviceIds() {
- ArrayList<Integer> deviceIds = new ArrayList<>();
- AudioDeviceInfo[] devices = AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS);
- for (AudioDeviceInfo device : devices) {
- if (isValidCommunicationDevice(device)) {
- deviceIds.add(device.getId());
- }
- }
- return deviceIds.stream().mapToInt(Integer::intValue).toArray();
+ List<AudioDeviceInfo> commDevices = AudioDeviceBroker.getAvailableCommunicationDevices();
+ return commDevices.stream().mapToInt(AudioDeviceInfo::getId).toArray();
}
- /**
- * @see AudioManager#setCommunicationDevice(int)
- * @see AudioManager#clearCommunicationDevice()
- */
+
+ /**
+ * @see AudioManager#setCommunicationDevice(int)
+ * @see AudioManager#clearCommunicationDevice()
+ */
public boolean setCommunicationDevice(IBinder cb, int portId) {
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
@@ -6118,9 +6085,10 @@
if (portId != 0) {
device = AudioManager.getDeviceForPortId(portId, AudioManager.GET_DEVICES_OUTPUTS);
if (device == null) {
- throw new IllegalArgumentException("invalid portID " + portId);
+ Log.w(TAG, "setCommunicationDevice: invalid portID " + portId);
+ return false;
}
- if (!isValidCommunicationDevice(device)) {
+ if (!AudioDeviceBroker.isValidCommunicationDevice(device)) {
if (!device.isSink()) {
throw new IllegalArgumentException("device must have sink role");
} else {
@@ -6168,17 +6136,15 @@
/** @see AudioManager#getCommunicationDevice() */
public int getCommunicationDevice() {
- AudioDeviceInfo device = null;
+ int deviceId = 0;
final long ident = Binder.clearCallingIdentity();
try {
- device = mDeviceBroker.getCommunicationDevice();
+ AudioDeviceInfo device = mDeviceBroker.getCommunicationDevice();
+ deviceId = device != null ? device.getId() : 0;
} finally {
Binder.restoreCallingIdentity(ident);
}
- if (device == null) {
- return 0;
- }
- return device.getId();
+ return deviceId;
}
/** @see AudioManager#addOnCommunicationDeviceChangedListener(
@@ -8083,6 +8049,7 @@
volumeChangedOptions.setDeliveryGroupPolicy(DELIVERY_GROUP_POLICY_MOST_RECENT);
volumeChangedOptions.setDeliveryGroupMatchingKey(
AudioManager.VOLUME_CHANGED_ACTION, String.valueOf(mStreamType));
+ volumeChangedOptions.setDeferUntilActive(true);
mVolumeChangedOptions = volumeChangedOptions.toBundle();
mStreamDevicesChanged = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
@@ -8091,6 +8058,7 @@
streamDevicesChangedOptions.setDeliveryGroupPolicy(DELIVERY_GROUP_POLICY_MOST_RECENT);
streamDevicesChangedOptions.setDeliveryGroupMatchingKey(
AudioManager.STREAM_DEVICES_CHANGED_ACTION, String.valueOf(mStreamType));
+ streamDevicesChangedOptions.setDeferUntilActive(true);
mStreamDevicesChangedOptions = streamDevicesChangedOptions.toBundle();
}
diff --git a/services/core/java/com/android/server/display/DisplayBrightnessState.java b/services/core/java/com/android/server/display/DisplayBrightnessState.java
index 87cbbfe..e27182f 100644
--- a/services/core/java/com/android/server/display/DisplayBrightnessState.java
+++ b/services/core/java/com/android/server/display/DisplayBrightnessState.java
@@ -28,11 +28,13 @@
private final float mBrightness;
private final float mSdrBrightness;
private final BrightnessReason mBrightnessReason;
+ private final String mDisplayBrightnessStrategyName;
private DisplayBrightnessState(Builder builder) {
this.mBrightness = builder.getBrightness();
this.mSdrBrightness = builder.getSdrBrightness();
this.mBrightnessReason = builder.getBrightnessReason();
+ this.mDisplayBrightnessStrategyName = builder.getDisplayBrightnessStrategyName();
}
/**
@@ -56,6 +58,14 @@
return mBrightnessReason;
}
+ /**
+ * Gets the {@link com.android.server.display.brightness.strategy.DisplayBrightnessStrategy}
+ * name
+ */
+ public String getDisplayBrightnessStrategyName() {
+ return mDisplayBrightnessStrategyName;
+ }
+
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder("DisplayBrightnessState:");
@@ -93,6 +103,10 @@
if (!mBrightnessReason.equals(displayBrightnessState.getBrightnessReason())) {
return false;
}
+ if (!mDisplayBrightnessStrategyName.equals(
+ displayBrightnessState.getDisplayBrightnessStrategyName())) {
+ return false;
+ }
return true;
}
@@ -108,6 +122,7 @@
private float mBrightness;
private float mSdrBrightness;
private BrightnessReason mBrightnessReason = new BrightnessReason();
+ private String mDisplayBrightnessStrategyName;
/**
* Gets the brightness
@@ -164,6 +179,27 @@
}
/**
+ * Gets the {@link com.android.server.display.brightness.strategy.DisplayBrightnessStrategy}
+ * name
+ */
+ public String getDisplayBrightnessStrategyName() {
+ return mDisplayBrightnessStrategyName;
+ }
+
+ /**
+ * Sets the
+ * {@link com.android.server.display.brightness.strategy.DisplayBrightnessStrategy}'s name
+ *
+ * @param displayBrightnessStrategyName The name of the
+ * {@link com.android.server.display.brightness.strategy.DisplayBrightnessStrategy} being
+ * used.
+ */
+ public Builder setDisplayBrightnessStrategyName(String displayBrightnessStrategyName) {
+ this.mDisplayBrightnessStrategyName = displayBrightnessStrategyName;
+ return this;
+ }
+
+ /**
* This is used to construct an immutable DisplayBrightnessState object from its builder
*/
public DisplayBrightnessState build() {
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 535129c..e048a0f 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -17,12 +17,14 @@
package com.android.server.display;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation;
+import android.hardware.input.HostUsiVersion;
import android.os.Environment;
import android.os.PowerManager;
import android.text.TextUtils;
@@ -57,6 +59,7 @@
import com.android.server.display.config.ThermalStatus;
import com.android.server.display.config.ThermalThrottling;
import com.android.server.display.config.ThresholdPoint;
+import com.android.server.display.config.UsiVersion;
import com.android.server.display.config.XmlParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -390,6 +393,12 @@
* <item>80</item>
* <item>1500</item>
* </screenOffBrightnessSensorValueToLux>
+ * // The version of the Universal Stylus Initiative (USI) protocol supported by this display.
+ * // This should be omitted if the display does not support USI styluses.
+ * <usiVersion>
+ * <majorVersion>2</majorVersion>
+ * <minorVersion>0</minorVersion>
+ * </usiVersion>
* </displayConfiguration>
* }
* </pre>
@@ -626,6 +635,9 @@
// The concurrent displays mode might need a stricter throttling policy
private BrightnessThrottlingData mConcurrentDisplaysBrightnessThrottlingData;
+ @Nullable
+ private HostUsiVersion mHostUsiVersion;
+
@VisibleForTesting
DisplayDeviceConfig(Context context) {
mContext = context;
@@ -1370,6 +1382,15 @@
return mScreenOffBrightnessSensorValueToLux;
}
+ /**
+ * @return The USI version supported by this display, or null if USI is not supported.
+ * @see HostUsiVersion
+ */
+ @Nullable
+ public HostUsiVersion getHostUsiVersion() {
+ return mHostUsiVersion;
+ }
+
@Override
public String toString() {
return "DisplayDeviceConfig{"
@@ -1474,6 +1495,8 @@
+ "\n"
+ ", mScreenOffBrightnessSensorValueToLux=" + Arrays.toString(
mScreenOffBrightnessSensorValueToLux)
+ + "\n"
+ + ", mUsiVersion= " + mHostUsiVersion
+ "}";
}
@@ -1535,6 +1558,7 @@
loadAutoBrightnessConfigValues(config);
loadRefreshRateSetting(config);
loadScreenOffBrightnessSensorValueToLuxFromDdc(config);
+ loadUsiVersion(config);
} else {
Slog.w(TAG, "DisplayDeviceConfig file is null");
}
@@ -2689,6 +2713,15 @@
}
}
+ private void loadUsiVersion(DisplayConfiguration config) {
+ final UsiVersion usiVersion = config.getUsiVersion();
+ mHostUsiVersion = usiVersion != null
+ ? new HostUsiVersion(
+ usiVersion.getMajorVersion().intValue(),
+ usiVersion.getMinorVersion().intValue())
+ : null;
+ }
+
/**
* Uniquely identifies a Sensor, with the combination of Type and Name.
*/
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index f2110fe..3f49ebe 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -86,6 +86,7 @@
import android.hardware.display.VirtualDisplayConfig;
import android.hardware.display.WifiDisplayStatus;
import android.hardware.graphics.common.DisplayDecorationSupport;
+import android.hardware.input.HostUsiVersion;
import android.media.projection.IMediaProjection;
import android.media.projection.IMediaProjectionManager;
import android.net.Uri;
@@ -4151,6 +4152,19 @@
return SurfaceControl.getDisplayNativePrimaries(displayToken);
}
+
+ @Override
+ public HostUsiVersion getHostUsiVersion(int displayId) {
+ synchronized (mSyncRoot) {
+ final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
+ if (display == null) {
+ return null;
+ }
+
+ return display.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig()
+ .getHostUsiVersion();
+ }
+ }
}
class DesiredDisplayModeSpecsObserver
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index dbd2ab0..fc2a4e5 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -2885,6 +2885,9 @@
}
private void noteScreenState(int screenState) {
+ // Log screen state change with display id
+ FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_STATE_CHANGED_V2,
+ screenState, mDisplayStatsId);
if (mBatteryStats != null) {
try {
// TODO(multi-display): make this multi-display
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 103a1da..a744415 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -1548,6 +1548,8 @@
? mCdsi.getReduceBrightColorsStrength() : -1);
mTempBrightnessEvent.setPowerFactor(mPowerRequest.screenLowPowerBrightnessFactor);
mTempBrightnessEvent.setWasShortTermModelActive(hadUserBrightnessPoint);
+ mTempBrightnessEvent.setDisplayBrightnessStrategyName(displayBrightnessState
+ .getDisplayBrightnessStrategyName());
// Temporary is what we use during slider interactions. We avoid logging those so that
// we don't spam logcat when the slider is being used.
boolean tempToTempTransition =
@@ -2390,6 +2392,9 @@
}
private void noteScreenState(int screenState) {
+ // Log screen state change with display id
+ FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_STATE_CHANGED_V2,
+ screenState, mDisplayStatsId);
if (mBatteryStats != null) {
try {
// TODO(multi-display): make this multi-display
diff --git a/services/core/java/com/android/server/display/brightness/BrightnessEvent.java b/services/core/java/com/android/server/display/brightness/BrightnessEvent.java
index f19852b..8b09571 100644
--- a/services/core/java/com/android/server/display/brightness/BrightnessEvent.java
+++ b/services/core/java/com/android/server/display/brightness/BrightnessEvent.java
@@ -53,6 +53,7 @@
private int mFlags;
private int mAdjustmentFlags;
private boolean mAutomaticBrightnessEnabled;
+ private String mDisplayBrightnessStrategyName;
public BrightnessEvent(BrightnessEvent that) {
copyFrom(that);
@@ -92,6 +93,7 @@
mAdjustmentFlags = that.getAdjustmentFlags();
// Auto-brightness setting
mAutomaticBrightnessEnabled = that.isAutomaticBrightnessEnabled();
+ mDisplayBrightnessStrategyName = that.getDisplayBrightnessStrategyName();
}
/**
@@ -120,6 +122,7 @@
mAdjustmentFlags = 0;
// Auto-brightness setting
mAutomaticBrightnessEnabled = true;
+ mDisplayBrightnessStrategyName = "";
}
/**
@@ -157,7 +160,8 @@
&& mWasShortTermModelActive == that.mWasShortTermModelActive
&& mFlags == that.mFlags
&& mAdjustmentFlags == that.mAdjustmentFlags
- && mAutomaticBrightnessEnabled == that.mAutomaticBrightnessEnabled;
+ && mAutomaticBrightnessEnabled == that.mAutomaticBrightnessEnabled
+ && mDisplayBrightnessStrategyName.equals(that.mDisplayBrightnessStrategyName);
}
/**
@@ -185,7 +189,8 @@
+ ", wasShortTermModelActive=" + mWasShortTermModelActive
+ ", flags=" + flagsToString()
+ ", reason=" + mReason.toString(mAdjustmentFlags)
- + ", autoBrightness=" + mAutomaticBrightnessEnabled;
+ + ", autoBrightness=" + mAutomaticBrightnessEnabled
+ + ", strategy=" + mDisplayBrightnessStrategyName;
}
@Override
@@ -355,6 +360,14 @@
return mAutomaticBrightnessEnabled;
}
+ public void setDisplayBrightnessStrategyName(String displayBrightnessStrategyName) {
+ mDisplayBrightnessStrategyName = displayBrightnessStrategyName;
+ }
+
+ public String getDisplayBrightnessStrategyName() {
+ return mDisplayBrightnessStrategyName;
+ }
+
public void setAutomaticBrightnessEnabled(boolean mAutomaticBrightnessEnabled) {
this.mAutomaticBrightnessEnabled = mAutomaticBrightnessEnabled;
}
diff --git a/services/core/java/com/android/server/display/brightness/BrightnessUtils.java b/services/core/java/com/android/server/display/brightness/BrightnessUtils.java
index d5aeba1..169cc4a 100644
--- a/services/core/java/com/android/server/display/brightness/BrightnessUtils.java
+++ b/services/core/java/com/android/server/display/brightness/BrightnessUtils.java
@@ -45,13 +45,15 @@
* A utility to construct the DisplayBrightnessState
*/
public static DisplayBrightnessState constructDisplayBrightnessState(
- int brightnessChangeReason, float brightness, float sdrBrightness) {
+ int brightnessChangeReason, float brightness, float sdrBrightness,
+ String displayBrightnessStrategyName) {
BrightnessReason brightnessReason = new BrightnessReason();
brightnessReason.setReason(brightnessChangeReason);
return new DisplayBrightnessState.Builder()
.setBrightness(brightness)
.setSdrBrightness(sdrBrightness)
.setBrightnessReason(brightnessReason)
+ .setDisplayBrightnessStrategyName(displayBrightnessStrategyName)
.build();
}
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java
index 0cf234b..dd400d9 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java
@@ -40,7 +40,7 @@
DisplayBrightnessState displayBrightnessState =
BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_BOOST,
PowerManager.BRIGHTNESS_MAX,
- PowerManager.BRIGHTNESS_MAX);
+ PowerManager.BRIGHTNESS_MAX, getName());
return displayBrightnessState;
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
index 98075f9..8299586 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
@@ -33,7 +33,8 @@
// Todo(b/241308599): Introduce a validator class and add validations before setting
// the brightness
return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_DOZE,
- displayPowerRequest.dozeScreenBrightness, displayPowerRequest.dozeScreenBrightness);
+ displayPowerRequest.dozeScreenBrightness, displayPowerRequest.dozeScreenBrightness,
+ getName());
}
@Override
diff --git a/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java
index fe684a4..090ec13 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java
@@ -48,7 +48,7 @@
// Todo(b/241308599): Introduce a validator class and add validations before setting
// the brightness
return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_FOLLOWER,
- mBrightnessToFollow, mBrightnessToFollow);
+ mBrightnessToFollow, mBrightnessToFollow, getName());
}
@Override
diff --git a/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
index 612bbe9..bc24196 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
@@ -31,7 +31,8 @@
public DisplayBrightnessState updateBrightness(
DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_UNKNOWN,
- PowerManager.BRIGHTNESS_INVALID_FLOAT, PowerManager.BRIGHTNESS_INVALID_FLOAT);
+ PowerManager.BRIGHTNESS_INVALID_FLOAT, PowerManager.BRIGHTNESS_INVALID_FLOAT,
+ getName());
}
@Override
diff --git a/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java
index 6d3830a..13327cb 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java
@@ -33,7 +33,7 @@
// the brightness
return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_OVERRIDE,
displayPowerRequest.screenBrightnessOverride,
- displayPowerRequest.screenBrightnessOverride);
+ displayPowerRequest.screenBrightnessOverride, getName());
}
@Override
diff --git a/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
index ee5e066..3d411d3 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
@@ -34,7 +34,7 @@
// the brightness
return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_SCREEN_OFF,
PowerManager.BRIGHTNESS_OFF_FLOAT,
- PowerManager.BRIGHTNESS_OFF_FLOAT);
+ PowerManager.BRIGHTNESS_OFF_FLOAT, getName());
}
@Override
diff --git a/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java
index d97415d..35f7dd0 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java
@@ -48,7 +48,7 @@
DisplayBrightnessState displayBrightnessState =
BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_TEMPORARY,
mTemporaryScreenBrightness,
- mTemporaryScreenBrightness);
+ mTemporaryScreenBrightness, getName());
return displayBrightnessState;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 376e6f8..b460745 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -727,7 +727,7 @@
void sendCommand(final HdmiCecMessage cecMessage,
final HdmiControlService.SendMessageCallback callback) {
assertRunOnServiceThread();
- addCecMessageToHistory(false /* isReceived */, cecMessage);
+ List<String> sendResults = new ArrayList<>();
runOnIoThread(new Runnable() {
@Override
public void run() {
@@ -738,6 +738,12 @@
do {
errorCode = mNativeWrapperImpl.nativeSendCecCommand(
cecMessage.getSource(), cecMessage.getDestination(), body);
+ switch (errorCode) {
+ case SendMessageResult.SUCCESS: sendResults.add("ACK"); break;
+ case SendMessageResult.FAIL: sendResults.add("FAIL"); break;
+ case SendMessageResult.NACK: sendResults.add("NACK"); break;
+ case SendMessageResult.BUSY: sendResults.add("BUSY"); break;
+ }
if (errorCode == SendMessageResult.SUCCESS) {
break;
}
@@ -763,6 +769,8 @@
});
}
});
+
+ addCecMessageToHistory(false /* isReceived */, cecMessage, sendResults);
}
/**
@@ -785,7 +793,7 @@
}
HdmiLogger.debug("[R]:" + command);
- addCecMessageToHistory(true /* isReceived */, command);
+ addCecMessageToHistory(true /* isReceived */, command, null);
mHdmiCecAtomWriter.messageReported(command,
incomingMessageDirection(srcAddress, dstAddress), getCallingUid());
@@ -836,9 +844,10 @@
}
@ServiceThreadOnly
- private void addCecMessageToHistory(boolean isReceived, HdmiCecMessage message) {
+ private void addCecMessageToHistory(boolean isReceived, HdmiCecMessage message,
+ List<String> sendResults) {
assertRunOnServiceThread();
- addEventToHistory(new MessageHistoryRecord(isReceived, message));
+ addEventToHistory(new MessageHistoryRecord(isReceived, message, sendResults));
}
private void addEventToHistory(Dumpable event) {
@@ -1720,11 +1729,13 @@
private static final class MessageHistoryRecord extends Dumpable {
private final boolean mIsReceived; // true if received message and false if sent message
private final HdmiCecMessage mMessage;
+ private final List<String> mSendResults;
- MessageHistoryRecord(boolean isReceived, HdmiCecMessage message) {
+ MessageHistoryRecord(boolean isReceived, HdmiCecMessage message, List<String> sendResults) {
super();
mIsReceived = isReceived;
mMessage = message;
+ mSendResults = sendResults;
}
@Override
@@ -1733,7 +1744,16 @@
pw.print(" time=");
pw.print(sdf.format(new Date(mTime)));
pw.print(" message=");
- pw.println(mMessage);
+ pw.print(mMessage);
+
+ StringBuilder results = new StringBuilder();
+ if (!mIsReceived && mSendResults != null) {
+ results.append(" (");
+ results.append(String.join(", ", mSendResults));
+ results.append(")");
+ }
+
+ pw.println(results);
}
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index be4373a..8c13297 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -38,7 +38,9 @@
import android.hardware.SensorPrivacyManager.Sensors;
import android.hardware.SensorPrivacyManagerInternal;
import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayViewport;
+import android.hardware.input.HostUsiVersion;
import android.hardware.input.IInputDeviceBatteryListener;
import android.hardware.input.IInputDeviceBatteryState;
import android.hardware.input.IInputDevicesChangedListener;
@@ -168,6 +170,7 @@
private final Context mContext;
private final InputManagerHandler mHandler;
+ private DisplayManagerInternal mDisplayManagerInternal;
// Context cache used for loading pointer resources.
private Context mPointerIconDisplayContext;
@@ -519,6 +522,8 @@
Slog.d(TAG, "System ready.");
}
+ mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
+
synchronized (mLidSwitchLock) {
mSystemReady = true;
@@ -1450,7 +1455,8 @@
}
private void updateMaximumObscuringOpacityForTouchFromSettings() {
- final float opacity = InputManager.getInstance().getMaximumObscuringOpacityForTouch();
+ InputManager im = Objects.requireNonNull(mContext.getSystemService(InputManager.class));
+ final float opacity = im.getMaximumObscuringOpacityForTouch();
if (opacity < 0 || opacity > 1) {
Log.e(TAG, "Invalid maximum obscuring opacity " + opacity
+ ", it should be >= 0 and <= 1, rejecting update.");
@@ -2254,6 +2260,11 @@
}
@Override
+ public HostUsiVersion getHostUsiVersionFromDisplayConfig(int displayId) {
+ return mDisplayManagerInternal.getHostUsiVersion(displayId);
+ }
+
+ @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 052c785..287cc29 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -16,6 +16,7 @@
package com.android.server.pm.permission;
+import static android.Manifest.permission.CAMERA;
import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
import static android.Manifest.permission.CAPTURE_AUDIO_OUTPUT;
import static android.Manifest.permission.RECORD_AUDIO;
@@ -1379,14 +1380,15 @@
boolean permissionGranted = context.checkPermission(permission, /*pid*/ -1,
uid) == PackageManager.PERMISSION_GRANTED;
- // Override certain permissions checks for the HotwordDetectionService. This service is
- // an isolated service, which ordinarily cannot hold permissions.
+ // Override certain permissions checks for the shared isolated process for both
+ // HotwordDetectionService and VisualQueryDetectionService, which ordinarily cannot hold
+ // any permissions.
// There's probably a cleaner, more generalizable way to do this. For now, this is
// the only use case for this, so simply override here.
if (!permissionGranted
&& Process.isIsolated(uid) // simple check which fails-fast for the common case
&& (permission.equals(RECORD_AUDIO) || permission.equals(CAPTURE_AUDIO_HOTWORD)
- || permission.equals(CAPTURE_AUDIO_OUTPUT))) {
+ || permission.equals(CAPTURE_AUDIO_OUTPUT) || permission.equals(CAMERA))) {
HotwordDetectionServiceProvider hotwordServiceProvider =
permissionManagerServiceInt.getHotwordDetectionServiceProvider();
permissionGranted = hotwordServiceProvider != null
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
index 383249f..401eac6 100644
--- a/services/core/java/com/android/server/policy/AppOpsPolicy.java
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -447,7 +447,8 @@
// package, so we don't need to modify it.
if (Process.isIsolated(uid) // simple check which fails-fast for the common case
&& (code == AppOpsManager.OP_RECORD_AUDIO
- || code == AppOpsManager.OP_RECORD_AUDIO_HOTWORD)) {
+ || code == AppOpsManager.OP_RECORD_AUDIO_HOTWORD
+ || code == AppOpsManager.OP_CAMERA)) {
final HotwordDetectionServiceIdentity hotwordDetectionServiceIdentity =
mVoiceInteractionManagerInternal.getHotwordDetectionServiceIdentity();
if (hotwordDetectionServiceIdentity != null
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index d4895ed..316b12a 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -762,7 +762,8 @@
synchronized (mGlobalLock) {
final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
return r != null
- ? r.getRequestedOrientation() : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+ ? r.getOverrideOrientation()
+ : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index fd3f32d..6ba3866 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1172,8 +1172,10 @@
pw.println(prefix + "mVoiceInteraction=true");
}
pw.print(prefix); pw.print("mOccludesParent="); pw.println(mOccludesParent);
- pw.print(prefix); pw.print("mOrientation=");
- pw.println(ActivityInfo.screenOrientationToString(mOrientation));
+ pw.print(prefix); pw.print("overrideOrientation=");
+ pw.println(ActivityInfo.screenOrientationToString(getOverrideOrientation()));
+ pw.print(prefix); pw.print("requestedOrientation=");
+ pw.println(ActivityInfo.screenOrientationToString(super.getOverrideOrientation()));
pw.println(prefix + "mVisibleRequested=" + mVisibleRequested
+ " mVisible=" + mVisible + " mClientVisible=" + isClientVisible()
+ ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
@@ -1960,6 +1962,15 @@
new ComponentName(info.packageName, info.targetActivity);
}
+ // Don't move below setActivityType since it triggers onConfigurationChange ->
+ // resolveOverrideConfiguration that requires having mLetterboxUiController initialised.
+ // Don't move below setOrientation(info.screenOrientation) since it triggers
+ // getOverrideOrientation that requires having mLetterboxUiController
+ // initialised.
+ mLetterboxUiController = new LetterboxUiController(mWmService, this);
+ mCameraCompatControlEnabled = mWmService.mContext.getResources()
+ .getBoolean(R.bool.config_isCameraCompatControlForStretchedIssuesEnabled);
+
mTargetSdk = info.applicationInfo.targetSdkVersion;
mShowForAllUsers = (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
setOrientation(info.screenOrientation);
@@ -2080,12 +2091,6 @@
launchMode = aInfo.launchMode;
- // Don't move below setActivityType since it triggers onConfigurationChange ->
- // resolveOverrideConfiguration that requires having mLetterboxUiController initialised.
- mLetterboxUiController = new LetterboxUiController(mWmService, this);
- mCameraCompatControlEnabled = mWmService.mContext.getResources()
- .getBoolean(R.bool.config_isCameraCompatControlForStretchedIssuesEnabled);
-
setActivityType(_componentSpecified, _launchedFromUid, _intent, options, sourceRecord);
immersive = (aInfo.flags & FLAG_IMMERSIVE) != 0;
@@ -2499,7 +2504,8 @@
if (topAttached != null) {
if (topAttached.isSnapshotCompatible(snapshot)
// This trampoline must be the same rotation.
- && mDisplayContent.getDisplayRotation().rotationForOrientation(mOrientation,
+ && mDisplayContent.getDisplayRotation().rotationForOrientation(
+ getOverrideOrientation(),
mDisplayContent.getRotation()) == snapshot.getRotation()) {
return STARTING_WINDOW_TYPE_SNAPSHOT;
}
@@ -7759,13 +7765,13 @@
return mLetterboxUiController.getInheritedOrientation();
}
}
- if (mOrientation == SCREEN_ORIENTATION_BEHIND && task != null) {
+ if (task != null && getOverrideOrientation() == SCREEN_ORIENTATION_BEHIND) {
// We use Task here because we want to be consistent with what happens in
// multi-window mode where other tasks orientations are ignored.
final ActivityRecord belowCandidate = task.getActivity(
- a -> a.mOrientation != SCREEN_ORIENTATION_UNSET && !a.finishing
- && a.mOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND, this,
- false /* includeBoundary */, true /* traverseTopToBottom */);
+ a -> a.canDefineOrientationForActivitiesAbove() /* callback */,
+ this /* boundary */, false /* includeBoundary */,
+ true /* traverseTopToBottom */);
if (belowCandidate != null) {
return belowCandidate.getRequestedConfigurationOrientation(forDisplay);
}
@@ -7773,6 +7779,19 @@
return super.getRequestedConfigurationOrientation(forDisplay);
}
+ /**
+ * Whether this activity can be used as an orientation source for activities above with
+ * {@link SCREEN_ORIENTATION_BEHIND}.
+ */
+ boolean canDefineOrientationForActivitiesAbove() {
+ if (finishing) {
+ return false;
+ }
+ final int overrideOrientation = getOverrideOrientation();
+ return overrideOrientation != SCREEN_ORIENTATION_UNSET
+ && overrideOrientation != SCREEN_ORIENTATION_BEHIND;
+ }
+
@Override
void onCancelFixedRotationTransform(int originalDisplayRotation) {
if (this != mDisplayContent.getLastOrientationSource()) {
@@ -7799,7 +7818,7 @@
}
}
- void setRequestedOrientation(int requestedOrientation) {
+ void setRequestedOrientation(@ActivityInfo.ScreenOrientation int requestedOrientation) {
if (mLetterboxUiController.shouldIgnoreRequestedOrientation(requestedOrientation)) {
return;
}
@@ -7842,7 +7861,7 @@
@VisibleForTesting
boolean shouldIgnoreOrientationRequests() {
if (!mAppActivityEmbeddingSplitsEnabled
- || !ActivityInfo.isFixedOrientationPortrait(mOrientation)
+ || !ActivityInfo.isFixedOrientationPortrait(getOverrideOrientation())
|| task.inMultiWindowMode()) {
return false;
}
@@ -7865,7 +7884,7 @@
// Allow app to specify orientation regardless of its visibility state if the current
// candidate want us to use orientation behind. I.e. the visible app on-top of this one
// wants us to use the orientation of the app behind it.
- return mOrientation;
+ return getOverrideOrientation();
}
// The {@link ActivityRecord} should only specify an orientation when it is not closing.
@@ -7873,15 +7892,31 @@
// task being started in the wrong orientation during the transition.
if (!getDisplayContent().mClosingApps.contains(this)
&& (isVisibleRequested() || getDisplayContent().mOpeningApps.contains(this))) {
- return mOrientation;
+ return getOverrideOrientation();
}
return SCREEN_ORIENTATION_UNSET;
}
- /** Returns the app's preferred orientation regardless of its currently visibility state. */
+ /**
+ * Returns the app's preferred orientation regardless of its current visibility state taking
+ * into account orientation per-app overrides applied by the device manufacturers.
+ */
+ @Override
+ protected int getOverrideOrientation() {
+ return mLetterboxUiController.overrideOrientationIfNeeded(super.getOverrideOrientation());
+ }
+
+ /**
+ * Returns the app's preferred orientation regardless of its currently visibility state. This
+ * is used to return a requested value to an app if they call {@link
+ * android.app.Activity#getRequestedOrientation} since {@link #getOverrideOrientation} value
+ * with override can confuse an app if it's different from what they requested with {@link
+ * android.app.Activity#setRequestedOrientation}.
+ */
+ @ActivityInfo.ScreenOrientation
int getRequestedOrientation() {
- return mOrientation;
+ return super.getOverrideOrientation();
}
/**
@@ -8444,8 +8479,8 @@
// If orientation is respected when insets are applied, then stableBounds will be empty.
boolean orientationRespectedWithInsets =
orientationRespectedWithInsets(parentBounds, stableBounds);
- if (orientationRespectedWithInsets
- && handlesOrientationChangeFromDescendant(mOrientation)) {
+ if (orientationRespectedWithInsets && handlesOrientationChangeFromDescendant(
+ getOverrideOrientation())) {
// No need to letterbox because of fixed orientation. Display will handle
// fixed-orientation requests and a display rotation is enough to respect requested
// orientation with insets applied.
@@ -9083,7 +9118,8 @@
}
if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY)
- && !ActivityInfo.isFixedOrientationPortrait(getRequestedOrientation())) {
+ && !ActivityInfo.isFixedOrientationPortrait(
+ getOverrideOrientation())) {
return info.getMinAspectRatio();
}
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 7aa734b..cd79f2e 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -86,7 +86,8 @@
/** Apps that fulfill a certain role that can can always launch new tasks */
static final int BAL_ALLOW_ALLOWLISTED_COMPONENT = 3;
- /** Apps which currently have a visible window */
+ /** Apps which currently have a visible window or are bound by a service with a visible
+ * window */
static final int BAL_ALLOW_VISIBLE_WINDOW = 4;
/** Allowed due to the PendingIntent sender */
diff --git a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
index bdb06a97..63dc7d2 100644
--- a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
+++ b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
@@ -26,6 +26,7 @@
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_BAL_PERMISSION;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_FOREGROUND;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_GRACE_PERIOD;
+import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_VISIBLE_WINDOW;
import static com.android.server.wm.BackgroundActivityStartController.BAL_BLOCK;
import static java.util.Objects.requireNonNull;
@@ -152,7 +153,7 @@
Slog.d(TAG, "[Process(" + pid
+ ")] Activity start allowed: process bound by foreground uid");
}
- return BAL_ALLOW_FOREGROUND;
+ return BAL_ALLOW_VISIBLE_WINDOW;
}
// Allow if the flag was explicitly set.
if (isBackgroundStartAllowedByToken(uid, packageName, isCheckingForFgsStart)) {
diff --git a/services/core/java/com/android/server/wm/DeviceStateController.java b/services/core/java/com/android/server/wm/DeviceStateController.java
index a6f8557..2e67399 100644
--- a/services/core/java/com/android/server/wm/DeviceStateController.java
+++ b/services/core/java/com/android/server/wm/DeviceStateController.java
@@ -16,80 +16,92 @@
package com.android.server.wm;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.devicestate.DeviceStateManager;
import android.os.Handler;
import android.os.HandlerExecutor;
+import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
+import java.util.ArrayList;
+import java.util.List;
import java.util.function.Consumer;
/**
- * Class that registers callbacks with the {@link DeviceStateManager} and
- * responds to fold state changes by forwarding such events to a delegate.
+ * Class that registers callbacks with the {@link DeviceStateManager} and responds to device
+ * changes.
*/
-final class DeviceStateController {
+final class DeviceStateController implements DeviceStateManager.DeviceStateCallback {
+
+ @NonNull
private final DeviceStateManager mDeviceStateManager;
- private final Context mContext;
+ @NonNull
+ private final int[] mOpenDeviceStates;
+ @NonNull
+ private final int[] mHalfFoldedDeviceStates;
+ @NonNull
+ private final int[] mFoldedDeviceStates;
+ @NonNull
+ private final int[] mRearDisplayDeviceStates;
+ @NonNull
+ private final List<Consumer<DeviceState>> mDeviceStateCallbacks = new ArrayList<>();
- private FoldStateListener mDeviceStateListener;
+ @Nullable
+ private DeviceState mLastDeviceState;
- public enum FoldState {
- UNKNOWN, OPEN, FOLDED, HALF_FOLDED
+ public enum DeviceState {
+ UNKNOWN, OPEN, FOLDED, HALF_FOLDED, REAR,
}
- DeviceStateController(Context context, Handler handler, Consumer<FoldState> delegate) {
- mContext = context;
- mDeviceStateManager = mContext.getSystemService(DeviceStateManager.class);
+ DeviceStateController(@NonNull Context context, @NonNull Handler handler) {
+ mDeviceStateManager = context.getSystemService(DeviceStateManager.class);
+ mOpenDeviceStates = context.getResources()
+ .getIntArray(R.array.config_openDeviceStates);
+ mHalfFoldedDeviceStates = context.getResources()
+ .getIntArray(R.array.config_halfFoldedDeviceStates);
+ mFoldedDeviceStates = context.getResources()
+ .getIntArray(R.array.config_foldedDeviceStates);
+ mRearDisplayDeviceStates = context.getResources()
+ .getIntArray(R.array.config_rearDisplayDeviceStates);
+
if (mDeviceStateManager != null) {
- mDeviceStateListener = new FoldStateListener(mContext, delegate);
- mDeviceStateManager
- .registerCallback(new HandlerExecutor(handler),
- mDeviceStateListener);
+ mDeviceStateManager.registerCallback(new HandlerExecutor(handler), this);
}
}
void unregisterFromDeviceStateManager() {
- if (mDeviceStateListener != null) {
- mDeviceStateManager.unregisterCallback(mDeviceStateListener);
+ if (mDeviceStateManager != null) {
+ mDeviceStateManager.unregisterCallback(this);
}
}
- /**
- * A listener for half-fold device state events that dispatches state changes to a delegate.
- */
- static final class FoldStateListener implements DeviceStateManager.DeviceStateCallback {
+ void registerDeviceStateCallback(@NonNull Consumer<DeviceState> callback) {
+ mDeviceStateCallbacks.add(callback);
+ }
- private final int[] mHalfFoldedDeviceStates;
- private final int[] mFoldedDeviceStates;
-
- @Nullable
- private FoldState mLastResult;
- private final Consumer<FoldState> mDelegate;
-
- FoldStateListener(Context context, Consumer<FoldState> delegate) {
- mFoldedDeviceStates = context.getResources().getIntArray(
- com.android.internal.R.array.config_foldedDeviceStates);
- mHalfFoldedDeviceStates = context.getResources().getIntArray(
- com.android.internal.R.array.config_halfFoldedDeviceStates);
- mDelegate = delegate;
+ @Override
+ public void onStateChanged(int state) {
+ final DeviceState deviceState;
+ if (ArrayUtils.contains(mHalfFoldedDeviceStates, state)) {
+ deviceState = DeviceState.HALF_FOLDED;
+ } else if (ArrayUtils.contains(mFoldedDeviceStates, state)) {
+ deviceState = DeviceState.FOLDED;
+ } else if (ArrayUtils.contains(mRearDisplayDeviceStates, state)) {
+ deviceState = DeviceState.REAR;
+ } else if (ArrayUtils.contains(mOpenDeviceStates, state)) {
+ deviceState = DeviceState.OPEN;
+ } else {
+ deviceState = DeviceState.UNKNOWN;
}
- @Override
- public void onStateChanged(int state) {
- final boolean halfFolded = ArrayUtils.contains(mHalfFoldedDeviceStates, state);
- FoldState result;
- if (halfFolded) {
- result = FoldState.HALF_FOLDED;
- } else {
- final boolean folded = ArrayUtils.contains(mFoldedDeviceStates, state);
- result = folded ? FoldState.FOLDED : FoldState.OPEN;
- }
- if (mLastResult == null || !mLastResult.equals(result)) {
- mLastResult = result;
- mDelegate.accept(result);
+ if (mLastDeviceState == null || !mLastDeviceState.equals(deviceState)) {
+ mLastDeviceState = deviceState;
+
+ for (Consumer<DeviceState> callback : mDeviceStateCallbacks) {
+ callback.accept(mLastDeviceState);
}
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index a15453e..de63191 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -94,7 +94,7 @@
DisplayArea(WindowManagerService wms, Type type, String name, int featureId) {
super(wms);
// TODO(display-area): move this up to ConfigurationContainer
- mOrientation = SCREEN_ORIENTATION_UNSET;
+ setOverrideOrientation(SCREEN_ORIENTATION_UNSET);
mType = type;
mName = name;
mFeatureId = featureId;
@@ -166,7 +166,8 @@
// If this is set to ignore the orientation request, we don't propagate descendant
// orientation request.
final int orientation = requestingContainer != null
- ? requestingContainer.mOrientation : SCREEN_ORIENTATION_UNSET;
+ ? requestingContainer.getOverrideOrientation()
+ : SCREEN_ORIENTATION_UNSET;
return !getIgnoreOrientationRequest(orientation)
&& super.onDescendantOrientationChanged(requestingContainer);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 1794e2a..9581ffe 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1145,14 +1145,17 @@
mWmService.mAtmService.getRecentTasks().getInputListener());
}
+ mDeviceStateController = new DeviceStateController(mWmService.mContext, mWmService.mH);
+
mDisplayPolicy = new DisplayPolicy(mWmService, this);
mDisplayRotation = new DisplayRotation(mWmService, this, mDisplayInfo.address);
- mDeviceStateController = new DeviceStateController(mWmService.mContext, mWmService.mH,
- newFoldState -> {
+ final Consumer<DeviceStateController.DeviceState> deviceStateConsumer =
+ (@NonNull DeviceStateController.DeviceState newFoldState) -> {
mDisplaySwitchTransitionLauncher.foldStateChanged(newFoldState);
mDisplayRotation.foldStateChanged(newFoldState);
- });
+ };
+ mDeviceStateController.registerDeviceStateCallback(deviceStateConsumer);
mCloseToSquareMaxAspectRatio = mWmService.mContext.getResources().getFloat(
R.dimen.config_closeToSquareDisplayMaxAspectRatio);
@@ -1618,7 +1621,8 @@
// If display rotation class tells us that it doesn't consider app requested orientation,
// this display won't rotate just because of an app changes its requested orientation. Thus
// it indicates that this display chooses not to handle this request.
- final int orientation = requestingContainer != null ? requestingContainer.mOrientation
+ final int orientation = requestingContainer != null
+ ? requestingContainer.getOverrideOrientation()
: SCREEN_ORIENTATION_UNSET;
final boolean handled = handlesOrientationChangeFromDescendant(orientation);
if (config == null) {
@@ -1744,14 +1748,17 @@
if (mTransitionController.useShellTransitionsRotation()) {
return ROTATION_UNDEFINED;
}
+ final int activityOrientation = r.getOverrideOrientation();
if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM
- || getIgnoreOrientationRequest(r.mOrientation)) {
+ || getIgnoreOrientationRequest(activityOrientation)) {
return ROTATION_UNDEFINED;
}
- if (r.mOrientation == ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
+ if (activityOrientation == ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
+ // TODO(b/266280737): Use ActivityRecord#canDefineOrientationForActivitiesAbove
final ActivityRecord nextCandidate = getActivity(
- a -> a.mOrientation != SCREEN_ORIENTATION_UNSET
- && a.mOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND,
+ a -> a.getOverrideOrientation() != SCREEN_ORIENTATION_UNSET
+ && a.getOverrideOrientation()
+ != ActivityInfo.SCREEN_ORIENTATION_BEHIND,
r, false /* includeBoundary */, true /* traverseTopToBottom */);
if (nextCandidate != null) {
r = nextCandidate;
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index e6d8b3d..762f49a 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -1573,7 +1573,7 @@
proto.end(token);
}
- boolean isDeviceInPosture(DeviceStateController.FoldState state, boolean isTabletop) {
+ boolean isDeviceInPosture(DeviceStateController.DeviceState state, boolean isTabletop) {
if (mFoldController == null) return false;
return mFoldController.isDeviceInPosture(state, isTabletop);
}
@@ -1585,10 +1585,10 @@
/**
* Called by the DeviceStateManager callback when the device state changes.
*/
- void foldStateChanged(DeviceStateController.FoldState foldState) {
+ void foldStateChanged(DeviceStateController.DeviceState deviceState) {
if (mFoldController != null) {
synchronized (mLock) {
- mFoldController.foldStateChanged(foldState);
+ mFoldController.foldStateChanged(deviceState);
}
}
}
@@ -1596,8 +1596,8 @@
private class FoldController {
@Surface.Rotation
private int mHalfFoldSavedRotation = -1; // No saved rotation
- private DeviceStateController.FoldState mFoldState =
- DeviceStateController.FoldState.UNKNOWN;
+ private DeviceStateController.DeviceState mDeviceState =
+ DeviceStateController.DeviceState.UNKNOWN;
private boolean mInHalfFoldTransition = false;
private final boolean mIsDisplayAlwaysSeparatingHinge;
private final Set<Integer> mTabletopRotations;
@@ -1637,32 +1637,33 @@
R.bool.config_isDisplayHingeAlwaysSeparating);
}
- boolean isDeviceInPosture(DeviceStateController.FoldState state, boolean isTabletop) {
- if (state != mFoldState) {
+ boolean isDeviceInPosture(DeviceStateController.DeviceState state, boolean isTabletop) {
+ if (state != mDeviceState) {
return false;
}
- if (mFoldState == DeviceStateController.FoldState.HALF_FOLDED) {
+ if (mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED) {
return !(isTabletop ^ mTabletopRotations.contains(mRotation));
}
return true;
}
- DeviceStateController.FoldState getFoldState() {
- return mFoldState;
+ DeviceStateController.DeviceState getFoldState() {
+ return mDeviceState;
}
boolean isSeparatingHinge() {
- return mFoldState == DeviceStateController.FoldState.HALF_FOLDED
- || (mFoldState == DeviceStateController.FoldState.OPEN
+ return mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED
+ || (mDeviceState == DeviceStateController.DeviceState.OPEN
&& mIsDisplayAlwaysSeparatingHinge);
}
boolean overrideFrozenRotation() {
- return mFoldState == DeviceStateController.FoldState.HALF_FOLDED;
+ return mDeviceState == DeviceStateController.DeviceState.HALF_FOLDED;
}
boolean shouldRevertOverriddenRotation() {
- return mFoldState == DeviceStateController.FoldState.OPEN // When transitioning to open.
+ // When transitioning to open.
+ return mDeviceState == DeviceStateController.DeviceState.OPEN
&& mInHalfFoldTransition
&& mHalfFoldSavedRotation != -1 // Ignore if we've already reverted.
&& mUserRotationMode
@@ -1676,30 +1677,30 @@
return savedRotation;
}
- void foldStateChanged(DeviceStateController.FoldState newState) {
+ void foldStateChanged(DeviceStateController.DeviceState newState) {
ProtoLog.v(WM_DEBUG_ORIENTATION,
"foldStateChanged: displayId %d, halfFoldStateChanged %s, "
+ "saved rotation: %d, mUserRotation: %d, mLastSensorRotation: %d, "
+ "mLastOrientation: %d, mRotation: %d",
mDisplayContent.getDisplayId(), newState.name(), mHalfFoldSavedRotation,
mUserRotation, mLastSensorRotation, mLastOrientation, mRotation);
- if (mFoldState == DeviceStateController.FoldState.UNKNOWN) {
- mFoldState = newState;
+ if (mDeviceState == DeviceStateController.DeviceState.UNKNOWN) {
+ mDeviceState = newState;
return;
}
- if (newState == DeviceStateController.FoldState.HALF_FOLDED
- && mFoldState != DeviceStateController.FoldState.HALF_FOLDED) {
+ if (newState == DeviceStateController.DeviceState.HALF_FOLDED
+ && mDeviceState != DeviceStateController.DeviceState.HALF_FOLDED) {
// The device has transitioned to HALF_FOLDED state: save the current rotation and
// update the device rotation.
mHalfFoldSavedRotation = mRotation;
- mFoldState = newState;
+ mDeviceState = newState;
// Now mFoldState is set to HALF_FOLDED, the overrideFrozenRotation function will
// return true, so rotation is unlocked.
mService.updateRotation(false /* alwaysSendConfiguration */,
false /* forceRelayout */);
} else {
mInHalfFoldTransition = true;
- mFoldState = newState;
+ mDeviceState = newState;
// Tell the device to update its orientation.
mService.updateRotation(false /* alwaysSendConfiguration */,
false /* forceRelayout */);
@@ -1822,7 +1823,7 @@
final long mTimestamp = System.currentTimeMillis();
final int mHalfFoldSavedRotation;
final boolean mInHalfFoldTransition;
- final DeviceStateController.FoldState mFoldState;
+ final DeviceStateController.DeviceState mDeviceState;
@Nullable final String mDisplayRotationCompatPolicySummary;
Record(DisplayRotation dr, int fromRotation, int toRotation) {
@@ -1843,8 +1844,9 @@
if (source != null) {
mLastOrientationSource = source.toString();
final WindowState w = source.asWindowState();
- mSourceOrientation =
- w != null ? w.mAttrs.screenOrientation : source.mOrientation;
+ mSourceOrientation = w != null
+ ? w.mAttrs.screenOrientation
+ : source.getOverrideOrientation();
} else {
mLastOrientationSource = null;
mSourceOrientation = SCREEN_ORIENTATION_UNSET;
@@ -1852,11 +1854,11 @@
if (dr.mFoldController != null) {
mHalfFoldSavedRotation = dr.mFoldController.mHalfFoldSavedRotation;
mInHalfFoldTransition = dr.mFoldController.mInHalfFoldTransition;
- mFoldState = dr.mFoldController.mFoldState;
+ mDeviceState = dr.mFoldController.mDeviceState;
} else {
mHalfFoldSavedRotation = NO_FOLD_CONTROLLER;
mInHalfFoldTransition = false;
- mFoldState = DeviceStateController.FoldState.UNKNOWN;
+ mDeviceState = DeviceStateController.DeviceState.UNKNOWN;
}
mDisplayRotationCompatPolicySummary = dc.mDisplayRotationCompatPolicy == null
? null
@@ -1882,7 +1884,7 @@
pw.println(prefix + " halfFoldSavedRotation="
+ mHalfFoldSavedRotation
+ " mInHalfFoldTransition=" + mInHalfFoldTransition
- + " mFoldState=" + mFoldState);
+ + " mFoldState=" + mDeviceState);
}
if (mDisplayRotationCompatPolicySummary != null) {
pw.println(prefix + mDisplayRotationCompatPolicySummary);
diff --git a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
index c6037da..3ffb2fa 100644
--- a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
@@ -296,8 +296,8 @@
&& activity.getRequestedConfigurationOrientation() != ORIENTATION_UNDEFINED
// "locked" and "nosensor" values are often used by camera apps that can't
// handle dynamic changes so we shouldn't force rotate them.
- && activity.getRequestedOrientation() != SCREEN_ORIENTATION_NOSENSOR
- && activity.getRequestedOrientation() != SCREEN_ORIENTATION_LOCKED
+ && activity.getOverrideOrientation() != SCREEN_ORIENTATION_NOSENSOR
+ && activity.getOverrideOrientation() != SCREEN_ORIENTATION_LOCKED
&& mCameraIdPackageBiMap.containsPackageName(activity.packageName)
&& activity.mLetterboxUiController.shouldForceRotateForCameraCompat();
}
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index 73d1ff9d..d73be18 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -17,11 +17,20 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.content.pm.ActivityInfo.OVERRIDE_ANY_ORIENTATION;
import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION;
import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH;
import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
+import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
+import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR;
+import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.pm.ActivityInfo.isFixedOrientation;
+import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
import static android.content.pm.ActivityInfo.screenOrientationToString;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
@@ -29,6 +38,7 @@
import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION;
import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH;
import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
+import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE;
import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION;
import static com.android.internal.util.FrameworkStatsLog.APP_COMPAT_STATE_CHANGED__LETTERBOX_POSITION__BOTTOM;
@@ -111,6 +121,20 @@
*/
private final float mExpandedTaskBarHeight;
+ // TODO(b/265576778): Cache other overrides as well.
+
+ // Corresponds to OVERRIDE_ANY_ORIENTATION
+ private final boolean mIsOverrideAnyOrientationEnabled;
+ // Corresponds to OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT
+ private final boolean mIsOverrideToPortraitOrientationEnabled;
+ // Corresponds to OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR
+ private final boolean mIsOverrideToNosensorOrientationEnabled;
+ // Corresponds to OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE
+ private final boolean mIsOverrideToReverseLandscapeOrientationEnabled;
+
+ @Nullable
+ private final Boolean mBooleanPropertyAllowOrientationOverride;
+
/*
* WindowContainerListener responsible to make translucent activities inherit
* constraints from the first opaque activity beneath them. It's null for not
@@ -193,6 +217,19 @@
mExpandedTaskBarHeight =
getResources().getDimensionPixelSize(R.dimen.taskbar_frame_height);
+
+ mBooleanPropertyAllowOrientationOverride =
+ readComponentProperty(packageManager, mActivityRecord.packageName,
+ /* gatingCondition */ null,
+ PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE);
+
+ mIsOverrideAnyOrientationEnabled = isCompatChangeEnabled(OVERRIDE_ANY_ORIENTATION);
+ mIsOverrideToPortraitOrientationEnabled =
+ isCompatChangeEnabled(OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT);
+ mIsOverrideToReverseLandscapeOrientationEnabled =
+ isCompatChangeEnabled(OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE);
+ mIsOverrideToNosensorOrientationEnabled =
+ isCompatChangeEnabled(OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR);
}
/**
@@ -207,8 +244,8 @@
*/
@Nullable
private static Boolean readComponentProperty(PackageManager packageManager, String packageName,
- BooleanSupplier gatingCondition, String propertyName) {
- if (!gatingCondition.getAsBoolean()) {
+ @Nullable BooleanSupplier gatingCondition, String propertyName) {
+ if (gatingCondition != null && !gatingCondition.getAsBoolean()) {
return null;
}
try {
@@ -307,6 +344,41 @@
mIsRefreshAfterRotationRequested = isRequested;
}
+ @ScreenOrientation
+ int overrideOrientationIfNeeded(@ScreenOrientation int candidate) {
+ if (Boolean.FALSE.equals(mBooleanPropertyAllowOrientationOverride)) {
+ return candidate;
+ }
+
+ if (mIsOverrideToReverseLandscapeOrientationEnabled
+ && (isFixedOrientationLandscape(candidate) || mIsOverrideAnyOrientationEnabled)) {
+ Slog.w(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
+ + mActivityRecord + " is overridden to "
+ + screenOrientationToString(SCREEN_ORIENTATION_REVERSE_LANDSCAPE));
+ return SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+ }
+
+ if (!mIsOverrideAnyOrientationEnabled && isFixedOrientation(candidate)) {
+ return candidate;
+ }
+
+ if (mIsOverrideToPortraitOrientationEnabled) {
+ Slog.w(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
+ + mActivityRecord + " is overridden to "
+ + screenOrientationToString(SCREEN_ORIENTATION_PORTRAIT));
+ return SCREEN_ORIENTATION_PORTRAIT;
+ }
+
+ if (mIsOverrideToNosensorOrientationEnabled) {
+ Slog.w(TAG, "Requested orientation " + screenOrientationToString(candidate) + " for "
+ + mActivityRecord + " is overridden to "
+ + screenOrientationToString(SCREEN_ORIENTATION_NOSENSOR));
+ return SCREEN_ORIENTATION_NOSENSOR;
+ }
+
+ return candidate;
+ }
+
/**
* Whether activity is eligible for activity "refresh" after camera compat force rotation
* treatment. See {@link DisplayRotationCompatPolicy} for context.
@@ -367,6 +439,10 @@
mBooleanPropertyCameraCompatAllowForceRotation);
}
+ private boolean isCompatChangeEnabled(long overrideChangeId) {
+ return mActivityRecord.info.isChangeEnabled(overrideChangeId);
+ }
+
/**
* Returns {@code true} when the following conditions are met:
* <ul>
@@ -383,8 +459,7 @@
if (!gatingCondition.getAsBoolean()) {
return false;
}
- return !Boolean.FALSE.equals(property)
- && !mActivityRecord.info.isChangeEnabled(overrideChangeId);
+ return !Boolean.FALSE.equals(property) && !isCompatChangeEnabled(overrideChangeId);
}
/**
@@ -393,7 +468,7 @@
* <li>{@code gatingCondition} isn't {@code false}
* <li>App developers didn't opt out with a component {@code property}
* <li>App developers opted in with a component {@code property} or an OEM opted in with a
- * component {@code property}
+ * {@code overrideChangeId} override
* </ul>
*
* <p>This is used for the treatments that are enabled only on per-app basis.
@@ -406,8 +481,7 @@
if (Boolean.FALSE.equals(property)) {
return false;
}
- return Boolean.TRUE.equals(property)
- || mActivityRecord.info.isChangeEnabled(overrideChangeId);
+ return Boolean.TRUE.equals(property) || isCompatChangeEnabled(overrideChangeId);
}
boolean hasWallpaperBackgroundForLetterbox() {
@@ -542,7 +616,7 @@
// Note that we check the task rather than the parent as with ActivityEmbedding the parent might
// be a TaskFragment, and its windowing mode is always MULTI_WINDOW, even if the task is
// actually fullscreen.
- private boolean isDisplayFullScreenAndInPosture(DeviceStateController.FoldState state,
+ private boolean isDisplayFullScreenAndInPosture(DeviceStateController.DeviceState state,
boolean isTabletop) {
Task task = mActivityRecord.getTask();
return mActivityRecord.mDisplayContent != null
@@ -568,7 +642,7 @@
// Don't check resolved configuration because it may not be updated yet during
// configuration change.
boolean bookMode = isDisplayFullScreenAndInPosture(
- DeviceStateController.FoldState.HALF_FOLDED, false /* isTabletop */);
+ DeviceStateController.DeviceState.HALF_FOLDED, false /* isTabletop */);
return isHorizontalReachabilityEnabled(parentConfiguration)
// Using the last global dynamic position to avoid "jumps" when moving
// between apps or activities.
@@ -580,7 +654,7 @@
// Don't check resolved configuration because it may not be updated yet during
// configuration change.
boolean tabletopMode = isDisplayFullScreenAndInPosture(
- DeviceStateController.FoldState.HALF_FOLDED, true /* isTabletop */);
+ DeviceStateController.DeviceState.HALF_FOLDED, true /* isTabletop */);
return isVerticalReachabilityEnabled(parentConfiguration)
// Using the last global dynamic position to avoid "jumps" when moving
// between apps or activities.
@@ -1107,7 +1181,7 @@
int letterboxPositionForHorizontalReachability = getLetterboxConfiguration()
.getLetterboxPositionForHorizontalReachability(
isDisplayFullScreenAndInPosture(
- DeviceStateController.FoldState.HALF_FOLDED,
+ DeviceStateController.DeviceState.HALF_FOLDED,
false /* isTabletop */));
positionToLog = letterboxHorizontalReachabilityPositionToLetterboxPosition(
letterboxPositionForHorizontalReachability);
@@ -1115,7 +1189,7 @@
int letterboxPositionForVerticalReachability = getLetterboxConfiguration()
.getLetterboxPositionForVerticalReachability(
isDisplayFullScreenAndInPosture(
- DeviceStateController.FoldState.HALF_FOLDED,
+ DeviceStateController.DeviceState.HALF_FOLDED,
true /* isTabletop */));
positionToLog = letterboxVerticalReachabilityPositionToLetterboxPosition(
letterboxPositionForVerticalReachability);
@@ -1224,7 +1298,8 @@
// To avoid wrong behaviour, we're not forcing orientation for activities with not
// fixed orientation (e.g. permission dialogs).
return hasInheritedLetterboxBehavior()
- && mActivityRecord.mOrientation != SCREEN_ORIENTATION_UNSPECIFIED;
+ && mActivityRecord.getOverrideOrientation()
+ != SCREEN_ORIENTATION_UNSPECIFIED;
}
float getInheritedMinAspectRatio() {
diff --git a/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java b/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java
index 30bdc34..2edb082 100644
--- a/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java
+++ b/services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java
@@ -51,10 +51,10 @@
/**
* Called by the DeviceStateManager callback when the state changes.
*/
- void foldStateChanged(DeviceStateController.FoldState newFoldState) {
+ void foldStateChanged(DeviceStateController.DeviceState newDeviceState) {
// Ignore transitions to/from half-folded.
- if (newFoldState == DeviceStateController.FoldState.HALF_FOLDED) return;
- mIsFolded = newFoldState == DeviceStateController.FoldState.FOLDED;
+ if (newDeviceState == DeviceStateController.DeviceState.HALF_FOLDED) return;
+ mIsFolded = newDeviceState == DeviceStateController.DeviceState.FOLDED;
}
/**
diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java
index 8a6ddf6..98ca9ae 100644
--- a/services/core/java/com/android/server/wm/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java
@@ -143,7 +143,11 @@
.setLaunchTaskDisplayArea(options.getLaunchTaskDisplayArea())
.setLaunchDisplayId(options.getLaunchDisplayId())
.setCallerDisplayId(options.getCallerDisplayId())
- .setLaunchRootTask(options.getLaunchRootTask());
+ .setLaunchRootTask(options.getLaunchRootTask())
+ .setPendingIntentBackgroundActivityStartMode(
+ options.getPendingIntentBackgroundActivityStartMode())
+ .setIgnorePendingIntentCreatorForegroundState(
+ options.getIgnorePendingIntentCreatorForegroundState());
}
/**
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 1b59d8d..adc82ec 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -5020,70 +5020,76 @@
ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Adding activity %s to task %s "
+ "callers: %s", r, task, new RuntimeException("here").fillInStackTrace());
- // The transition animation and starting window are not needed if {@code allowMoveToFront}
- // is false, because the activity won't be visible.
- if ((!isActivityTypeHomeOrRecents() || hasActivity()) && allowMoveToFront) {
- final DisplayContent dc = mDisplayContent;
- if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
- "Prepare open transition: starting " + r);
- if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
- dc.prepareAppTransition(TRANSIT_NONE);
- mTaskSupervisor.mNoAnimActivities.add(r);
- mTransitionController.setNoAnimation(r);
- } else {
- dc.prepareAppTransition(TRANSIT_OPEN);
- mTaskSupervisor.mNoAnimActivities.remove(r);
- }
- if (newTask && !r.mLaunchTaskBehind) {
- // If a new task is being launched, then mark the existing top activity as
- // supporting picture-in-picture while pausing only if the starting activity
- // would not be considered an overlay on top of the current activity
- // (eg. not fullscreen, or the assistant)
- enableEnterPipOnTaskSwitch(pipCandidate,
- null /* toFrontTask */, r, options);
- }
- boolean doShow = true;
- if (newTask) {
- // Even though this activity is starting fresh, we still need
- // to reset it to make sure we apply affinities to move any
- // existing activities from other tasks in to it.
- // If the caller has requested that the target task be
- // reset, then do so.
- if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
- resetTaskIfNeeded(r, r);
- doShow = topRunningNonDelayedActivityLocked(null) == r;
- }
- } else if (options != null && options.getAnimationType()
- == ActivityOptions.ANIM_SCENE_TRANSITION) {
- doShow = false;
- }
- if (options != null && options.getDisableStartingWindow()) {
- doShow = false;
- }
- if (r.mLaunchTaskBehind) {
- // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
- // tell WindowManager that r is visible even though it is at the back of the root
- // task.
- r.setVisibility(true);
- ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
- // Go ahead to execute app transition for this activity since the app transition
- // will not be triggered through the resume channel.
- mDisplayContent.executeAppTransition();
- } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
- // Figure out if we are transitioning from another activity that is
- // "has the same starting icon" as the next one. This allows the
- // window manager to keep the previous window it had previously
- // created, if it still had one.
- Task baseTask = r.getTask();
- final ActivityRecord prev = baseTask.getActivity(
- a -> a.mStartingData != null && a.showToCurrentUser());
- mWmService.mStartingSurfaceController.showStartingWindow(r, prev, newTask,
- isTaskSwitch, sourceRecord);
- }
- } else {
+ if (isActivityTypeHomeOrRecents() && getActivityBelow(r) == null) {
// If this is the first activity, don't do any fancy animations,
// because there is nothing for it to animate on top of.
ActivityOptions.abort(options);
+ return;
+ }
+
+ if (!allowMoveToFront) {
+ // The transition animation and starting window are not needed if
+ // {@code allowMoveToFront} is false, because the activity won't be visible.
+ ActivityOptions.abort(options);
+ return;
+ }
+
+ final DisplayContent dc = mDisplayContent;
+ if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
+ "Prepare open transition: starting " + r);
+ if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
+ dc.prepareAppTransition(TRANSIT_NONE);
+ mTaskSupervisor.mNoAnimActivities.add(r);
+ mTransitionController.setNoAnimation(r);
+ } else {
+ dc.prepareAppTransition(TRANSIT_OPEN);
+ mTaskSupervisor.mNoAnimActivities.remove(r);
+ }
+ if (newTask && !r.mLaunchTaskBehind) {
+ // If a new task is being launched, then mark the existing top activity as
+ // supporting picture-in-picture while pausing only if the starting activity
+ // would not be considered an overlay on top of the current activity
+ // (eg. not fullscreen, or the assistant)
+ enableEnterPipOnTaskSwitch(pipCandidate,
+ null /* toFrontTask */, r, options);
+ }
+ boolean doShow = true;
+ if (newTask) {
+ // Even though this activity is starting fresh, we still need
+ // to reset it to make sure we apply affinities to move any
+ // existing activities from other tasks in to it.
+ // If the caller has requested that the target task be
+ // reset, then do so.
+ if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
+ resetTaskIfNeeded(r, r);
+ doShow = topRunningNonDelayedActivityLocked(null) == r;
+ }
+ } else if (options != null && options.getAnimationType()
+ == ActivityOptions.ANIM_SCENE_TRANSITION) {
+ doShow = false;
+ }
+ if (options != null && options.getDisableStartingWindow()) {
+ doShow = false;
+ }
+ if (r.mLaunchTaskBehind) {
+ // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
+ // tell WindowManager that r is visible even though it is at the back of the root
+ // task.
+ r.setVisibility(true);
+ ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ // Go ahead to execute app transition for this activity since the app transition
+ // will not be triggered through the resume channel.
+ mDisplayContent.executeAppTransition();
+ } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
+ // Figure out if we are transitioning from another activity that is
+ // "has the same starting icon" as the next one. This allows the
+ // window manager to keep the previous window it had previously
+ // created, if it still had one.
+ Task baseTask = r.getTask();
+ final ActivityRecord prev = baseTask.getActivity(
+ a -> a.mStartingData != null && a.showToCurrentUser());
+ mWmService.mStartingSurfaceController.showStartingWindow(r, prev, newTask,
+ isTaskSwitch, sourceRecord);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 63bb5c3..b06bdb1 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -73,6 +73,7 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ActivityInfo;
+import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.Point;
@@ -178,8 +179,9 @@
protected final WindowList<E> mChildren = new WindowList<E>();
// The specified orientation for this window container.
- @ActivityInfo.ScreenOrientation
- protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+ // Shouldn't be accessed directly since subclasses can override getOverrideOrientation.
+ @ScreenOrientation
+ private int mOverrideOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
/**
* The window container which decides its orientation since the last time
@@ -1456,19 +1458,20 @@
/**
* Gets the configuration orientation by the requested screen orientation
- * ({@link ActivityInfo.ScreenOrientation}) of this activity.
+ * ({@link ScreenOrientation}) of this activity.
*
* @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
* {@link Configuration#ORIENTATION_PORTRAIT},
* {@link Configuration#ORIENTATION_UNDEFINED}).
*/
+ @ScreenOrientation
int getRequestedConfigurationOrientation() {
return getRequestedConfigurationOrientation(false /* forDisplay */);
}
/**
* Gets the configuration orientation by the requested screen orientation
- * ({@link ActivityInfo.ScreenOrientation}) of this activity.
+ * ({@link ScreenOrientation}) of this activity.
*
* @param forDisplay whether it is the requested config orientation for display.
* If {@code true}, we may reverse the requested orientation if the root is
@@ -1479,8 +1482,9 @@
* {@link Configuration#ORIENTATION_PORTRAIT},
* {@link Configuration#ORIENTATION_UNDEFINED}).
*/
+ @ScreenOrientation
int getRequestedConfigurationOrientation(boolean forDisplay) {
- int requestedOrientation = mOrientation;
+ int requestedOrientation = getOverrideOrientation();
final RootDisplayArea root = getRootDisplayArea();
if (forDisplay && root != null && root.isOrientationDifferentFromDisplay()) {
// Reverse the requested orientation if the orientation of its root is different from
@@ -1490,7 +1494,7 @@
// (portrait).
// When an app below the DAG is requesting landscape, it should actually request the
// display to be portrait, so that the DAG and the app will be in landscape.
- requestedOrientation = reverseOrientation(mOrientation);
+ requestedOrientation = reverseOrientation(getOverrideOrientation());
}
if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
@@ -1515,7 +1519,7 @@
*
* @param orientation the specified orientation.
*/
- void setOrientation(int orientation) {
+ void setOrientation(@ScreenOrientation int orientation) {
setOrientation(orientation, null /* requestingContainer */);
}
@@ -1523,17 +1527,17 @@
* Sets the specified orientation of this container. It percolates this change upward along the
* hierarchy to let each level of the hierarchy a chance to respond to it.
*
- * @param orientation the specified orientation. Needs to be one of {@link
- * android.content.pm.ActivityInfo.ScreenOrientation}.
+ * @param orientation the specified orientation. Needs to be one of {@link ScreenOrientation}.
* @param requestingContainer the container which orientation request has changed. Mostly used
* to ensure it gets correct configuration.
*/
- void setOrientation(int orientation, @Nullable WindowContainer requestingContainer) {
- if (mOrientation == orientation) {
+ void setOrientation(@ScreenOrientation int orientation,
+ @Nullable WindowContainer requestingContainer) {
+ if (getOverrideOrientation() == orientation) {
return;
}
- mOrientation = orientation;
+ setOverrideOrientation(orientation);
final WindowContainer parent = getParent();
if (parent != null) {
if (getConfiguration().orientation != getRequestedConfigurationOrientation()
@@ -1552,9 +1556,9 @@
}
}
- @ActivityInfo.ScreenOrientation
+ @ScreenOrientation
int getOrientation() {
- return getOrientation(mOrientation);
+ return getOrientation(getOverrideOrientation());
}
/**
@@ -1568,7 +1572,8 @@
* better match.
* @return The orientation as specified by this branch or the window hierarchy.
*/
- int getOrientation(int candidate) {
+ @ScreenOrientation
+ int getOrientation(@ScreenOrientation int candidate) {
mLastOrientationSource = null;
if (!providesOrientation()) {
return SCREEN_ORIENTATION_UNSET;
@@ -1578,16 +1583,16 @@
// specified; otherwise we prefer to use the orientation of its topmost child that has one
// specified and fall back on this container's unset or unspecified value as a candidate
// if none of the children have a better candidate for the orientation.
- if (mOrientation != SCREEN_ORIENTATION_UNSET
- && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
+ if (getOverrideOrientation() != SCREEN_ORIENTATION_UNSET
+ && getOverrideOrientation() != SCREEN_ORIENTATION_UNSPECIFIED) {
mLastOrientationSource = this;
- return mOrientation;
+ return getOverrideOrientation();
}
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowContainer wc = mChildren.get(i);
- // TODO: Maybe mOrientation should default to SCREEN_ORIENTATION_UNSET vs.
+ // TODO: Maybe mOverrideOrientation should default to SCREEN_ORIENTATION_UNSET vs.
// SCREEN_ORIENTATION_UNSPECIFIED?
final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
@@ -1619,6 +1624,20 @@
}
/**
+ * Returns orientation specified on this level of hierarchy without taking children into
+ * account, like {@link #getOrientation} does, allowing subclasses to override. See {@link
+ * ActivityRecord#getOverrideOrientation} for an example.
+ */
+ @ScreenOrientation
+ protected int getOverrideOrientation() {
+ return mOverrideOrientation;
+ }
+
+ protected void setOverrideOrientation(@ScreenOrientation int orientation) {
+ mOverrideOrientation = orientation;
+ }
+
+ /**
* @return The deepest source which decides the orientation of this window container since the
* last time {@link #getOrientation(int) was called.
*/
@@ -2674,7 +2693,7 @@
final long token = proto.start(fieldId);
super.dumpDebug(proto, CONFIGURATION_CONTAINER, logLevel);
- proto.write(ORIENTATION, mOrientation);
+ proto.write(ORIENTATION, mOverrideOrientation);
proto.write(VISIBLE, isVisible);
writeIdentifierToProto(proto, IDENTIFIER);
if (mSurfaceAnimator.isAnimating()) {
diff --git a/services/core/jni/tvinput/JTvInputHal.cpp b/services/core/jni/tvinput/JTvInputHal.cpp
index 3453cbd..98e6b19 100644
--- a/services/core/jni/tvinput/JTvInputHal.cpp
+++ b/services/core/jni/tvinput/JTvInputHal.cpp
@@ -338,6 +338,12 @@
return ::ndk::ScopedAStatus::ok();
}
+::ndk::ScopedAStatus JTvInputHal::TvInputCallback::notifyTvMessageEvent(
+ const AidlTvMessageEvent& event) {
+ // TODO: Implement this
+ return ::ndk::ScopedAStatus::ok();
+}
+
JTvInputHal::ITvInputWrapper::ITvInputWrapper(std::shared_ptr<AidlITvInput>& aidlTvInput)
: mIsHidl(false), mAidlTvInput(aidlTvInput) {}
diff --git a/services/core/jni/tvinput/JTvInputHal.h b/services/core/jni/tvinput/JTvInputHal.h
index 2697294..984407a 100644
--- a/services/core/jni/tvinput/JTvInputHal.h
+++ b/services/core/jni/tvinput/JTvInputHal.h
@@ -52,6 +52,7 @@
using AidlNativeHandle = ::aidl::android::hardware::common::NativeHandle;
using AidlTvInputDeviceInfo = ::aidl::android::hardware::tv::input::TvInputDeviceInfo;
using AidlTvInputEvent = ::aidl::android::hardware::tv::input::TvInputEvent;
+using AidlTvMessageEvent = ::aidl::android::hardware::tv::input::TvMessageEvent;
using AidlTvStreamConfig = ::aidl::android::hardware::tv::input::TvStreamConfig;
extern gTvInputHalClassInfoType gTvInputHalClassInfo;
@@ -131,6 +132,7 @@
public:
explicit TvInputCallback(JTvInputHal* hal);
::ndk::ScopedAStatus notify(const AidlTvInputEvent& event) override;
+ ::ndk::ScopedAStatus notifyTvMessageEvent(const AidlTvMessageEvent& event) override;
Return<void> notify(const HidlTvInputEvent& event) override;
private:
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index a27eb7f..97dbe04 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -117,6 +117,11 @@
<xs:element type="integer-array" name="screenOffBrightnessSensorValueToLux">
<xs:annotation name="final"/>
</xs:element>
+ <!-- The version of the Universal Stylus Initiative
+ (USI, https://universalstylus.org/) protocol supported by the display, if any. -->
+ <xs:element type="usiVersion" name="usiVersion">
+ <xs:annotation name="final"/>
+ </xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
@@ -502,4 +507,15 @@
<xs:element name="item" type="xs:nonNegativeInteger" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
+
+ <xs:complexType name="usiVersion">
+ <xs:element name="majorVersion" type="xs:nonNegativeInteger"
+ minOccurs="1" maxOccurs="1">
+ <xs:annotation name="final"/>
+ </xs:element>
+ <xs:element name="minorVersion" type="xs:nonNegativeInteger"
+ minOccurs="1" maxOccurs="1">
+ <xs:annotation name="final"/>
+ </xs:element>
+ </xs:complexType>
</xs:schema>
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 6c66d0d..aba8a2c 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -101,6 +101,7 @@
method public final com.android.server.display.config.SensorDetails getScreenOffBrightnessSensor();
method public final com.android.server.display.config.IntegerArray getScreenOffBrightnessSensorValueToLux();
method @NonNull public final com.android.server.display.config.ThermalThrottling getThermalThrottling();
+ method public final com.android.server.display.config.UsiVersion getUsiVersion();
method public final void setAmbientBrightnessChangeThresholds(@NonNull com.android.server.display.config.Thresholds);
method public final void setAmbientBrightnessChangeThresholdsIdle(com.android.server.display.config.Thresholds);
method public final void setAmbientLightHorizonLong(java.math.BigInteger);
@@ -125,6 +126,7 @@
method public final void setScreenOffBrightnessSensor(com.android.server.display.config.SensorDetails);
method public final void setScreenOffBrightnessSensorValueToLux(com.android.server.display.config.IntegerArray);
method public final void setThermalThrottling(@NonNull com.android.server.display.config.ThermalThrottling);
+ method public final void setUsiVersion(com.android.server.display.config.UsiVersion);
}
public class DisplayQuirks {
@@ -263,6 +265,14 @@
method public final void setDarkeningThresholds(@NonNull com.android.server.display.config.BrightnessThresholds);
}
+ public class UsiVersion {
+ ctor public UsiVersion();
+ method public final java.math.BigInteger getMajorVersion();
+ method public final java.math.BigInteger getMinorVersion();
+ method public final void setMajorVersion(java.math.BigInteger);
+ method public final void setMinorVersion(java.math.BigInteger);
+ }
+
public class XmlParser {
ctor public XmlParser();
method public static com.android.server.display.config.DisplayConfiguration read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
diff --git a/services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java b/services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java
new file mode 100644
index 0000000..f3feb02
--- /dev/null
+++ b/services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.face;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.Looper;
+import android.os.RemoteException;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(MockitoJUnitRunner.class)
+public class FaceManagerTest {
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ Context mContext;
+ @Mock
+ IFaceService mService;
+
+ @Captor
+ ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mCaptor;
+
+ List<FaceSensorPropertiesInternal> mProps;
+ FaceManager mFaceManager;
+
+ @Before
+ public void setUp() throws Exception {
+ when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
+ mFaceManager = new FaceManager(mContext, mService);
+ mProps = new ArrayList<>();
+ mProps.add(new FaceSensorPropertiesInternal(
+ 0 /* id */,
+ FaceSensorProperties.STRENGTH_STRONG,
+ 1 /* maxTemplatesAllowed */,
+ new ArrayList<>() /* conponentInfo */,
+ FaceSensorProperties.TYPE_UNKNOWN,
+ true /* supportsFaceDetection */,
+ true /* supportsSelfIllumination */,
+ false /* resetLockoutRequiresChallenge */));
+ }
+
+ @Test
+ public void getSensorPropertiesInternal_noBinderCalls() throws RemoteException {
+ verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
+
+ mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
+ List<FaceSensorPropertiesInternal> actual = mFaceManager.getSensorPropertiesInternal();
+
+ assertThat(actual).isEqualTo(mProps);
+ verify(mService, never()).getSensorPropertiesInternal(any());
+ }
+}
diff --git a/services/tests/mockingservicestests/src/android/hardware/face/OWNERS b/services/tests/mockingservicestests/src/android/hardware/face/OWNERS
new file mode 100644
index 0000000..6a2192a
--- /dev/null
+++ b/services/tests/mockingservicestests/src/android/hardware/face/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/biometrics/OWNERS
diff --git a/services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java b/services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java
new file mode 100644
index 0000000..558202d
--- /dev/null
+++ b/services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.fingerprint;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.Looper;
+import android.os.RemoteException;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+@RunWith(MockitoJUnitRunner.class)
+public class FingerprintManagerTest {
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ Context mContext;
+ @Mock
+ IFingerprintService mService;
+
+ @Captor
+ ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mCaptor;
+
+ List<FingerprintSensorPropertiesInternal> mProps;
+ FingerprintManager mFingerprintManager;
+
+ @Before
+ public void setUp() throws Exception {
+ when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
+ mFingerprintManager = new FingerprintManager(mContext, mService);
+ mProps = new ArrayList<>();
+ mProps.add(new FingerprintSensorPropertiesInternal(
+ 0 /* sensorId */,
+ FingerprintSensorProperties.STRENGTH_STRONG,
+ 1 /* maxEnrollmentsPerUser */,
+ new ArrayList<>() /* componentInfo */,
+ FingerprintSensorProperties.TYPE_UNKNOWN,
+ true /* halControlsIllumination */,
+ true /* resetLockoutRequiresHardwareAuthToken */,
+ new ArrayList<>() /* sensorLocations */));
+ }
+
+ @Test
+ public void getSensorPropertiesInternal_noBinderCalls() throws RemoteException {
+ verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
+
+ mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
+ List<FingerprintSensorPropertiesInternal> actual =
+ mFingerprintManager.getSensorPropertiesInternal();
+
+ assertThat(actual).isEqualTo(mProps);
+ verify(mService, never()).getSensorPropertiesInternal(any());
+ }
+}
diff --git a/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS b/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS
new file mode 100644
index 0000000..3edcf70
--- /dev/null
+++ b/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/biometrics/OWNERS
\ No newline at end of file
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
index a8b8f91..7281fafc 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -30,6 +30,7 @@
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -370,11 +371,12 @@
}
/**
- * Confirm that {@link JobSchedulerService#getRescheduleJobForFailureLocked(JobStatus, int)}
+ * Confirm that
+ * {@link JobSchedulerService#getRescheduleJobForFailureLocked(JobStatus, int, int)}
* returns a job with the correct delay and deadline constraints.
*/
@Test
- public void testGetRescheduleJobForFailure() {
+ public void testGetRescheduleJobForFailure_timingCalculations() {
final long nowElapsed = sElapsedRealtimeClock.millis();
final long initialBackoffMs = MINUTE_IN_MILLIS;
mService.mConstants.SYSTEM_STOP_TO_FAILURE_RATIO = 3;
@@ -387,15 +389,18 @@
// failure = 0, systemStop = 1
JobStatus rescheduledJob = mService.getRescheduleJobForFailureLocked(originalJob,
+ JobParameters.STOP_REASON_DEVICE_STATE,
JobParameters.INTERNAL_STOP_REASON_DEVICE_THERMAL);
assertEquals(nowElapsed + initialBackoffMs, rescheduledJob.getEarliestRunTime());
assertEquals(JobStatus.NO_LATEST_RUNTIME, rescheduledJob.getLatestRunTimeElapsed());
// failure = 0, systemStop = 2
rescheduledJob = mService.getRescheduleJobForFailureLocked(rescheduledJob,
+ JobParameters.STOP_REASON_DEVICE_STATE,
JobParameters.INTERNAL_STOP_REASON_PREEMPT);
// failure = 0, systemStop = 3
rescheduledJob = mService.getRescheduleJobForFailureLocked(rescheduledJob,
+ JobParameters.STOP_REASON_CONSTRAINT_CHARGING,
JobParameters.INTERNAL_STOP_REASON_CONSTRAINTS_NOT_SATISFIED);
assertEquals(nowElapsed + initialBackoffMs, rescheduledJob.getEarliestRunTime());
assertEquals(JobStatus.NO_LATEST_RUNTIME, rescheduledJob.getLatestRunTimeElapsed());
@@ -403,6 +408,7 @@
// failure = 0, systemStop = 2 * SYSTEM_STOP_TO_FAILURE_RATIO
for (int i = 0; i < mService.mConstants.SYSTEM_STOP_TO_FAILURE_RATIO; ++i) {
rescheduledJob = mService.getRescheduleJobForFailureLocked(rescheduledJob,
+ JobParameters.STOP_REASON_SYSTEM_PROCESSING,
JobParameters.INTERNAL_STOP_REASON_RTC_UPDATED);
}
assertEquals(nowElapsed + 2 * initialBackoffMs, rescheduledJob.getEarliestRunTime());
@@ -410,18 +416,52 @@
// failure = 1, systemStop = 2 * SYSTEM_STOP_TO_FAILURE_RATIO
rescheduledJob = mService.getRescheduleJobForFailureLocked(rescheduledJob,
+ JobParameters.STOP_REASON_TIMEOUT,
JobParameters.INTERNAL_STOP_REASON_TIMEOUT);
assertEquals(nowElapsed + 3 * initialBackoffMs, rescheduledJob.getEarliestRunTime());
assertEquals(JobStatus.NO_LATEST_RUNTIME, rescheduledJob.getLatestRunTimeElapsed());
// failure = 2, systemStop = 2 * SYSTEM_STOP_TO_FAILURE_RATIO
rescheduledJob = mService.getRescheduleJobForFailureLocked(rescheduledJob,
+ JobParameters.STOP_REASON_UNDEFINED,
JobParameters.INTERNAL_STOP_REASON_SUCCESSFUL_FINISH);
assertEquals(nowElapsed + 4 * initialBackoffMs, rescheduledJob.getEarliestRunTime());
assertEquals(JobStatus.NO_LATEST_RUNTIME, rescheduledJob.getLatestRunTimeElapsed());
}
/**
+ * Confirm that
+ * {@link JobSchedulerService#getRescheduleJobForFailureLocked(JobStatus, int, int)}
+ * returns a job that is correctly marked as demoted by the user.
+ */
+ @Test
+ public void testGetRescheduleJobForFailure_userDemotion() {
+ JobStatus originalJob = createJobStatus("testGetRescheduleJobForFailure", createJobInfo());
+ assertEquals(0, originalJob.getInternalFlags() & JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER);
+
+ // Reschedule for a non-user reason
+ JobStatus rescheduledJob = mService.getRescheduleJobForFailureLocked(originalJob,
+ JobParameters.STOP_REASON_DEVICE_STATE,
+ JobParameters.INTERNAL_STOP_REASON_DEVICE_THERMAL);
+ assertEquals(0,
+ rescheduledJob.getInternalFlags() & JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER);
+
+ // Reschedule for a user reason
+ rescheduledJob = mService.getRescheduleJobForFailureLocked(rescheduledJob,
+ JobParameters.STOP_REASON_USER,
+ JobParameters.INTERNAL_STOP_REASON_USER_UI_STOP);
+ assertNotEquals(0,
+ rescheduledJob.getInternalFlags() & JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER);
+
+ // Reschedule a previously demoted job for a non-user reason
+ rescheduledJob = mService.getRescheduleJobForFailureLocked(rescheduledJob,
+ JobParameters.STOP_REASON_CONSTRAINT_CHARGING,
+ JobParameters.INTERNAL_STOP_REASON_CONSTRAINTS_NOT_SATISFIED);
+ assertNotEquals(0,
+ rescheduledJob.getInternalFlags() & JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER);
+ }
+
+ /**
* Confirm that {@link JobSchedulerService#getRescheduleJobForPeriodic(JobStatus)} returns a job
* with the correct delay and deadline constraints if the periodic job is scheduled with the
* minimum possible period.
@@ -731,6 +771,7 @@
JobStatus job = createJobStatus("testGetRescheduleJobForPeriodic_insideWindow_failedJob",
createJobInfo().setPeriodic(HOUR_IN_MILLIS));
JobStatus failedJob = mService.getRescheduleJobForFailureLocked(job,
+ JobParameters.STOP_REASON_UNDEFINED,
JobParameters.INTERNAL_STOP_REASON_SUCCESSFUL_FINISH);
JobStatus rescheduledJob = mService.getRescheduleJobForPeriodic(failedJob);
@@ -739,6 +780,7 @@
advanceElapsedClock(5 * MINUTE_IN_MILLIS); // now + 5 minutes
failedJob = mService.getRescheduleJobForFailureLocked(job,
+ JobParameters.STOP_REASON_UNDEFINED,
JobParameters.INTERNAL_STOP_REASON_SUCCESSFUL_FINISH);
advanceElapsedClock(5 * MINUTE_IN_MILLIS); // now + 10 minutes
@@ -748,6 +790,7 @@
advanceElapsedClock(35 * MINUTE_IN_MILLIS); // now + 45 minutes
failedJob = mService.getRescheduleJobForFailureLocked(job,
+ JobParameters.STOP_REASON_UNDEFINED,
JobParameters.INTERNAL_STOP_REASON_SUCCESSFUL_FINISH);
advanceElapsedClock(10 * MINUTE_IN_MILLIS); // now + 55 minutes
@@ -759,6 +802,7 @@
advanceElapsedClock(2 * MINUTE_IN_MILLIS); // now + 57 minutes
failedJob = mService.getRescheduleJobForFailureLocked(job,
+ JobParameters.STOP_REASON_UNDEFINED,
JobParameters.INTERNAL_STOP_REASON_SUCCESSFUL_FINISH);
advanceElapsedClock(2 * MINUTE_IN_MILLIS); // now + 59 minutes
@@ -856,6 +900,7 @@
JobStatus job = createJobStatus("testGetRescheduleJobForPeriodic_outsideWindow_failedJob",
createJobInfo().setPeriodic(HOUR_IN_MILLIS));
JobStatus failedJob = mService.getRescheduleJobForFailureLocked(job,
+ JobParameters.STOP_REASON_UNDEFINED,
JobParameters.INTERNAL_STOP_REASON_SUCCESSFUL_FINISH);
long now = sElapsedRealtimeClock.millis();
long nextWindowStartTime = now + HOUR_IN_MILLIS;
@@ -893,6 +938,7 @@
"testGetRescheduleJobForPeriodic_outsideWindow_flex_failedJob",
createJobInfo().setPeriodic(HOUR_IN_MILLIS, 30 * MINUTE_IN_MILLIS));
JobStatus failedJob = mService.getRescheduleJobForFailureLocked(job,
+ JobParameters.STOP_REASON_UNDEFINED,
JobParameters.INTERNAL_STOP_REASON_SUCCESSFUL_FINISH);
// First window starts 30 minutes from now.
advanceElapsedClock(30 * MINUTE_IN_MILLIS);
@@ -935,6 +981,7 @@
"testGetRescheduleJobForPeriodic_outsideWindow_flex_failedJob_longPeriod",
createJobInfo().setPeriodic(7 * DAY_IN_MILLIS, 9 * HOUR_IN_MILLIS));
JobStatus failedJob = mService.getRescheduleJobForFailureLocked(job,
+ JobParameters.STOP_REASON_UNDEFINED,
JobParameters.INTERNAL_STOP_REASON_SUCCESSFUL_FINISH);
// First window starts 6.625 days from now.
advanceElapsedClock(6 * DAY_IN_MILLIS + 15 * HOUR_IN_MILLIS);
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
index 6df54a6..2c47fd9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -469,6 +469,34 @@
assertEquals(JobInfo.PRIORITY_LOW, job.getEffectivePriority());
}
+ @Test
+ public void testShouldTreatAsUserInitiated() {
+ JobInfo jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar"))
+ .setUserInitiated(false)
+ .build();
+ JobStatus job = createJobStatus(jobInfo);
+
+ assertFalse(job.shouldTreatAsUserInitiatedJob());
+
+ jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar"))
+ .setUserInitiated(true)
+ .build();
+ job = createJobStatus(jobInfo);
+
+ assertTrue(job.shouldTreatAsUserInitiatedJob());
+
+ JobStatus rescheduledJob = new JobStatus(job, NO_EARLIEST_RUNTIME, NO_LATEST_RUNTIME,
+ 0, 0, 0, 0);
+ assertTrue(rescheduledJob.shouldTreatAsUserInitiatedJob());
+
+ job.addInternalFlags(JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER);
+ assertFalse(job.shouldTreatAsUserInitiatedJob());
+
+ rescheduledJob = new JobStatus(job, NO_EARLIEST_RUNTIME, NO_LATEST_RUNTIME,
+ 0, 0, 0, 0);
+ assertFalse(rescheduledJob.shouldTreatAsUserInitiatedJob());
+ }
+
/**
* Test {@link JobStatus#wouldBeReadyWithConstraint} on explicit constraints that weren't
* requested.
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
index 4bc8242..0ea20a8 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
@@ -212,6 +213,10 @@
assertEquals(new DisplayDeviceConfig.BrightnessThrottlingData(throttlingLevels),
mDisplayDeviceConfig.getConcurrentDisplaysBrightnessThrottlingData());
+ assertNotNull(mDisplayDeviceConfig.getHostUsiVersion());
+ assertEquals(mDisplayDeviceConfig.getHostUsiVersion().getMajorVersion(), 2);
+ assertEquals(mDisplayDeviceConfig.getHostUsiVersion().getMinorVersion(), 0);
+
// Todo: Add asserts for BrightnessThrottlingData, DensityMapping,
// HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor.
}
@@ -570,6 +575,10 @@
+ "<item>30</item>\n"
+ "<item>40</item>\n"
+ "</screenOffBrightnessSensorValueToLux>\n"
+ + "<usiVersion>\n"
+ + "<majorVersion>2</majorVersion>\n"
+ + "<minorVersion>0</minorVersion>\n"
+ + "</usiVersion>\n"
+ "</displayConfiguration>\n";
}
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/BrightnessEventTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/BrightnessEventTest.java
index d332b30..c0c63c6 100644
--- a/services/tests/servicestests/src/com/android/server/display/brightness/BrightnessEventTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/BrightnessEventTest.java
@@ -30,6 +30,7 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public final class BrightnessEventTest {
+ private static final String DISPLAY_BRIGHTNESS_STRATEGY_NAME = "strategy_name";
private BrightnessEvent mBrightnessEvent;
@Before
@@ -53,6 +54,7 @@
mBrightnessEvent.setFlags(0);
mBrightnessEvent.setAdjustmentFlags(0);
mBrightnessEvent.setAutomaticBrightnessEnabled(true);
+ mBrightnessEvent.setDisplayBrightnessStrategyName(DISPLAY_BRIGHTNESS_STRATEGY_NAME);
}
@Test
@@ -70,7 +72,8 @@
"BrightnessEvent: disp=1, physDisp=test, brt=0.6, initBrt=25.0, rcmdBrt=0.6,"
+ " preBrt=NaN, lux=100.0, preLux=150.0, hbmMax=0.62, hbmMode=off, rbcStrength=-1,"
+ " thrmMax=0.65, powerFactor=0.2, wasShortTermModelActive=true, flags=,"
- + " reason=doze [ low_pwr ], autoBrightness=true";
+ + " reason=doze [ low_pwr ], autoBrightness=true, strategy="
+ + DISPLAY_BRIGHTNESS_STRATEGY_NAME;
assertEquals(expectedString, actualString);
}
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/BoostBrightnessStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/BoostBrightnessStrategyTest.java
index c1de894..c434631 100644
--- a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/BoostBrightnessStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/BoostBrightnessStrategyTest.java
@@ -55,6 +55,7 @@
.setBrightness(PowerManager.BRIGHTNESS_MAX)
.setBrightnessReason(brightnessReason)
.setSdrBrightness(PowerManager.BRIGHTNESS_MAX)
+ .setDisplayBrightnessStrategyName(mBoostBrightnessStrategy.getName())
.build();
DisplayBrightnessState updatedDisplayBrightnessState =
mBoostBrightnessStrategy.updateBrightness(displayPowerRequest);
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java
index 76fa172..d60caf6 100644
--- a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java
@@ -52,6 +52,7 @@
.setBrightness(dozeScreenBrightness)
.setBrightnessReason(brightnessReason)
.setSdrBrightness(dozeScreenBrightness)
+ .setDisplayBrightnessStrategyName(mDozeBrightnessModeStrategy.getName())
.build();
DisplayBrightnessState updatedDisplayBrightnessState =
mDozeBrightnessModeStrategy.updateBrightness(displayPowerRequest);
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/FollowerBrightnessStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/FollowerBrightnessStrategyTest.java
index f20404e..081f19d 100644
--- a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/FollowerBrightnessStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/FollowerBrightnessStrategyTest.java
@@ -54,6 +54,7 @@
.setBrightness(brightnessToFollow)
.setBrightnessReason(brightnessReason)
.setSdrBrightness(brightnessToFollow)
+ .setDisplayBrightnessStrategyName(mFollowerBrightnessStrategy.getName())
.build();
DisplayBrightnessState updatedDisplayBrightnessState =
mFollowerBrightnessStrategy.updateBrightness(displayPowerRequest);
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java
index 2487b32b..530245d 100644
--- a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java
@@ -55,6 +55,7 @@
.setBrightness(overrideBrightness)
.setBrightnessReason(brightnessReason)
.setSdrBrightness(overrideBrightness)
+ .setDisplayBrightnessStrategyName(mOverrideBrightnessStrategy.getName())
.build();
DisplayBrightnessState updatedDisplayBrightnessState =
mOverrideBrightnessStrategy.updateBrightness(displayPowerRequest);
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java
index 353e92e..7147aa8 100644
--- a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java
@@ -52,6 +52,8 @@
.setBrightness(PowerManager.BRIGHTNESS_OFF_FLOAT)
.setSdrBrightness(PowerManager.BRIGHTNESS_OFF_FLOAT)
.setBrightnessReason(brightnessReason)
+ .setDisplayBrightnessStrategyName(mScreenOffBrightnessModeStrategy
+ .getName())
.build();
DisplayBrightnessState updatedDisplayBrightnessState =
mScreenOffBrightnessModeStrategy.updateBrightness(displayPowerRequest);
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategyTest.java
index 99679a3..9830edb 100644
--- a/services/tests/servicestests/src/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategyTest.java
@@ -55,6 +55,7 @@
.setBrightness(temporaryBrightness)
.setBrightnessReason(brightnessReason)
.setSdrBrightness(temporaryBrightness)
+ .setDisplayBrightnessStrategyName(mTemporaryBrightnessStrategy.getName())
.build();
DisplayBrightnessState updatedDisplayBrightnessState =
mTemporaryBrightnessStrategy.updateBrightness(displayPowerRequest);
diff --git a/services/tests/servicestests/src/com/android/server/job/PendingJobQueueTest.java b/services/tests/servicestests/src/com/android/server/job/PendingJobQueueTest.java
index 8c3838b..23d7082 100644
--- a/services/tests/servicestests/src/com/android/server/job/PendingJobQueueTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/PendingJobQueueTest.java
@@ -201,6 +201,32 @@
}
}
assertNull(jobQueue.next());
+ assertEquals(0, jobQueue.size());
+ }
+
+ @Test
+ public void testRemove_duringIteration() {
+ List<JobStatus> jobs = new ArrayList<>();
+ jobs.add(createJobStatus("testRemove", createJobInfo(1), 1));
+ jobs.add(createJobStatus("testRemove", createJobInfo(2), 2));
+ jobs.add(createJobStatus("testRemove", createJobInfo(3).setExpedited(true), 3));
+ jobs.add(createJobStatus("testRemove", createJobInfo(4), 4));
+ jobs.add(createJobStatus("testRemove", createJobInfo(5).setExpedited(true), 5));
+
+ PendingJobQueue jobQueue = new PendingJobQueue();
+ jobQueue.addAll(jobs);
+
+ ArraySet<JobStatus> removed = new ArraySet<>();
+ JobStatus job;
+ jobQueue.resetIterator();
+ while ((job = jobQueue.next()) != null) {
+ jobQueue.remove(job);
+ removed.add(job);
+ assertFalse("Queue retained a removed job " + testJobToString(job),
+ jobQueue.contains(job));
+ }
+ assertNull(jobQueue.next());
+ assertEquals(0, jobQueue.size());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index d1ab541..eabbc76 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -99,6 +99,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
import android.service.voice.IVoiceInteractionSession;
import android.util.Pair;
import android.util.Size;
@@ -108,10 +109,12 @@
import androidx.test.filters.SmallTest;
+import com.android.compatibility.common.util.DeviceConfigStateHelper;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
import com.android.server.wm.utils.MockTracker;
+import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@@ -131,10 +134,9 @@
@Presubmit
@RunWith(WindowTestRunner.class)
public class ActivityStarterTests extends WindowTestsBase {
- private ActivityStartController mController;
- private ActivityMetricsLogger mActivityMetricsLogger;
- private PackageManagerInternal mMockPackageManager;
+ private static final String ENABLE_DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER =
+ "enable_default_rescind_bal_privileges_from_pending_intent_sender";
private static final int PRECONDITION_NO_CALLER_APP = 1;
private static final int PRECONDITION_NO_INTENT_COMPONENT = 1 << 1;
private static final int PRECONDITION_NO_ACTIVITY_INFO = 1 << 2;
@@ -145,7 +147,6 @@
private static final int PRECONDITION_DIFFERENT_UID = 1 << 7;
private static final int PRECONDITION_ACTIVITY_SUPPORTS_INTENT_EXCEPTION = 1 << 8;
private static final int PRECONDITION_CANNOT_START_ANY_ACTIVITY = 1 << 9;
-
private static final int FAKE_CALLING_UID = 666;
private static final int FAKE_REAL_CALLING_UID = 667;
private static final String FAKE_CALLING_PACKAGE = "com.whatever.dude";
@@ -153,6 +154,13 @@
private static final int UNIMPORTANT_UID2 = 12346;
private static final int CURRENT_IME_UID = 12347;
+ protected final DeviceConfigStateHelper mDeviceConfig = new DeviceConfigStateHelper(
+ DeviceConfig.NAMESPACE_WINDOW_MANAGER);
+
+ private ActivityStartController mController;
+ private ActivityMetricsLogger mActivityMetricsLogger;
+ private PackageManagerInternal mMockPackageManager;
+
@Before
public void setUp() throws Exception {
mController = mock(ActivityStartController.class);
@@ -161,6 +169,13 @@
doReturn(balController).when(mController).getBackgroundActivityLaunchController();
mActivityMetricsLogger = mock(ActivityMetricsLogger.class);
clearInvocations(mActivityMetricsLogger);
+ mDeviceConfig.set(ENABLE_DEFAULT_RESCIND_BAL_PRIVILEGES_FROM_PENDING_INTENT_SENDER,
+ String.valueOf(true));
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mDeviceConfig.close();
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DeviceStateControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DeviceStateControllerTests.java
index 86732c9..2a28ae2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DeviceStateControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DeviceStateControllerTests.java
@@ -16,13 +16,12 @@
package com.android.server.wm;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
import android.content.Context;
import android.content.res.Resources;
@@ -32,9 +31,10 @@
import androidx.test.filters.SmallTest;
+import com.android.internal.R;
+
import org.junit.Before;
import org.junit.Test;
-import org.mockito.ArgumentCaptor;
import java.util.function.Consumer;
@@ -48,92 +48,76 @@
@Presubmit
public class DeviceStateControllerTests {
- private DeviceStateController.FoldStateListener mFoldStateListener;
private DeviceStateController mTarget;
private DeviceStateControllerBuilder mBuilder;
private Context mMockContext;
- private Handler mMockHandler;
- private Resources mMockRes;
private DeviceStateManager mMockDeviceStateManager;
-
- private Consumer<DeviceStateController.FoldState> mDelegate;
- private DeviceStateController.FoldState mCurrentState = DeviceStateController.FoldState.UNKNOWN;
+ private DeviceStateController.DeviceState mCurrentState =
+ DeviceStateController.DeviceState.UNKNOWN;
@Before
public void setUp() {
mBuilder = new DeviceStateControllerBuilder();
- mCurrentState = DeviceStateController.FoldState.UNKNOWN;
+ mCurrentState = DeviceStateController.DeviceState.UNKNOWN;
}
- private void initialize(boolean supportFold, boolean supportHalfFold) throws Exception {
+ private void initialize(boolean supportFold, boolean supportHalfFold) {
mBuilder.setSupportFold(supportFold, supportHalfFold);
- mDelegate = (newFoldState) -> {
+ Consumer<DeviceStateController.DeviceState> delegate = (newFoldState) -> {
mCurrentState = newFoldState;
};
- mBuilder.setDelegate(mDelegate);
+ mBuilder.setDelegate(delegate);
mBuilder.build();
- verifyFoldStateListenerRegistration(1);
+ verify(mMockDeviceStateManager).registerCallback(any(), any());
}
@Test
- public void testInitialization() throws Exception {
+ public void testInitialization() {
initialize(true /* supportFold */, true /* supportHalfFolded */);
- mFoldStateListener.onStateChanged(mUnfoldedStates[0]);
- assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN);
+ mTarget.onStateChanged(mOpenDeviceStates[0]);
+ assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
}
@Test
- public void testInitializationWithNoFoldSupport() throws Exception {
+ public void testInitializationWithNoFoldSupport() {
initialize(false /* supportFold */, false /* supportHalfFolded */);
- mFoldStateListener.onStateChanged(mFoldedStates[0]);
+ mTarget.onStateChanged(mFoldedStates[0]);
// Note that the folded state is ignored.
- assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN);
+ assertEquals(DeviceStateController.DeviceState.UNKNOWN, mCurrentState);
}
@Test
- public void testWithFoldSupported() throws Exception {
+ public void testWithFoldSupported() {
initialize(true /* supportFold */, false /* supportHalfFolded */);
- mFoldStateListener.onStateChanged(mUnfoldedStates[0]);
- assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN);
- mFoldStateListener.onStateChanged(mFoldedStates[0]);
- assertEquals(mCurrentState, DeviceStateController.FoldState.FOLDED);
- mFoldStateListener.onStateChanged(mHalfFoldedStates[0]);
- assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN); // Ignored
+ mTarget.onStateChanged(mOpenDeviceStates[0]);
+ assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
+ mTarget.onStateChanged(mFoldedStates[0]);
+ assertEquals(DeviceStateController.DeviceState.FOLDED, mCurrentState);
+ mTarget.onStateChanged(mHalfFoldedStates[0]);
+ assertEquals(DeviceStateController.DeviceState.UNKNOWN, mCurrentState); // Ignored
}
@Test
- public void testWithHalfFoldSupported() throws Exception {
+ public void testWithHalfFoldSupported() {
initialize(true /* supportFold */, true /* supportHalfFolded */);
- mFoldStateListener.onStateChanged(mUnfoldedStates[0]);
- assertEquals(mCurrentState, DeviceStateController.FoldState.OPEN);
- mFoldStateListener.onStateChanged(mFoldedStates[0]);
- assertEquals(mCurrentState, DeviceStateController.FoldState.FOLDED);
- mFoldStateListener.onStateChanged(mHalfFoldedStates[0]);
- assertEquals(mCurrentState, DeviceStateController.FoldState.HALF_FOLDED);
+ mTarget.onStateChanged(mOpenDeviceStates[0]);
+ assertEquals(DeviceStateController.DeviceState.OPEN, mCurrentState);
+ mTarget.onStateChanged(mFoldedStates[0]);
+ assertEquals(DeviceStateController.DeviceState.FOLDED, mCurrentState);
+ mTarget.onStateChanged(mHalfFoldedStates[0]);
+ assertEquals(DeviceStateController.DeviceState.HALF_FOLDED, mCurrentState);
}
-
private final int[] mFoldedStates = {0};
- private final int[] mUnfoldedStates = {1};
+ private final int[] mOpenDeviceStates = {1};
private final int[] mHalfFoldedStates = {2};
-
-
- private void verifyFoldStateListenerRegistration(int numOfInvocation) {
- final ArgumentCaptor<DeviceStateController.FoldStateListener> listenerCaptor =
- ArgumentCaptor.forClass(DeviceStateController.FoldStateListener.class);
- verify(mMockDeviceStateManager, times(numOfInvocation)).registerCallback(
- any(),
- listenerCaptor.capture());
- if (numOfInvocation > 0) {
- mFoldStateListener = listenerCaptor.getValue();
- }
- }
+ private final int[] mRearDisplayStates = {3};
private class DeviceStateControllerBuilder {
private boolean mSupportFold = false;
private boolean mSupportHalfFold = false;
- private Consumer<DeviceStateController.FoldState> mDelegate;
+ private Consumer<DeviceStateController.DeviceState> mDelegate;
DeviceStateControllerBuilder setSupportFold(
boolean supportFold, boolean supportHalfFold) {
@@ -143,34 +127,44 @@
}
DeviceStateControllerBuilder setDelegate(
- Consumer<DeviceStateController.FoldState> delegate) {
+ Consumer<DeviceStateController.DeviceState> delegate) {
mDelegate = delegate;
return this;
}
private void mockFold(boolean enableFold, boolean enableHalfFold) {
+ if (enableFold || enableHalfFold) {
+ when(mMockContext.getResources()
+ .getIntArray(R.array.config_openDeviceStates))
+ .thenReturn(mOpenDeviceStates);
+ when(mMockContext.getResources()
+ .getIntArray(R.array.config_rearDisplayDeviceStates))
+ .thenReturn(mRearDisplayStates);
+ }
+
if (enableFold) {
- when(mMockContext.getResources().getIntArray(
- com.android.internal.R.array.config_foldedDeviceStates))
+ when(mMockContext.getResources()
+ .getIntArray(R.array.config_foldedDeviceStates))
.thenReturn(mFoldedStates);
}
if (enableHalfFold) {
- when(mMockContext.getResources().getIntArray(
- com.android.internal.R.array.config_halfFoldedDeviceStates))
+ when(mMockContext.getResources()
+ .getIntArray(R.array.config_halfFoldedDeviceStates))
.thenReturn(mHalfFoldedStates);
}
}
- private void build() throws Exception {
+ private void build() {
mMockContext = mock(Context.class);
- mMockRes = mock(Resources.class);
- when(mMockContext.getResources()).thenReturn((mMockRes));
mMockDeviceStateManager = mock(DeviceStateManager.class);
when(mMockContext.getSystemService(DeviceStateManager.class))
.thenReturn(mMockDeviceStateManager);
+ Resources mockRes = mock(Resources.class);
+ when(mMockContext.getResources()).thenReturn((mockRes));
mockFold(mSupportFold, mSupportHalfFold);
- mMockHandler = mock(Handler.class);
- mTarget = new DeviceStateController(mMockContext, mMockHandler, mDelegate);
+ Handler mockHandler = mock(Handler.class);
+ mTarget = new DeviceStateController(mMockContext, mockHandler);
+ mTarget.registerDeviceStateCallback(mDelegate);
}
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 78707d6..3b34ba4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1738,7 +1738,7 @@
// No need to apply rotation if the display ignores orientation request.
doCallRealMethod().when(displayContent).rotationForActivityInDifferentOrientation(any());
- pinnedActivity.mOrientation = SCREEN_ORIENTATION_LANDSCAPE;
+ pinnedActivity.setOverrideOrientation(SCREEN_ORIENTATION_LANDSCAPE);
displayContent.setIgnoreOrientationRequest(true);
assertEquals(WindowConfiguration.ROTATION_UNDEFINED,
displayContent.rotationForActivityInDifferentOrientation(pinnedActivity));
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 4ce43e1..f814608 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -705,7 +705,7 @@
enableOrientationSensor();
- mTarget.foldStateChanged(DeviceStateController.FoldState.OPEN);
+ mTarget.foldStateChanged(DeviceStateController.DeviceState.OPEN);
freezeRotation(Surface.ROTATION_270);
mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_0));
@@ -715,7 +715,7 @@
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
// ... until half-fold
- mTarget.foldStateChanged(DeviceStateController.FoldState.HALF_FOLDED);
+ mTarget.foldStateChanged(DeviceStateController.DeviceState.HALF_FOLDED);
assertTrue(waitForUiHandler());
verify(sMockWm).updateRotation(false, false);
assertTrue(waitForUiHandler());
@@ -723,7 +723,7 @@
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
// ... then transition back to flat
- mTarget.foldStateChanged(DeviceStateController.FoldState.OPEN);
+ mTarget.foldStateChanged(DeviceStateController.DeviceState.OPEN);
assertTrue(waitForUiHandler());
verify(sMockWm, atLeast(1)).updateRotation(false, false);
assertTrue(waitForUiHandler());
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
index 791d6f2..7d30b60 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -16,14 +16,23 @@
package com.android.server.wm;
+import static android.content.pm.ActivityInfo.OVERRIDE_ANY_ORIENTATION;
import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION;
import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH;
import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION;
+import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE;
+import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR;
+import static android.content.pm.ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION;
import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH;
import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE;
+import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE;
import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -491,6 +500,80 @@
return mainWindow;
}
+ // overrideOrientationIfNeeded
+
+ @Test
+ @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT})
+ public void testOverrideOrientationIfNeeded_portraitOverrideEnabled_returnsPortrait()
+ throws Exception {
+ assertEquals(mController.overrideOrientationIfNeeded(
+ /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_PORTRAIT);
+ }
+
+ @Test
+ @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR})
+ public void testOverrideOrientationIfNeeded_portraitOverrideEnabled_returnsNosensor() {
+ assertEquals(mController.overrideOrientationIfNeeded(
+ /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_NOSENSOR);
+ }
+
+ @Test
+ @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR})
+ public void testOverrideOrientationIfNeeded_nosensorOverride_orientationFixed_returnsUnchanged() {
+ assertEquals(mController.overrideOrientationIfNeeded(
+ /* candidate */ SCREEN_ORIENTATION_PORTRAIT), SCREEN_ORIENTATION_PORTRAIT);
+ }
+
+ @Test
+ @EnableCompatChanges({OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE})
+ public void testOverrideOrientationIfNeeded_reverseLandscapeOverride_orientationPortraitOrUndefined_returnsUnchanged() {
+ assertEquals(mController.overrideOrientationIfNeeded(
+ /* candidate */ SCREEN_ORIENTATION_PORTRAIT), SCREEN_ORIENTATION_PORTRAIT);
+ assertEquals(mController.overrideOrientationIfNeeded(
+ /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_UNSPECIFIED);
+ }
+
+ @Test
+ @EnableCompatChanges({OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE})
+ public void testOverrideOrientationIfNeeded_reverseLandscapeOverride_orientationLandscape_returnsReverseLandscape() {
+ assertEquals(mController.overrideOrientationIfNeeded(
+ /* candidate */ SCREEN_ORIENTATION_LANDSCAPE),
+ SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
+ }
+
+ @Test
+ @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT})
+ public void testOverrideOrientationIfNeeded_portraitOverride_orientationFixed_returnsUnchanged() {
+ assertEquals(mController.overrideOrientationIfNeeded(
+ /* candidate */ SCREEN_ORIENTATION_NOSENSOR), SCREEN_ORIENTATION_NOSENSOR);
+ }
+
+ @Test
+ @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT, OVERRIDE_ANY_ORIENTATION})
+ public void testOverrideOrientationIfNeeded_portraitAndIgnoreFixedOverrides_returnsPortrait() {
+ assertEquals(mController.overrideOrientationIfNeeded(
+ /* candidate */ SCREEN_ORIENTATION_NOSENSOR), SCREEN_ORIENTATION_PORTRAIT);
+ }
+
+ @Test
+ @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR, OVERRIDE_ANY_ORIENTATION})
+ public void testOverrideOrientationIfNeeded_noSensorAndIgnoreFixedOverrides_returnsNosensor() {
+ assertEquals(mController.overrideOrientationIfNeeded(
+ /* candidate */ SCREEN_ORIENTATION_PORTRAIT), SCREEN_ORIENTATION_NOSENSOR);
+ }
+
+ @Test
+ @EnableCompatChanges({OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT})
+ public void testOverrideOrientationIfNeeded_propertyIsFalse_returnsUnchanged()
+ throws Exception {
+ mockThatProperty(PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE, /* value */ false);
+
+ mController = new LetterboxUiController(mWm, mActivity);
+
+ assertEquals(mController.overrideOrientationIfNeeded(
+ /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED), SCREEN_ORIENTATION_UNSPECIFIED);
+ }
+
private void mockThatProperty(String propertyName, boolean value) throws Exception {
Property property = new Property(propertyName, /* value */ value, /* packageName */ "",
/* className */ "");
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 08635ab..c131c84 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -468,7 +468,7 @@
mWm.setRecentsAnimationController(mController);
spyOn(mDisplayContent.mFixedRotationTransitionListener);
final ActivityRecord recents = mock(ActivityRecord.class);
- recents.mOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+ recents.setOverrideOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
doReturn(ORIENTATION_PORTRAIT).when(recents)
.getRequestedConfigurationOrientation(anyBoolean());
mDisplayContent.mFixedRotationTransitionListener.onStartRecentsAnimation(recents);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 7e150e9..91e875f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -102,7 +102,7 @@
import com.android.internal.policy.SystemBarUtils;
import com.android.internal.statusbar.LetterboxDetails;
import com.android.server.statusbar.StatusBarManagerInternal;
-import com.android.server.wm.DeviceStateController.FoldState;
+import com.android.server.wm.DeviceStateController.DeviceState;
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
@@ -3202,9 +3202,9 @@
private void setFoldablePosture(boolean isHalfFolded, boolean isTabletop) {
final DisplayRotation r = mActivity.mDisplayContent.getDisplayRotation();
doReturn(isHalfFolded).when(r).isDisplaySeparatingHinge();
- doReturn(false).when(r).isDeviceInPosture(any(FoldState.class), anyBoolean());
+ doReturn(false).when(r).isDeviceInPosture(any(DeviceState.class), anyBoolean());
if (isHalfFolded) {
- doReturn(true).when(r).isDeviceInPosture(FoldState.HALF_FOLDED, isTabletop);
+ doReturn(true).when(r).isDeviceInPosture(DeviceState.HALF_FOLDED, isTabletop);
}
mActivity.recomputeConfiguration();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index 1a1ca54..5006bf7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -1665,7 +1665,7 @@
@Override
int getOrientation() {
- return getOrientation(super.mOrientation);
+ return getOrientation(super.getOverrideOrientation());
}
@Override
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 0aa1715..cad1f6f 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -16,6 +16,8 @@
package com.android.server.usb;
+import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN;
+import static android.hardware.usb.DisplayPortAltModeInfo.LINK_TRAINING_STATUS_UNKNOWN;
import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL;
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
@@ -1188,11 +1190,11 @@
final String portId = args[1];
if (mPortManager != null) {
mPortManager.simulateDisplayPortAltModeInfo(portId,
- DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN,
- DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN,
+ DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN,
+ DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN,
0,
false,
- 0,
+ LINK_TRAINING_STATUS_UNKNOWN,
pw);
pw.println();
mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")),
@@ -1271,7 +1273,7 @@
pw.println(" <cable>: type DisplayPortAltModeStatus");
pw.println(" <num-lanes>: type int, expected 0, 2, or 4");
pw.println(" <hpd>: type boolean, expected true or false");
- pw.println(" <link-training-status>: type int with range [0,2]");
+ pw.println(" <link-training-status>: type LinkTrainingStatus");
pw.println(" dumpsys usb reset-displayport-status \"matrix\"");
pw.println("reset-displayport-status can also be used in order to set");
pw.println("the DisplayPortInfo to default values.");
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
index b8536f9..afee940 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
@@ -17,6 +17,8 @@
package com.android.server.voiceinteraction;
import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
+import static android.Manifest.permission.LOG_COMPAT_CHANGE;
+import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG;
import static android.Manifest.permission.RECORD_AUDIO;
import static android.service.attention.AttentionService.PROXIMITY_UNKNOWN;
import static android.service.voice.HotwordDetectionService.AUDIO_SOURCE_EXTERNAL;
@@ -43,11 +45,14 @@
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_SECURITY_EXCEPTION;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_UNEXPECTED_CALLBACK;
import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECT_UNEXPECTED_CALLBACK;
+import static com.android.server.voiceinteraction.HotwordDetectionConnection.ENFORCE_HOTWORD_PHRASE_ID;
import static com.android.server.voiceinteraction.SoundTriggerSessionPermissionsDecorator.enforcePermissionForPreflight;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.app.AppOpsManager;
+import android.app.compat.CompatChanges;
import android.attention.AttentionManagerInternal;
import android.content.Context;
import android.content.PermissionChecker;
@@ -692,8 +697,13 @@
}
}
- static void enforceExtraKeyphraseIdNotLeaked(HotwordDetectedResult result,
+ @RequiresPermission(allOf = {READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE})
+ void enforceExtraKeyphraseIdNotLeaked(HotwordDetectedResult result,
SoundTrigger.KeyphraseRecognitionEvent recognitionEvent) {
+ if (!CompatChanges.isChangeEnabled(ENFORCE_HOTWORD_PHRASE_ID,
+ mVoiceInteractionServiceUid)) {
+ return;
+ }
// verify the phrase ID in HotwordDetectedResult is not exposing extra phrases
// the DSP did not detect
for (SoundTrigger.KeyphraseRecognitionExtra keyphrase : recognitionEvent.keyphraseExtras) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index 665d5e7..220ef21 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -29,6 +29,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
import android.content.ComponentName;
import android.content.ContentCaptureOptions;
import android.content.Context;
@@ -39,6 +41,7 @@
import android.media.AudioManagerInternal;
import android.media.permission.Identity;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IRemoteCallback;
@@ -48,6 +51,7 @@
import android.os.ServiceManager;
import android.os.SharedMemory;
import android.provider.DeviceConfig;
+import android.service.voice.HotwordDetectedResult;
import android.service.voice.HotwordDetectionService;
import android.service.voice.HotwordDetector;
import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback;
@@ -83,6 +87,26 @@
private static final String TAG = "HotwordDetectionConnection";
static final boolean DEBUG = false;
+ /**
+ * For apps targeting Android API {@link Build.VERSION_CODES#UPSIDE_DOWN_CAKE} and above,
+ * implementors of the {@link HotwordDetectionService} must not augment the phrase IDs which are
+ * supplied via {@link HotwordDetectionService
+ * #onDetect(AlwaysOnHotwordDetector.EventPayload, long, HotwordDetectionService.Callback)}.
+ *
+ * <p>The {@link HotwordDetectedResult#getHotwordPhraseId()} must match one of the phrase IDs
+ * from the {@link android.service.voice.AlwaysOnHotwordDetector
+ * .EventPayload#getKeyphraseRecognitionExtras()} list.
+ * </p>
+ *
+ * <p>This behavior change is made to ensure the {@link HotwordDetectionService} honors what
+ * it receives from the {@link android.hardware.soundtrigger.SoundTriggerModule}, and it
+ * cannot signal to the client application a phrase which was not origially detected.
+ * </p>
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final long ENFORCE_HOTWORD_PHRASE_ID = 215066299L;
+
private static final String KEY_RESTART_PERIOD_IN_SECONDS = "restart_period_in_seconds";
private static final long RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS = 60 * 60 * 1000; // 1 hour
private static final int MAX_ISOLATED_PROCESS_NUMBER = 10;
@@ -108,7 +132,7 @@
final int mUser;
final Context mContext;
volatile HotwordDetectionServiceIdentity mIdentity;
- //TODO: add similar identity for visual query service for the use of content capturing
+ //TODO: Consider rename this to SandboxedDetectionIdentity
private Instant mLastRestartInstant;
private ScheduledFuture<?> mDebugHotwordLoggingTimeoutFuture = null;
@@ -117,6 +141,7 @@
@GuardedBy("mLock")
@Nullable
private final Identity mVoiceInteractorIdentity;
+ private int mRestartCount = 0;
@NonNull private ServiceConnection mRemoteHotwordDetectionService;
@NonNull private ServiceConnection mRemoteVisualQueryDetectionService;
private IBinder mAudioFlinger;
@@ -234,10 +259,6 @@
mDebugHotwordLogging = false;
unbindVisualQueryDetectionService();
unbindHotwordDetectionService();
- if (mIdentity != null) {
- removeServiceUidForAudioPolicy(mIdentity.getIsolatedUid());
- }
- mIdentity = null;
if (mCancellationTaskFuture != null) {
mCancellationTaskFuture.cancel(/* mayInterruptIfRunning= */ true);
}
@@ -246,18 +267,34 @@
}
}
+ @SuppressWarnings("GuardedBy")
private void unbindVisualQueryDetectionService() {
if (mRemoteVisualQueryDetectionService != null) {
mRemoteVisualQueryDetectionService.unbind();
- //TODO: Set visual query detection service provider to null
+ mRemoteVisualQueryDetectionService = null;
}
+ resetDetectionProcessIdentityIfEmptyLocked();
}
+ @SuppressWarnings("GuardedBy")
private void unbindHotwordDetectionService() {
if (mRemoteHotwordDetectionService != null) {
mRemoteHotwordDetectionService.unbind();
+ mRemoteHotwordDetectionService = null;
+ }
+ resetDetectionProcessIdentityIfEmptyLocked();
+ }
+
+ // TODO(b/266669849): Clean up SuppressWarnings for calling methods.
+ @GuardedBy("mLock")
+ private void resetDetectionProcessIdentityIfEmptyLocked() {
+ if (mRemoteHotwordDetectionService == null && mRemoteVisualQueryDetectionService == null) {
LocalServices.getService(PermissionManagerServiceInternal.class)
.setHotwordDetectionServiceProvider(null);
+ if (mIdentity != null) {
+ removeServiceUidForAudioPolicy(mIdentity.getIsolatedUid());
+ }
+ mIdentity = null;
}
}
@@ -427,14 +464,20 @@
ServiceConnection oldHotwordConnection = mRemoteHotwordDetectionService;
ServiceConnection oldVisualQueryDetectionConnection = mRemoteVisualQueryDetectionService;
HotwordDetectionServiceIdentity previousIdentity = mIdentity;
- //TODO: Add previousIdentity for visual query detection service
mLastRestartInstant = Instant.now();
// Recreate connection to reset the cache.
+ mRestartCount++;
- mRemoteHotwordDetectionService = mHotwordDetectionServiceConnectionFactory.createLocked();
- mRemoteVisualQueryDetectionService =
- mVisualQueryDetectionServiceConnectionFactory.createLocked();
+ if (oldHotwordConnection != null) {
+ mRemoteHotwordDetectionService =
+ mHotwordDetectionServiceConnectionFactory.createLocked();
+ }
+
+ if (oldVisualQueryDetectionConnection != null) {
+ mRemoteVisualQueryDetectionService =
+ mVisualQueryDetectionServiceConnectionFactory.createLocked();
+ }
Slog.v(TAG, "Started the new process, dispatching processRestarted to detector");
runForEachDetectorSessionLocked((session) -> {
@@ -458,6 +501,9 @@
oldVisualQueryDetectionConnection.unbind();
}
+ // TODO(b/266670431): Handles identity resetting for the new process to make sure the
+ // correct identity is provided.
+
if (previousIdentity != null) {
removeServiceUidForAudioPolicy(previousIdentity.getIsolatedUid());
}
@@ -531,8 +577,7 @@
&& mRemoteHotwordDetectionService != null
&& mRemoteHotwordDetectionService.isBound());
pw.print(prefix); pw.print("mRestartCount=");
- pw.println(mHotwordDetectionServiceConnectionFactory.mRestartCount);
- pw.println(mVisualQueryDetectionServiceConnectionFactory.mRestartCount);
+ pw.println(mRestartCount);
pw.print(prefix); pw.print("mLastRestartInstant="); pw.println(mLastRestartInstant);
pw.print(prefix); pw.print("mDetectorType=");
pw.println(HotwordDetector.detectorTypeToString(mDetectorType));
@@ -547,8 +592,6 @@
private final Intent mIntent;
private final int mBindingFlags;
- private int mRestartCount = 0;
-
ServiceConnectionFactory(@NonNull Intent intent, boolean bindInstantServiceAllowed) {
mIntent = intent;
mBindingFlags = bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0;
@@ -558,7 +601,7 @@
ServiceConnection connection =
new ServiceConnection(mContext, mIntent, mBindingFlags, mUser,
ISandboxedDetectionService.Stub::asInterface,
- mRestartCount++ % MAX_ISOLATED_PROCESS_NUMBER);
+ mRestartCount % MAX_ISOLATED_PROCESS_NUMBER);
connection.connect();
updateAudioFlinger(connection, mAudioFlinger);
@@ -660,13 +703,11 @@
HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE,
mVoiceInteractionServiceUid);
}
- String instancePrefix =
- mIntent.getAction().equals(HotwordDetectionService.SERVICE_INTERFACE)
- ? "hotword_detector_" : "visual_query_detector_";
boolean bindResult = mContext.bindIsolatedService(
mIntent,
- Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE | mBindingFlags,
- instancePrefix + mInstanceNumber,
+ Context.BIND_SHARED_ISOLATED_PROCESS | Context.BIND_AUTO_CREATE
+ | Context.BIND_FOREGROUND_SERVICE | mBindingFlags,
+ "hotword_detector_" + mInstanceNumber,
mExecutor,
serviceConnection);
if (!bindResult) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index ddb3262..f0f230f 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -34,6 +34,7 @@
import android.net.NetworkCapabilities;
import android.net.ipsec.ike.SaProposal;
import android.os.Build;
+import android.os.Handler;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.service.carrier.CarrierService;
@@ -49,6 +50,7 @@
import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.feature.RcsFeature;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
import com.android.internal.telephony.ICarrierConfigLoader;
import com.android.telephony.Rlog;
@@ -65,7 +67,7 @@
@SystemService(Context.CARRIER_CONFIG_SERVICE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public class CarrierConfigManager {
- private final static String TAG = "CarrierConfigManager";
+ private static final String TAG = "CarrierConfigManager";
/**
* Extra included in {@link #ACTION_CARRIER_CONFIG_CHANGED} to indicate the slot index that the
@@ -108,25 +110,25 @@
* Only send USSD over IMS while CS is out of service, otherwise send USSD over CS.
* {@link #KEY_CARRIER_USSD_METHOD_INT}
*/
- public static final int USSD_OVER_CS_PREFERRED = 0;
+ public static final int USSD_OVER_CS_PREFERRED = 0;
/**
* Send USSD over IMS or CS while IMS is out of service or silent redial over CS if needed.
* {@link #KEY_CARRIER_USSD_METHOD_INT}
*/
- public static final int USSD_OVER_IMS_PREFERRED = 1;
+ public static final int USSD_OVER_IMS_PREFERRED = 1;
/**
* Only send USSD over CS.
* {@link #KEY_CARRIER_USSD_METHOD_INT}
*/
- public static final int USSD_OVER_CS_ONLY = 2;
+ public static final int USSD_OVER_CS_ONLY = 2;
/**
* Only send USSD over IMS and disallow silent redial over CS.
* {@link #KEY_CARRIER_USSD_METHOD_INT}
*/
- public static final int USSD_OVER_IMS_ONLY = 3;
+ public static final int USSD_OVER_IMS_ONLY = 3;
/**
* Indicates CARRIER_NR_AVAILABILITY_NSA determine that the carrier enable the non-standalone
@@ -161,8 +163,8 @@
* @see TelephonyManager#getSimCarrierId()
* @see TelephonyManager#getSimSpecificCarrierId()
*/
- public static final String
- ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
+ public static final String ACTION_CARRIER_CONFIG_CHANGED =
+ "android.telephony.action.CARRIER_CONFIG_CHANGED";
// Below are the keys used in carrier config bundles. To add a new variable, define the key and
// give it a default value in sDefaults. If you need to ship a per-network override in the
@@ -183,8 +185,8 @@
* @deprecated Use {@link Ims#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL} instead.
*/
@Deprecated
- public static final String
- KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
+ public static final String KEY_CARRIER_VOLTE_PROVISIONED_BOOL =
+ "carrier_volte_provisioned_bool";
/**
* Boolean indicating the Supplementary Services(SS) is disable when airplane mode on in the
@@ -217,29 +219,29 @@
public static final String KEY_CALL_FORWARDING_WHEN_UNREACHABLE_SUPPORTED_BOOL =
"call_forwarding_when_unreachable_supported_bool";
- /**
- * Boolean indicating if carrier supports call forwarding option "When unanswered".
- *
- * {@code true}: Call forwarding option "When unanswered" is supported.
- * {@code false}: Call forwarding option "When unanswered" is not supported. Option will be
- * removed in the UI.
- *
- * By default this value is true.
- * @hide
- */
+ /**
+ * Boolean indicating if carrier supports call forwarding option "When unanswered".
+ *
+ * {@code true}: Call forwarding option "When unanswered" is supported.
+ * {@code false}: Call forwarding option "When unanswered" is not supported. Option will be
+ * removed in the UI.
+ *
+ * By default this value is true.
+ * @hide
+ */
public static final String KEY_CALL_FORWARDING_WHEN_UNANSWERED_SUPPORTED_BOOL =
"call_forwarding_when_unanswered_supported_bool";
- /**
- * Boolean indicating if carrier supports call forwarding option "When busy".
- *
- * {@code true}: Call forwarding option "When busy" is supported.
- * {@code false}: Call forwarding option "When busy" is not supported. Option will be
- * removed in the UI.
- *
- * By default this value is true.
- * @hide
- */
+ /**
+ * Boolean indicating if carrier supports call forwarding option "When busy".
+ *
+ * {@code true}: Call forwarding option "When busy" is supported.
+ * {@code false}: Call forwarding option "When busy" is not supported. Option will be
+ * removed in the UI.
+ *
+ * By default this value is true.
+ * @hide
+ */
public static final String KEY_CALL_FORWARDING_WHEN_BUSY_SUPPORTED_BOOL =
"call_forwarding_when_busy_supported_bool";
@@ -259,12 +261,12 @@
public static final String KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL =
"additional_settings_call_waiting_visibility_bool";
- /**
- * Boolean indicating if the "Call barring" item is visible in the Call Settings menu.
- * If true, the "Call Barring" menu will be visible. If false, the menu will be gone.
- *
- * Disabled by default.
- */
+ /**
+ * Boolean indicating if the "Call barring" item is visible in the Call Settings menu.
+ * If true, the "Call Barring" menu will be visible. If false, the menu will be gone.
+ *
+ * Disabled by default.
+ */
public static final String KEY_CALL_BARRING_VISIBILITY_BOOL =
"call_barring_visibility_bool";
@@ -321,8 +323,8 @@
* If true, this will prevent the IccNetworkDepersonalizationPanel from being shown, and
* effectively disable the "Sim network lock" feature.
*/
- public static final String
- KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
+ public static final String KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL =
+ "ignore_sim_network_locked_events_bool";
/**
* When checking if a given number is the voicemail number, if this flag is true
@@ -340,16 +342,15 @@
* consequence: there will be no way to make an Emergency Call if your SIM is network-locked and
* you don't know the PIN.)
*/
- public static final String
- KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
+ public static final String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL =
+ "sim_network_unlock_allow_dismiss_bool";
/**
* Flag indicating whether or not sending emergency SMS messages over IMS
* is supported when in LTE/limited LTE (Emergency only) service mode..
- *
*/
- public static final String
- KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL = "support_emergency_sms_over_ims_bool";
+ public static final String KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL =
+ "support_emergency_sms_over_ims_bool";
/** Flag indicating if the phone is a world phone */
public static final String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
@@ -359,8 +360,8 @@
* If true, entitlement checks will be executed if device has been configured for it,
* If false, entitlement checks will be skipped.
*/
- public static final String
- KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
+ public static final String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL =
+ "require_entitlement_checks_bool";
/**
* Flag indicating if the carrier supports tethering of mobile data.
@@ -392,8 +393,8 @@
* consistent with the regular Dialer, this value should agree with the corresponding values
* from config.xml under apps/Contacts.
*/
- public static final String
- KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool";
+ public static final String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL =
+ "enable_dialer_key_vibration_bool";
/** Flag indicating if dtmf tone type is enabled */
public static final String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
@@ -416,11 +417,12 @@
* @hide
*/
public static final String KEY_PLAY_CALL_RECORDING_TONE_BOOL = "play_call_recording_tone_bool";
+
/**
* Determines if the carrier requires converting the destination number before sending out an
* SMS. Certain networks and numbering plans require different formats.
*/
- public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL=
+ public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL =
"sms_requires_destination_number_conversion_bool";
/**
@@ -428,7 +430,8 @@
* platforms, even the ones with hard SEND/END keys, but for maximum flexibility it's controlled
* by a flag here (which can be overridden on a per-product basis.)
*/
- public static final String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
+ public static final String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL =
+ "show_onscreen_dial_button_bool";
/** Determines if device implements a noise suppression device for in call audio. */
public static final String
@@ -440,8 +443,8 @@
* accidental redialing from the call log UI. This is a good idea, so the default here is
* false.)
*/
- public static final String
- KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool";
+ public static final String KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL =
+ "allow_emergency_numbers_in_call_log_bool";
/**
* A string array containing numbers that shouldn't be included in the call log.
@@ -467,10 +470,9 @@
* Flag indicating whether to show single operator row in the choose network setting.
*
* The device configuration value {@code config_enableNewAutoSelectNetworkUI} ultimately
- * controls whether this carrier configuration option is used. Where
- * {@code config_enableNewAutoSelectNetworkUI} is false, the value of the
- * {@link #KEY_SHOW_SINGLE_OPERATOR_ROW_IN_CHOOSE_NETWORK_SETTING_BOOL} carrier configuration
- * option is ignored.
+ * controls whether this carrier configuration option is used.
+ * Where {@code config_enableNewAutoSelectNetworkUI} is false, the value of this
+ * carrier configuration is ignored.
*
* If {@code true}, default value, merge the duplicate networks which with the same plmn, keep
* the one that with the higher signal strength level.
@@ -498,18 +500,18 @@
* @deprecated Never implemented. Has no behavior impact when override. DO NOT USE.
*/
@Deprecated
- public static final String
- KEY_SIMPLIFIED_NETWORK_SETTINGS_BOOL = "simplified_network_settings_bool";
+ public static final String KEY_SIMPLIFIED_NETWORK_SETTINGS_BOOL =
+ "simplified_network_settings_bool";
/** Control whether users can reach the SIM lock settings. */
- public static final String
- KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
+ public static final String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
/** Control whether users can edit APNs in Settings. */
public static final String KEY_APN_EXPAND_BOOL = "apn_expand_bool";
/** Control whether users can choose a network operator. */
- public static final String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool";
+ public static final String KEY_OPERATOR_SELECTION_EXPAND_BOOL =
+ "operator_selection_expand_bool";
/**
* Used in the Preferred Network Types menu to determine if the 2G option is displayed.
@@ -537,7 +539,8 @@
* TODO: This should be combined with config_use_hfa_for_provisioning and implemented as an enum
* (NONE, HFA, OTASP).
*/
- public static final String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
+ public static final String KEY_USE_OTASP_FOR_PROVISIONING_BOOL =
+ "use_otasp_for_provisioning_bool";
/** Display carrier settings menu if true */
public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
@@ -562,25 +565,26 @@
* available the user cannot use voicemail. This flag allows the user to edit the voicemail
* number in such cases, and is false by default.
*/
- public static final String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL= "editable_voicemail_number_bool";
+ public static final String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL =
+ "editable_voicemail_number_bool";
/**
* Determine whether the voicemail notification is persistent in the notification bar. If true,
* the voicemail notifications cannot be dismissed from the notification bar.
*/
- public static final String
- KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool";
+ public static final String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL =
+ "voicemail_notification_persistent_bool";
/** For IMS video over LTE calls, determines whether video pause signalling is supported. */
- public static final String
- KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL = "support_pause_ims_video_calls_bool";
+ public static final String KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL =
+ "support_pause_ims_video_calls_bool";
/**
* Disables dialing "*228" (OTASP provisioning) on CDMA carriers where it is not supported or is
* potentially harmful by locking the SIM to 3G.
*/
- public static final String
- KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
+ public static final String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL =
+ "disable_cdma_activation_code_bool";
/**
* List of network type constants which support only a single data connection at a time.
@@ -588,8 +592,8 @@
* @see TelephonyManager NETWORK_TYPE_*
* @see #KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY
*/
- public static final String
- KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
+ public static final String KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY =
+ "only_single_dc_allowed_int_array";
/**
* Only apply if {@link #KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY} specifies the network types that
@@ -604,15 +608,15 @@
* Override the platform's notion of a network operator being considered roaming.
* Value is string array of MCCMNCs to be considered roaming for 3GPP RATs.
*/
- public static final String
- KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY = "gsm_roaming_networks_string_array";
+ public static final String KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY =
+ "gsm_roaming_networks_string_array";
/**
* Override the platform's notion of a network operator being considered not roaming.
* Value is string array of MCCMNCs to be considered not roaming for 3GPP RATs.
*/
- public static final String
- KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY = "gsm_nonroaming_networks_string_array";
+ public static final String KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY =
+ "gsm_nonroaming_networks_string_array";
/**
* The package name containing the ImsService that will be bound to the telephony framework to
@@ -622,6 +626,7 @@
* {@link #KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING} instead to configure these values
* separately. If any of those values are not empty, they will override this value.
*/
+ @Deprecated
public static final String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING =
"config_ims_package_override_string";
@@ -668,7 +673,7 @@
/**
* Override the platform's notion of a network operator being considered non roaming.
- * If true all networks are considered as home network a.k.a non-roaming. When false,
+ * If true all networks are considered as home network a.k.a. non-roaming. When false,
* the 2 pairs of CMDA and GSM roaming/non-roaming arrays are consulted.
*
* @see #KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY
@@ -703,8 +708,7 @@
* <li>3: {@link #USSD_OVER_IMS_ONLY} </li>
* </ul>
*/
- public static final String KEY_CARRIER_USSD_METHOD_INT =
- "carrier_ussd_method_int";
+ public static final String KEY_CARRIER_USSD_METHOD_INT = "carrier_ussd_method_int";
/**
* Flag specifying whether to show an alert dialog for 5G disable when the user disables VoLTE.
@@ -735,8 +739,7 @@
* downgrading the call in the process.
* @hide
*/
- public static final String KEY_ALLOW_MERGING_RTT_CALLS_BOOL =
- "allow_merging_rtt_calls_bool";
+ public static final String KEY_ALLOW_MERGING_RTT_CALLS_BOOL = "allow_merging_rtt_calls_bool";
/**
* Flag specifying whether the carrier wants to notify the user when a VT call has been handed
@@ -797,7 +800,7 @@
/**
* When {@code true}, changes to the mobile data enabled switch will not cause the VT
- * registration state to change. That is, turning on or off mobile data will not cause VT to be
+ * registration state to change. That is, turning on or off mobile data will not cause VT to be
* enabled or disabled.
* When {@code false}, disabling mobile data will cause VT to be de-registered.
*/
@@ -820,7 +823,8 @@
* carrier provisioning. If false: hard disabled. If true: then depends on carrier
* provisioning, availability etc.
*/
- public static final String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
+ public static final String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL =
+ "carrier_wfc_ims_available_bool";
/**
* Flag specifying whether Cross SIM over IMS should be available for carrier.
@@ -860,8 +864,8 @@
"international_roaming_dial_string_replace_string_array";
/**
- * Flag specifying whether WFC over IMS supports the "wifi only" option. If false, the wifi
- * calling settings will not include an option for "wifi only". If true, the wifi calling
+ * Flag specifying whether WFC over IMS supports the "wifi only" option. If false, the wifi
+ * calling settings will not include an option for "wifi only". If true, the wifi calling
* settings will include an option for "wifi only"
* <p>
* By default, it is assumed that WFC supports "wifi only".
@@ -904,7 +908,7 @@
/**
* Flag indicating whether failed calls due to no service should prompt the user to enable
- * WIFI calling. When {@code true}, if the user attempts to establish a call when there is no
+ * WIFI calling. When {@code true}, if the user attempts to establish a call when there is no
* service available, they are connected to WIFI, and WIFI calling is disabled, a different
* call failure message will be used to encourage the user to enable WIFI calling.
* @hide
@@ -930,8 +934,8 @@
* {@link Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE}
*/
@Deprecated
- public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
- = "carrier_volte_provisioning_required_bool";
+ public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL =
+ "carrier_volte_provisioning_required_bool";
/**
* Flag indicating whether or not the IMS MmTel UT capability requires carrier provisioning
@@ -974,22 +978,22 @@
* As of now, Verizon is the only carrier enforcing this dependency in their
* WFC awareness and activation requirements.
*/
- public static final String KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL
- = "carrier_volte_override_wfc_provisioning_bool";
+ public static final String KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL =
+ "carrier_volte_override_wfc_provisioning_bool";
/**
* Override the device's configuration for the cellular data service to use for this SIM card.
* @hide
*/
- public static final String KEY_CARRIER_DATA_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING
- = "carrier_data_service_wwan_package_override_string";
+ public static final String KEY_CARRIER_DATA_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING =
+ "carrier_data_service_wwan_package_override_string";
/**
* Override the device's configuration for the IWLAN data service to use for this SIM card.
* @hide
*/
- public static final String KEY_CARRIER_DATA_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING
- = "carrier_data_service_wlan_package_override_string";
+ public static final String KEY_CARRIER_DATA_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING =
+ "carrier_data_service_wlan_package_override_string";
/**
* Override the device's configuration for the cellular data service class to use
@@ -1008,8 +1012,8 @@
"carrier_data_service_wlan_class_override_string";
/** Flag specifying whether VoLTE TTY is supported. */
- public static final String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL
- = "carrier_volte_tty_supported_bool";
+ public static final String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL =
+ "carrier_volte_tty_supported_bool";
/** Flag specifying whether VoWIFI TTY is supported.
* @hide
@@ -1021,37 +1025,37 @@
* Flag specifying whether IMS service can be turned off. If false then the service will not be
* turned-off completely, but individual features can be disabled.
*/
- public static final String KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL
- = "carrier_allow_turnoff_ims_bool";
+ public static final String KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL =
+ "carrier_allow_turnoff_ims_bool";
/**
* Flag specifying whether Generic Bootstrapping Architecture capable SIM is required for IMS.
*/
- public static final String KEY_CARRIER_IMS_GBA_REQUIRED_BOOL
- = "carrier_ims_gba_required_bool";
+ public static final String KEY_CARRIER_IMS_GBA_REQUIRED_BOOL =
+ "carrier_ims_gba_required_bool";
/**
- * Flag specifying whether IMS instant lettering is available for the carrier. {@code True} if
+ * Flag specifying whether IMS instant lettering is available for the carrier. {@code True} if
* instant lettering is available for the carrier, {@code false} otherwise.
*/
public static final String KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL =
"carrier_instant_lettering_available_bool";
- /*
+ /**
* Flag specifying whether IMS should be the first phone attempted for E911 even if the
* phone is not in service.
*/
- public static final String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL
- = "carrier_use_ims_first_for_emergency_bool";
+ public static final String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL =
+ "carrier_use_ims_first_for_emergency_bool";
/**
* When {@code true}, the determination of whether to place a call as an emergency call will be
* based on the known {@link android.telephony.emergency.EmergencyNumber}s for the SIM on which
- * the call is being placed. In a dual SIM scenario, if Sim A has the emergency numbers
+ * the call is being placed. In a dual SIM scenario, if Sim A has the emergency numbers
* 123, 456 and Sim B has the emergency numbers 789, and the user places a call on SIM A to 789,
* it will not be treated as an emergency call in this case.
* When {@code false}, the determination is based on the emergency numbers from all device SIMs,
- * regardless of which SIM the call is being placed on. If Sim A has the emergency numbers
+ * regardless of which SIM the call is being placed on. If Sim A has the emergency numbers
* 123, 456 and Sim B has the emergency numbers 789, and the user places a call on SIM A to 789,
* the call will be dialed as an emergency number, but with an unspecified routing.
* @hide
@@ -1062,7 +1066,7 @@
/**
* When IMS instant lettering is available for a carrier (see
* {@link #KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL}), determines the list of characters
- * which may not be contained in messages. Should be specified as a regular expression suitable
+ * which may not be contained in messages. Should be specified as a regular expression suitable
* for use with {@link String#matches(String)}.
*/
public static final String KEY_CARRIER_INSTANT_LETTERING_INVALID_CHARS_STRING =
@@ -1071,8 +1075,8 @@
/**
* When IMS instant lettering is available for a carrier (see
* {@link #KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL}), determines a list of characters which
- * must be escaped with a backslash '\' character. Should be specified as a string containing
- * the characters to be escaped. For example to escape quote and backslash the string would be
+ * must be escaped with a backslash '\' character. Should be specified as a string containing
+ * the characters to be escaped. For example to escape quote and backslash the string would be
* a quote and a backslash.
*/
public static final String KEY_CARRIER_INSTANT_LETTERING_ESCAPED_CHARS_STRING =
@@ -1081,10 +1085,10 @@
/**
* When IMS instant lettering is available for a carrier (see
* {@link #KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL}), determines the character encoding
- * which will be used when determining the length of messages. Used in the InCall UI to limit
- * the number of characters the user may type. If empty-string, the instant lettering
- * message size limit will be enforced on a 1:1 basis. That is, each character will count
- * towards the messages size limit as a single bye. If a character encoding is specified, the
+ * which will be used when determining the length of messages. Used in the InCall UI to limit
+ * the number of characters the user may type. If empty-string, the instant lettering
+ * message size limit will be enforced on a 1:1 basis. That is, each character will count
+ * towards the messages size limit as a single byte. If a character encoding is specified, the
* message size limit will be based on the number of bytes in the message per the specified
* encoding.
*/
@@ -1093,7 +1097,7 @@
/**
* When IMS instant lettering is available for a carrier (see
- * {@link #KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL}), the length limit for messages. Used
+ * {@link #KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL}), the length limit for messages. Used
* in the InCall UI to ensure the user cannot enter more characters than allowed by the carrier.
* See also {@link #KEY_CARRIER_INSTANT_LETTERING_ENCODING_STRING} for more information on how
* the length of the message is calculated.
@@ -1114,7 +1118,8 @@
* manager can control and route outgoing and incoming phone calls, even if they're placed
* using another connection service (PSTN, for example).
*/
- public static final String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
+ public static final String KEY_DEFAULT_SIM_CALL_MANAGER_STRING =
+ "default_sim_call_manager_string";
/**
* The default flag specifying whether ETWS/CMAS test setting is forcibly disabled in
@@ -1217,8 +1222,7 @@
* CDMA carrier ERI (Enhanced Roaming Indicator) file name
* @hide
*/
- public static final String KEY_CARRIER_ERI_FILE_NAME_STRING =
- "carrier_eri_file_name_string";
+ public static final String KEY_CARRIER_ERI_FILE_NAME_STRING = "carrier_eri_file_name_string";
/* The following 3 fields are related to carrier visual voicemail. */
@@ -1242,13 +1246,12 @@
* Whether cellular data is required to access visual voicemail.
*/
public static final String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL =
- "vvm_cellular_data_required_bool";
+ "vvm_cellular_data_required_bool";
/**
* The default OMTP visual voicemail client prefix to use. Defaulted to "//VVM"
*/
- public static final String KEY_VVM_CLIENT_PREFIX_STRING =
- "vvm_client_prefix_string";
+ public static final String KEY_VVM_CLIENT_PREFIX_STRING = "vvm_client_prefix_string";
/**
* Whether to use SSL to connect to the visual voicemail IMAP server. Defaulted to false.
@@ -1273,8 +1276,7 @@
* <p>This is for carriers that does not support VVM deactivation so voicemail can continue to
* function without the data cost.
*/
- public static final String KEY_VVM_LEGACY_MODE_ENABLED_BOOL =
- "vvm_legacy_mode_enabled_bool";
+ public static final String KEY_VVM_LEGACY_MODE_ENABLED_BOOL = "vvm_legacy_mode_enabled_bool";
/**
* Whether to prefetch audio data on new voicemail arrival, defaulted to true.
@@ -1288,7 +1290,8 @@
* @deprecated use {@link #KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY}.
*/
@Deprecated
- public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
+ public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING =
+ "carrier_vvm_package_name_string";
/**
* A list of the carrier's visual voicemail app package names to ensure that dialer visual
@@ -1307,7 +1310,7 @@
* Status screen. The default value is true.
*/
public static final String KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL =
- "show_signal_strength_in_sim_status_bool";
+ "show_signal_strength_in_sim_status_bool";
/**
* Flag specifying if we should interpret all signal strength as one bar higher
@@ -1386,9 +1389,8 @@
public static final String KEY_IGNORE_RTT_MODE_SETTING_BOOL =
"ignore_rtt_mode_setting_bool";
-
/**
- * Determines whether adhoc conference calls are supported by a carrier. When {@code true},
+ * Determines whether adhoc conference calls are supported by a carrier. When {@code true},
* adhoc conference calling is supported, {@code false otherwise}.
*/
public static final String KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL =
@@ -1396,14 +1398,14 @@
/**
* Determines whether conference participants can be added to existing call to form an adhoc
- * conference call (in contrast to merging calls to form a conference). When {@code true},
+ * conference call (in contrast to merging calls to form a conference). When {@code true},
* adding conference participants to existing call is supported, {@code false otherwise}.
*/
public static final String KEY_SUPPORT_ADD_CONFERENCE_PARTICIPANTS_BOOL =
"support_add_conference_participants_bool";
/**
- * Determines whether conference calls are supported by a carrier. When {@code true},
+ * Determines whether conference calls are supported by a carrier. When {@code true},
* conference calling is supported, {@code false otherwise}.
*/
public static final String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
@@ -1411,7 +1413,7 @@
/**
* Determines whether a maximum size limit for IMS conference calls is enforced on the device.
* When {@code true}, IMS conference calls will be limited to at most
- * {@link #KEY_IMS_CONFERENCE_SIZE_LIMIT_INT} participants. When {@code false}, no attempt is
+ * {@link #KEY_IMS_CONFERENCE_SIZE_LIMIT_INT} participants. When {@code false}, no attempt is
* made to limit the number of participants in a conference (the carrier will raise an error
* when an attempt is made to merge too many participants into a conference).
* <p>
@@ -1425,14 +1427,14 @@
/**
* Determines the maximum number of participants the carrier supports for a conference call.
- * This number is exclusive of the current device. A conference between 3 devices, for example,
+ * This number is exclusive of the current device. A conference between 3 devices, for example,
* would have a size limit of 2 participants.
* Enforced when {@link #KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL} is {@code true}.
*/
public static final String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int";
/**
- * Determines whether manage IMS conference calls is supported by a carrier. When {@code true},
+ * Determines whether manage IMS conference calls is supported by a carrier. When {@code true},
* manage IMS conference call is supported, {@code false otherwise}.
* @hide
*/
@@ -1455,7 +1457,7 @@
* and B and C are considered the conference peers.
* <p>
* When {@code true}, the conference peer will display the conference state if it receives
- * conference event package data from the network. When {@code false}, the conference peer will
+ * conference event package data from the network. When {@code false}, the conference peer will
* ignore conference event package data received from the network.
* @hide
*/
@@ -1473,7 +1475,7 @@
/**
* Indicates whether the carrier supports the negotiations of RFC8285 compliant RTP header
- * extensions supported on a call during the Session Description Protocol (SDP). This option
+ * extensions supported on a call during the Session Description Protocol (SDP). This option
* is only used when {@link #KEY_SUPPORTS_DEVICE_TO_DEVICE_COMMUNICATION_USING_RTP_BOOL} is
* {@code true}.
* <p>
@@ -1503,7 +1505,7 @@
"display_hd_audio_property_bool";
/**
- * Determines whether IMS conference calls are supported by a carrier. When {@code true},
+ * Determines whether IMS conference calls are supported by a carrier. When {@code true},
* IMS conference calling is supported, {@code false} otherwise.
* @hide
*/
@@ -1512,9 +1514,9 @@
/**
* Determines whether the device will locally disconnect an IMS conference when the participant
- * count drops to zero. When {@code true}, it is assumed the carrier does NOT disconnect a
+ * count drops to zero. When {@code true}, it is assumed the carrier does NOT disconnect a
* conference when the participant count drops to zero and that the device must do this by
- * disconnecting the conference locally. When {@code false}, it is assumed that the carrier
+ * disconnecting the conference locally. When {@code false}, it is assumed that the carrier
* is responsible for disconnecting the conference when there are no longer any participants
* present.
* <p>
@@ -1530,8 +1532,8 @@
"local_disconnect_empty_ims_conference_bool";
/**
- * Determines whether video conference calls are supported by a carrier. When {@code true},
- * video calls can be merged into conference calls, {@code false} otherwiwse.
+ * Determines whether video conference calls are supported by a carrier. When {@code true},
+ * video calls can be merged into conference calls, {@code false} otherwise.
* <p>
* Note: even if video conference calls are not supported, audio calls may be merged into a
* conference if {@link #KEY_SUPPORT_CONFERENCE_CALL_BOOL} is {@code true}.
@@ -1568,7 +1570,8 @@
/**
* Determine whether preferred network type can be shown.
*/
- public static final String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool";
+ public static final String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL =
+ "hide_preferred_network_type_bool";
/**
* String array for package names that need to be enabled for this carrier.
@@ -1800,20 +1803,20 @@
public static final String KEY_SIM_COUNTRY_ISO_OVERRIDE_STRING =
"sim_country_iso_override_string";
- /**
- * The Component Name of a carrier-provided CallScreeningService implementation. Telecom will
- * bind to {@link android.telecom.CallScreeningService} for ALL incoming calls and provide
- * the carrier
- * CallScreeningService with the opportunity to allow or block calls.
- * <p>
- * The String includes the package name/the class name.
- * Example:
- * <item>com.android.carrier/com.android.carrier.callscreeningserviceimpl</item>
- * <p>
- * Using {@link ComponentName#flattenToString()} to convert a ComponentName object to String.
- * Using {@link ComponentName#unflattenFromString(String)} to convert a String object to a
- * ComponentName.
- */
+ /**
+ * The Component Name of a carrier-provided CallScreeningService implementation. Telecom will
+ * bind to {@link android.telecom.CallScreeningService} for ALL incoming calls and provide
+ * the carrier
+ * CallScreeningService with the opportunity to allow or block calls.
+ * <p>
+ * The String includes the package name/the class name.
+ * Example:
+ * <item>com.android.carrier/com.android.carrier.callscreeningserviceimpl</item>
+ * <p>
+ * Using {@link ComponentName#flattenToString()} to convert a ComponentName object to String.
+ * Using {@link ComponentName#unflattenFromString(String)} to convert a String object to a
+ * ComponentName.
+ */
public static final String KEY_CARRIER_CALL_SCREENING_APP_STRING = "call_screening_app";
/**
@@ -1925,20 +1928,20 @@
"broadcast_emergency_call_state_changes_bool";
/**
- * Indicates whether STK LAUNCH_BROWSER command is disabled.
- * If {@code true}, then the browser will not be launched
- * on UI for the LAUNCH_BROWSER STK command.
- * @hide
- */
+ * Indicates whether STK LAUNCH_BROWSER command is disabled.
+ * If {@code true}, then the browser will not be launched
+ * on UI for the LAUNCH_BROWSER STK command.
+ * @hide
+ */
public static final String KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL =
"stk_disable_launch_browser_bool";
/**
- * Boolean indicating if the helper text for STK GET INKEY/INPUT commands with the digit only
- * mode is displayed on the input screen.
- * The helper text is dispayed regardless of the input mode, if {@code false}.
- * @hide
- */
+ * Boolean indicating if the helper text for STK GET INKEY/INPUT commands with the digit only
+ * mode is displayed on the input screen.
+ * The helper text is displayed regardless of the input mode, if {@code false}.
+ * @hide
+ */
public static final String KEY_HIDE_DIGITS_HELPER_TEXT_ON_STK_INPUT_SCREEN_BOOL =
"hide_digits_helper_text_on_stk_input_screen_bool";
@@ -2098,16 +2101,22 @@
public static final String KEY_MMS_ALLOW_ATTACH_AUDIO_BOOL = "allowAttachAudio";
public static final String KEY_MMS_APPEND_TRANSACTION_ID_BOOL = "enabledTransID";
public static final String KEY_MMS_GROUP_MMS_ENABLED_BOOL = "enableGroupMms";
- public static final String KEY_MMS_MMS_DELIVERY_REPORT_ENABLED_BOOL = "enableMMSDeliveryReports";
+ public static final String KEY_MMS_MMS_DELIVERY_REPORT_ENABLED_BOOL =
+ "enableMMSDeliveryReports";
public static final String KEY_MMS_MMS_ENABLED_BOOL = "enabledMMS";
public static final String KEY_MMS_MMS_READ_REPORT_ENABLED_BOOL = "enableMMSReadReports";
public static final String KEY_MMS_MULTIPART_SMS_ENABLED_BOOL = "enableMultipartSMS";
public static final String KEY_MMS_NOTIFY_WAP_MMSC_ENABLED_BOOL = "enabledNotifyWapMMSC";
- public static final String KEY_MMS_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES_BOOL = "sendMultipartSmsAsSeparateMessages";
- public static final String KEY_MMS_SHOW_CELL_BROADCAST_APP_LINKS_BOOL = "config_cellBroadcastAppLinks";
- public static final String KEY_MMS_SMS_DELIVERY_REPORT_ENABLED_BOOL = "enableSMSDeliveryReports";
- public static final String KEY_MMS_SUPPORT_HTTP_CHARSET_HEADER_BOOL = "supportHttpCharsetHeader";
- public static final String KEY_MMS_SUPPORT_MMS_CONTENT_DISPOSITION_BOOL = "supportMmsContentDisposition";
+ public static final String KEY_MMS_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES_BOOL =
+ "sendMultipartSmsAsSeparateMessages";
+ public static final String KEY_MMS_SHOW_CELL_BROADCAST_APP_LINKS_BOOL =
+ "config_cellBroadcastAppLinks";
+ public static final String KEY_MMS_SMS_DELIVERY_REPORT_ENABLED_BOOL =
+ "enableSMSDeliveryReports";
+ public static final String KEY_MMS_SUPPORT_HTTP_CHARSET_HEADER_BOOL =
+ "supportHttpCharsetHeader";
+ public static final String KEY_MMS_SUPPORT_MMS_CONTENT_DISPOSITION_BOOL =
+ "supportMmsContentDisposition";
public static final String KEY_MMS_ALIAS_MAX_CHARS_INT = "aliasMaxChars";
public static final String KEY_MMS_ALIAS_MIN_CHARS_INT = "aliasMinChars";
public static final String KEY_MMS_HTTP_SOCKET_TIMEOUT_INT = "httpSocketTimeout";
@@ -2116,7 +2125,8 @@
public static final String KEY_MMS_MAX_MESSAGE_SIZE_INT = "maxMessageSize";
public static final String KEY_MMS_MESSAGE_TEXT_MAX_SIZE_INT = "maxMessageTextSize";
public static final String KEY_MMS_RECIPIENT_LIMIT_INT = "recipientLimit";
- public static final String KEY_MMS_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD_INT = "smsToMmsTextLengthThreshold";
+ public static final String KEY_MMS_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD_INT =
+ "smsToMmsTextLengthThreshold";
public static final String KEY_MMS_SMS_TO_MMS_TEXT_THRESHOLD_INT = "smsToMmsTextThreshold";
public static final String KEY_MMS_SUBJECT_MAX_LENGTH_INT = "maxSubjectLength";
public static final String KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING = "emailGatewayNumber";
@@ -2145,7 +2155,7 @@
* The flatten {@link android.content.ComponentName componentName} of the activity that can
* setup the device and activate with the network per carrier requirements.
*
- * e.g, com.google.android.carrierPackageName/.CarrierActivityName
+ * e.g., com.google.android.carrierPackageName/.CarrierActivityName
* @hide
*/
@SystemApi
@@ -2286,7 +2296,7 @@
/**
* Determines whether the carrier supports making non-emergency phone calls while the phone is
- * in emergency callback mode. Default value is {@code true}, meaning that non-emergency calls
+ * in emergency callback mode. Default value is {@code true}, meaning that non-emergency calls
* are allowed in emergency callback mode.
*/
public static final String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL =
@@ -2309,7 +2319,7 @@
/**
* Flag indicating whether to allow carrier video calls to emergency numbers.
- * When {@code true}, video calls to emergency numbers will be allowed. When {@code false},
+ * When {@code true}, video calls to emergency numbers will be allowed. When {@code false},
* video calls to emergency numbers will be initiated as audio-only calls instead.
*/
public static final String KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL =
@@ -2337,7 +2347,7 @@
* When presence is supported, the device should use the
* {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE} bit mask and set the
* {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE_VT_CAPABLE} bit to indicate
- * whether each contact supports video calling. The UI is made aware that presence is enabled
+ * whether each contact supports video calling. The UI is made aware that presence is enabled
* via {@link android.telecom.PhoneAccount#CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE}
* and can choose to hide or show the video calling icon based on whether a contact supports
* video.
@@ -2361,7 +2371,7 @@
* contacts emergency services. Platform considers values for below cases:
* 1) 0 <= VALUE <= 604800(one week): the value will be used as the duration directly.
* 2) VALUE > 604800(one week): will use the default value as duration instead.
- * 3) VALUE < 0: block will be disabled forever until user re-eanble block manually,
+ * 3) VALUE < 0: block will be disabled forever until user re-enable block manually,
* the suggested value to disable forever is -1.
* See {@code android.provider.BlockedNumberContract#notifyEmergencyContact(Context)}
* See {@code android.provider.BlockedNumberContract#isBlocked(Context, String)}.
@@ -2391,7 +2401,7 @@
/**
* For carriers which require an empty flash to be sent before sending the normal 3-way calling
- * flash, the duration in milliseconds of the empty flash to send. When {@code 0}, no empty
+ * flash, the duration in milliseconds of the empty flash to send. When {@code 0}, no empty
* flash is sent.
*/
public static final String KEY_CDMA_3WAYCALL_FLASH_DELAY_INT = "cdma_3waycall_flash_delay_int";
@@ -2431,8 +2441,7 @@
* Int indicating the max number length for FDN
* @hide
*/
- public static final String KEY_FDN_NUMBER_LENGTH_LIMIT_INT =
- "fdn_number_length_limit_int";
+ public static final String KEY_FDN_NUMBER_LENGTH_LIMIT_INT = "fdn_number_length_limit_int";
/**
* Report IMEI as device id even if it's a CDMA/LTE phone.
@@ -2444,16 +2453,15 @@
/**
* The families of Radio Access Technologies that will get clustered and ratcheted,
* ie, we will report transitions up within the family, but not down until we change
- * cells. This prevents flapping between base technologies and higher techs that are
+ * cells. This prevents flapping between base technologies and higher techs that are
* granted on demand within the cell.
* @hide
*/
- public static final String KEY_RATCHET_RAT_FAMILIES =
- "ratchet_rat_families";
+ public static final String KEY_RATCHET_RAT_FAMILIES = "ratchet_rat_families";
/**
* Flag indicating whether some telephony logic will treat a call which was formerly a video
- * call as if it is still a video call. When {@code true}:
+ * call as if it is still a video call. When {@code true}:
* <p>
* Logic which will automatically drop a video call which takes place over WIFI when a
* voice call is answered (see {@link #KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL}.
@@ -2465,7 +2473,7 @@
/**
* When {@code true}, if the user is in an ongoing video call over WIFI and answers an incoming
- * audio call, the video call will be disconnected before the audio call is answered. This is
+ * audio call, the video call will be disconnected before the audio call is answered. This is
* in contrast to the usual expected behavior where a foreground video call would be put into
* the background and held when an incoming audio call is answered.
*/
@@ -2475,8 +2483,8 @@
/**
* Flag indicating whether the carrier supports merging wifi calls when VoWIFI is disabled.
* This can happen in the case of a carrier which allows offloading video calls to WIFI
- * separately of whether voice over wifi is enabled. In such a scenario when two video calls
- * are downgraded to voice, they remain over wifi. However, if VoWIFI is disabled, these calls
+ * separately of whether voice over wifi is enabled. In such a scenario when two video calls
+ * are downgraded to voice, they remain over wifi. However, if VoWIFI is disabled, these calls
* cannot be merged.
*/
public static final String KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL =
@@ -2486,9 +2494,9 @@
* Flag indicating whether the carrier supports the Hold command while in an IMS call.
* <p>
* The device configuration value {@code config_device_respects_hold_carrier_config} ultimately
- * controls whether this carrier configuration option is used. Where
- * {@code config_device_respects_hold_carrier_config} is false, the value of the
- * {@link #KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL} carrier configuration option is ignored.
+ * controls whether this carrier configuration option is used.
+ * Where {@code config_device_respects_hold_carrier_config} is false, the value of
+ * this carrier configuration is ignored.
* @hide
*/
public static final String KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL = "allow_hold_in_ims_call";
@@ -2543,8 +2551,7 @@
* <p>
* This is {@code true} by default.
*/
- public static final String KEY_ALLOW_HOLD_VIDEO_CALL_BOOL =
- "allow_hold_video_call_bool";
+ public static final String KEY_ALLOW_HOLD_VIDEO_CALL_BOOL = "allow_hold_video_call_bool";
/**
* When true, indicates that the HD audio icon in the in-call screen should not be shown for
@@ -2638,7 +2645,8 @@
* is returned.
* @hide
*/
- public static final String KEY_FILTERED_CNAP_NAMES_STRING_ARRAY = "filtered_cnap_names_string_array";
+ public static final String KEY_FILTERED_CNAP_NAMES_STRING_ARRAY =
+ "filtered_cnap_names_string_array";
/**
* The RCS configuration server URL. This URL is used to initiate RCS provisioning.
@@ -2706,9 +2714,9 @@
"emergency_notification_delay_int";
/**
- * When {@code true}, the carrier allows the user of the
- * {@link TelephonyManager#sendUssdRequest(String, TelephonyManager.UssdResponseCallback,
- * Handler)} API to perform USSD requests. {@code True} by default.
+ * When {@code true}, the carrier allows the user of the {@link
+ * TelephonyManager#sendUssdRequest(String, TelephonyManager.UssdResponseCallback, Handler)}
+ * API to perform USSD requests. {@code True} by default.
* @hide
*/
public static final String KEY_ALLOW_USSD_REQUESTS_VIA_TELEPHONY_MANAGER_BOOL =
@@ -2720,7 +2728,7 @@
* fails.
*/
public static final String KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL =
- "support_3gpp_call_forwarding_while_roaming_bool";
+ "support_3gpp_call_forwarding_while_roaming_bool";
/**
* Boolean indicating whether to display voicemail number as default call forwarding number in
@@ -2786,8 +2794,7 @@
* This setting may be still overridden by explicit user choice. By default,
* {@link #DATA_CYCLE_USE_PLATFORM_DEFAULT} will be used.
*/
- public static final String KEY_MONTHLY_DATA_CYCLE_DAY_INT =
- "monthly_data_cycle_day_int";
+ public static final String KEY_MONTHLY_DATA_CYCLE_DAY_INT = "monthly_data_cycle_day_int";
/**
* When {@link #KEY_MONTHLY_DATA_CYCLE_DAY_INT}, {@link #KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG},
@@ -2833,7 +2840,7 @@
/**
* Controls if the device should automatically warn the user that sim voice & data function
- * might be limited due to dual sim scenario. When set to {@true} display the notification,
+ * might be limited due to dual sim scenario. When set to {@code true} display the notification,
* {@code false} otherwise.
* @hide
*/
@@ -2859,16 +2866,14 @@
* their cellular data limit. When set to {@code false} the carrier is
* expected to have implemented their own notification mechanism. {@code true} by default.
*/
- public static final String KEY_DATA_LIMIT_NOTIFICATION_BOOL =
- "data_limit_notification_bool";
+ public static final String KEY_DATA_LIMIT_NOTIFICATION_BOOL = "data_limit_notification_bool";
/**
* Controls if the device should automatically notify the user when rapid
* cellular data usage is observed. When set to {@code false} the carrier is
- * expected to have implemented their own notification mechanism. {@code true} by default.
+ * expected to have implemented their own notification mechanism. {@code true} by default.
*/
- public static final String KEY_DATA_RAPID_NOTIFICATION_BOOL =
- "data_rapid_notification_bool";
+ public static final String KEY_DATA_RAPID_NOTIFICATION_BOOL = "data_rapid_notification_bool";
/**
* Offset to be reduced from rsrp threshold while calculating signal strength level.
@@ -2901,8 +2906,7 @@
* "nrarfcn2_start-nrarfcn2_end" ... }
* @hide
*/
- public static final String KEY_BOOSTED_NRARFCNS_STRING_ARRAY =
- "boosted_nrarfcns_string_array";
+ public static final String KEY_BOOSTED_NRARFCNS_STRING_ARRAY = "boosted_nrarfcns_string_array";
/**
* Determine whether to use only RSRP for the number of LTE signal bars.
@@ -3009,8 +3013,8 @@
* is set, the default value 2 is used.
* @hide
*/
- public static final String
- KEY_NGRAN_SSRSRP_HYSTERESIS_DB_INT = "ngran_ssrsrp_hysteresis_db_int";
+ public static final String KEY_NGRAN_SSRSRP_HYSTERESIS_DB_INT =
+ "ngran_ssrsrp_hysteresis_db_int";
/**
* An interval in dB for {@link SignalThresholdInfo#SIGNAL_MEASUREMENT_TYPE_SSRSRQ} measurement
@@ -3018,10 +3022,10 @@
*
* <p>The default value is 2 and the minimum allowed value is 0. If no value or negative value
* is set, the default value 2 is used.
- *@hide
+ * @hide
*/
- public static final String
- KEY_NGRAN_SSRSRQ_HYSTERESIS_DB_INT = "ngran_ssrsrq_hysteresis_db_int";
+ public static final String KEY_NGRAN_SSRSRQ_HYSTERESIS_DB_INT =
+ "ngran_ssrsrq_hysteresis_db_int";
/**
* An interval in dB for {@link SignalThresholdInfo#SIGNAL_MEASUREMENT_TYPE_SSSINR} measurement
@@ -3031,8 +3035,8 @@
* is set, the default value 2 is used.
* @hide
*/
- public static final String
- KEY_NGRAN_SSSINR_HYSTERESIS_DB_INT = "ngran_sssinr_hysteresis_db_int";
+ public static final String KEY_NGRAN_SSSINR_HYSTERESIS_DB_INT =
+ "ngran_sssinr_hysteresis_db_int";
/**
* Bit-field integer to determine whether to use SS reference signal received power (SSRSRP),
@@ -3120,8 +3124,7 @@
* A match on this supersedes a match on {@link #KEY_NON_ROAMING_OPERATOR_STRING_ARRAY}.
* @hide
*/
- public static final String KEY_ROAMING_OPERATOR_STRING_ARRAY =
- "roaming_operator_string_array";
+ public static final String KEY_ROAMING_OPERATOR_STRING_ARRAY = "roaming_operator_string_array";
/**
* URL from which the proto containing the public key of the Carrier used for
@@ -3190,7 +3193,7 @@
* Boolean flag indicating whether the carrier supports TTY.
* <p>
* Note that {@link #KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL} controls availability of TTY over
- * VoLTE; if {@link #KEY_TTY_SUPPORTED_BOOL} is disabled, then
+ * VoLTE; if this carrier configuration is disabled, then
* {@link #KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL} is also implicitly disabled.
* <p>
* {@link TelecomManager#isTtySupported()} should be used to determine if a device supports TTY,
@@ -3314,11 +3317,11 @@
public static final String KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL =
"check_pricing_with_carrier_data_roaming_bool";
- /**
- * Determines whether we should show a notification when the phone established a data
- * connection in roaming network, to warn users about possible roaming charges.
- * @hide
- */
+ /**
+ * Determines whether we should show a notification when the phone established a data
+ * connection in roaming network, to warn users about possible roaming charges.
+ * @hide
+ */
public static final String KEY_SHOW_DATA_CONNECTED_ROAMING_NOTIFICATION_BOOL =
"show_data_connected_roaming_notification";
@@ -3333,8 +3336,7 @@
* these boundaries is considered invalid.
* @hide
*/
- public static final String KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY =
- "lte_rsrp_thresholds_int_array";
+ public static final String KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY = "lte_rsrp_thresholds_int_array";
/**
* A list of 4 customized LTE Reference Signal Received Quality (RSRQ) thresholds.
@@ -3351,8 +3353,7 @@
* This key is considered invalid if the format is violated. If the key is invalid or
* not configured, a default value set will apply.
*/
- public static final String KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY =
- "lte_rsrq_thresholds_int_array";
+ public static final String KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY = "lte_rsrq_thresholds_int_array";
/**
* A list of 4 customized LTE Reference Signal Signal to Noise Ratio (RSSNR) thresholds.
@@ -3378,8 +3379,7 @@
* is set, the default value 2 is used.
* @hide
*/
- public static final String
- KEY_EUTRAN_RSRP_HYSTERESIS_DB_INT = "eutran_rsrp_hysteresis_db_int";
+ public static final String KEY_EUTRAN_RSRP_HYSTERESIS_DB_INT = "eutran_rsrp_hysteresis_db_int";
/**
* An interval in dB for {@link SignalThresholdInfo#SIGNAL_MEASUREMENT_TYPE_RSRQ} measurement
@@ -3399,8 +3399,8 @@
* is set, the default value 2 is used.
* @hide
*/
- public static final String
- KEY_EUTRAN_RSSNR_HYSTERESIS_DB_INT = "eutran_rssnr_hysteresis_db_int";
+ public static final String KEY_EUTRAN_RSSNR_HYSTERESIS_DB_INT =
+ "eutran_rssnr_hysteresis_db_int";
/**
* Decides when clients try to bind to iwlan network service, which package name will
@@ -3449,6 +3449,7 @@
*/
public static final String KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_CLASS_OVERRIDE_STRING =
"carrier_qualified_networks_service_class_override_string";
+
/**
* A list of 4 WCDMA RSCP thresholds above which a signal level is considered POOR,
* MODERATE, GOOD, or EXCELLENT, to be used in SignalStrength reporting.
@@ -3524,7 +3525,7 @@
/**
* Specifies a carrier-defined {@link android.telecom.CallRedirectionService} which Telecom
- * will bind to for outgoing calls. An empty string indicates that no carrier-defined
+ * will bind to for outgoing calls. An empty string indicates that no carrier-defined
* {@link android.telecom.CallRedirectionService} is specified.
*/
public static final String KEY_CALL_REDIRECTION_SERVICE_COMPONENT_NAME_STRING =
@@ -3824,7 +3825,7 @@
* This configuration allows the framework to use user data communication to detect Idle state,
* and this is used on the 5G icon.
*
- * There is a new way for for RRC state detection at Android 12. If
+ * There is a new way for RRC state detection at Android 12. If
* {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported}(
* {@link TelephonyManager#CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED}) returns true,
* then framework can use PHYSICAL_CHANNEL_CONFIG for RRC state detection. Based on this
@@ -3980,8 +3981,7 @@
* FQDN (Fully Qualified Domain Name) of the SM-DP+ (e.g., smdp.gsma.com) restricted to the
* Alphanumeric mode character set defined in table 5 of ISO/IEC 18004 excluding '$'.
*/
- public static final String KEY_SMDP_SERVER_ADDRESS_STRING =
- "smdp_server_address_string";
+ public static final String KEY_SMDP_SERVER_ADDRESS_STRING = "smdp_server_address_string";
/**
* This timer value is used in the eSIM Exponential Backoff download retry algorithm.
@@ -4032,7 +4032,7 @@
public static final String KEY_OPPORTUNISTIC_ESIM_DOWNLOAD_VIA_WIFI_ONLY_BOOL =
"opportunistic_esim_download_via_wifi_only_bool";
-/**
+ /**
* Controls RSRP threshold, in dBm, at which OpportunisticNetworkService will decide whether
* the opportunistic network is good enough for internet data.
*
@@ -4126,6 +4126,7 @@
*/
public static final String KEY_OPPORTUNISTIC_NETWORK_PING_PONG_TIME_LONG =
"opportunistic_network_ping_pong_time_long";
+
/**
* Controls back off time in milli seconds for switching back to
* opportunistic subscription. This time will be added to
@@ -4345,7 +4346,7 @@
* If opportunistic network is determined as out of service or below
* {@link #KEY_EXIT_THRESHOLD_SS_RSRP_INT} or
* {@link #KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE} within
- * {@link #KEY_5G_PING_PONG_TIME_LONG} of switching to opportunistic network,
+ * the time specified by this carrier config of switching to opportunistic network,
* it will be determined as ping pong situation by system app or 1st party app.
*
* @hide
@@ -4401,29 +4402,30 @@
public static final String KEY_ENABLE_4G_OPPORTUNISTIC_NETWORK_SCAN_BOOL =
"enabled_4g_opportunistic_network_scan_bool";
- /**
- * Only relevant when the device supports opportunistic networks but does not support
- * simultaneuous 5G+5G. Controls how long, in milliseconds, to wait before opportunistic network
- * goes out of service before switching the 5G capability back to primary stack. The idea of
- * waiting a few seconds is to minimize the calling of the expensive capability switching
- * operation in the case where CBRS goes back into service shortly after going out of it.
- *
- * @hide
- */
- public static final String KEY_TIME_TO_SWITCH_BACK_TO_PRIMARY_IF_OPPORTUNISTIC_OOS_LONG =
+ /**
+ * Only relevant when the device supports opportunistic networks but does not support
+ * simultaneous 5G+5G. Controls how long, in milliseconds, to wait before opportunistic network
+ * goes out of service before switching the 5G capability back to primary stack. The idea of
+ * waiting a few seconds is to minimize the calling of the expensive capability switching
+ * operation in the case where CBRS goes back into service shortly after going out of it.
+ *
+ * @hide
+ */
+ public static final String KEY_TIME_TO_SWITCH_BACK_TO_PRIMARY_IF_OPPORTUNISTIC_OOS_LONG =
"time_to_switch_back_to_primary_if_opportunistic_oos_long";
- /**
- * Only relevant when the device supports opportunistic networks but does not support
- * simultaneuous 5G+5G. Controls how long, in milliseconds, after 5G capability has switched back
- * to primary stack due to opportunistic network being OOS. The idea is to minimizing the
- * 'ping-ponging' effect where device is constantly witching capability back and forth between
- * primary and opportunistic stack.
- *
- * @hide
- */
- public static final String KEY_OPPORTUNISTIC_TIME_TO_SCAN_AFTER_CAPABILITY_SWITCH_TO_PRIMARY_LONG
- = "opportunistic_time_to_scan_after_capability_switch_to_primary_long";
+ /**
+ * Only relevant when the device supports opportunistic networks but does not support
+ * simultaneous 5G+5G. Controls how long, in milliseconds, after 5G capability has switched back
+ * to primary stack due to opportunistic network being OOS. The idea is to minimizing the
+ * 'ping-ponging' effect where device is constantly witching capability back and forth between
+ * primary and opportunistic stack.
+ *
+ * @hide
+ */
+ public static final String
+ KEY_OPPORTUNISTIC_TIME_TO_SCAN_AFTER_CAPABILITY_SWITCH_TO_PRIMARY_LONG =
+ "opportunistic_time_to_scan_after_capability_switch_to_primary_long";
/**
* Indicates zero or more emergency number prefix(es), because some carrier requires
@@ -4550,8 +4552,7 @@
* @hide
*/
@SystemApi
- public static final String KEY_GBA_UA_SECURITY_PROTOCOL_INT =
- "gba_ua_security_protocol_int";
+ public static final String KEY_GBA_UA_SECURITY_PROTOCOL_INT = "gba_ua_security_protocol_int";
/**
* An integer representing the cipher suite to be used when building the
@@ -4561,8 +4562,7 @@
* @hide
*/
@SystemApi
- public static final String KEY_GBA_UA_TLS_CIPHER_SUITE_INT =
- "gba_ua_tls_cipher_suite_int";
+ public static final String KEY_GBA_UA_TLS_CIPHER_SUITE_INT = "gba_ua_tls_cipher_suite_int";
/**
* The data stall recovery timers array in milliseconds, each element is the delay before
@@ -4721,7 +4721,6 @@
*/
public static final int SUPL_EMERGENCY_MODE_TYPE_DP_ONLY = 2;
-
/**
* Determine whether current lpp_mode used for E-911 needs to be kept persistently.
* {@code false} - not keeping the lpp_mode means using default configuration of gps.conf
@@ -4839,8 +4838,8 @@
* The default value for this configuration is {@link #SUPL_EMERGENCY_MODE_TYPE_CP_ONLY}.
* @hide
*/
- public static final String KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT = KEY_PREFIX
- + "es_supl_control_plane_support_int";
+ public static final String KEY_ES_SUPL_CONTROL_PLANE_SUPPORT_INT =
+ KEY_PREFIX + "es_supl_control_plane_support_int";
/**
* A list of roaming PLMNs where SUPL ES mode does not support a control-plane mechanism to
@@ -4875,13 +4874,14 @@
}
}
- /**
- * An int array containing CDMA enhanced roaming indicator values for Home (non-roaming) network.
- * The default values come from 3GPP2 C.R1001 table 8.1-1.
- * Enhanced Roaming Indicator Number Assignments
- *
- * @hide
- */
+ /**
+ * An int array containing CDMA enhanced roaming indicator values for Home (non-roaming)
+ * network.
+ * The default values come from 3GPP2 C.R1001 table 8.1-1.
+ * Enhanced Roaming Indicator Number Assignments
+ *
+ * @hide
+ */
public static final String KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY =
"cdma_enhanced_roaming_indicator_for_home_network_int_array";
@@ -4893,7 +4893,7 @@
/**
* Indicates use 3GPP application to replace 3GPP2 application even if it's a CDMA/CDMA-LTE
- * phone, becasue some carriers's CSIM application is present but not supported.
+ * phone, because some carriers' CSIM application is present but not supported.
* @hide
*/
public static final String KEY_USE_USIM_BOOL = "use_usim_bool";
@@ -4956,8 +4956,7 @@
* {@see SubscriptionInfo#getUsageSetting}
*
*/
- public static final String KEY_CELLULAR_USAGE_SETTING_INT =
- "cellular_usage_setting_int";
+ public static final String KEY_CELLULAR_USAGE_SETTING_INT = "cellular_usage_setting_int";
/**
* Data switch validation minimal gap time, in milliseconds.
@@ -5021,7 +5020,7 @@
* "Carrier Provisioning Info" or "Trigger Carrier Provisioning" button clicked.
*
* <p>
- * e.g, com.google.android.carrierPackageName/.CarrierReceiverName
+ * e.g., com.google.android.carrierPackageName/.CarrierReceiverName
*
* @hide
*/
@@ -5061,9 +5060,9 @@
* Capability Exchange (UCE). See RCC.71, section 3 for more information.
* <p>
* If this key's value is set to false, the procedure for RCS contact capability exchange
- * via SIP SUBSCRIBE/NOTIFY will also be disabled internally, and
- * {@link Ims#KEY_ENABLE_PRESENCE_PUBLISH_BOOL} must also be set to false to ensure
- * apps do not improperly think that capability exchange via SIP PUBLISH is enabled.
+ * via SIP SUBSCRIBE/NOTIFY will also be disabled internally, and this key must also be set
+ * to false to ensure apps do not improperly think that capability exchange via SIP PUBLISH
+ * is enabled.
* <p> The default value for this key is {@code false}.
*/
public static final String KEY_ENABLE_PRESENCE_PUBLISH_BOOL =
@@ -5119,7 +5118,6 @@
public static final String KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL =
KEY_PREFIX + "enable_presence_capability_exchange_bool";
-
/**
* Flag indicating whether or not the carrier expects the RCS UCE service to periodically
* refresh the RCS capabilities cache of the user's contacts as well as request the
@@ -5253,7 +5251,7 @@
KEY_PREFIX + "sip_timer_j_millis_int";
/** Specifies the SIP Server default port. */
- public static final String KEY_SIP_SERVER_PORT_NUMBER_INT =
+ public static final String KEY_SIP_SERVER_PORT_NUMBER_INT =
KEY_PREFIX + "sip_server_port_number_int";
/**
@@ -5265,7 +5263,6 @@
/** @hide */
@IntDef({REQUEST_URI_FORMAT_TEL, REQUEST_URI_FORMAT_SIP})
-
public @interface RequestUriFormatType {}
/**
@@ -5312,7 +5309,6 @@
PREFERRED_TRANSPORT_DYNAMIC_UDP_TCP,
PREFERRED_TRANSPORT_TLS
})
-
public @interface PreferredTransportType {}
/** Preferred Transport is always UDP. */
@@ -5393,7 +5389,6 @@
/** @hide */
@IntDef({IPSEC_AUTHENTICATION_ALGORITHM_HMAC_MD5, IPSEC_AUTHENTICATION_ALGORITHM_HMAC_SHA1})
-
public @interface IpsecAuthenticationAlgorithmType {}
/** IPSec Authentication algorithm is HMAC-MD5. see Annex H of TS 33.203 */
@@ -5418,7 +5413,6 @@
IPSEC_ENCRYPTION_ALGORITHM_DES_EDE3_CBC,
IPSEC_ENCRYPTION_ALGORITHM_AES_CBC
})
-
public @interface IpsecEncryptionAlgorithmType {}
/** IPSec Encryption algorithm is NULL. see Annex H of TS 33.203 */
@@ -5477,7 +5471,6 @@
GEOLOCATION_PIDF_FOR_NON_EMERGENCY_ON_CELLULAR,
GEOLOCATION_PIDF_FOR_EMERGENCY_ON_CELLULAR
})
-
public @interface GeolocationPidfAllowedType {}
/**
@@ -5571,7 +5564,6 @@
NETWORK_TYPE_HOME,
NETWORK_TYPE_ROAMING
})
-
public @interface NetworkType {}
/** Indicates HOME Network. */
@@ -5588,7 +5580,6 @@
E911_RTCP_INACTIVITY_ON_CONNECTED,
E911_RTP_INACTIVITY_ON_CONNECTED
})
-
public @interface MediaInactivityReason {}
/** RTCP inactivity occurred when call is on HOLD. */
@@ -5634,7 +5625,7 @@
* <li>{@link #KEY_CAPABILITY_TYPE_CALL_COMPOSER_INT_ARRAY}</li>
* </ul>
* <p> The values are defined in
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech}
*
* changing mmtel_requires_provisioning_bundle requires changes to
* carrier_volte_provisioning_required_bool and vice versa
@@ -5648,10 +5639,10 @@
* is supported.
* @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE
* <p>Possible values are,
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
*/
public static final String KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY =
KEY_PREFIX + "capability_type_voice_int_array";
@@ -5661,10 +5652,10 @@
* is supported.
* @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO
* <p>Possible values are,
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
*/
public static final String KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY =
KEY_PREFIX + "capability_type_video_int_array";
@@ -5674,10 +5665,10 @@
* supplementary services. (IR.92) is supported.
* @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT
* <p>Possible values are,
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
*/
public static final String KEY_CAPABILITY_TYPE_UT_INT_ARRAY =
KEY_PREFIX + "capability_type_ut_int_array";
@@ -5686,10 +5677,10 @@
* List of different RAT technologies on which Provisioning for SMS (IR.92) is supported.
* @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS
* <p>Possible values are,
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
*/
public static final String KEY_CAPABILITY_TYPE_SMS_INT_ARRAY =
KEY_PREFIX + "capability_type_sms_int_array";
@@ -5699,10 +5690,10 @@
* (section 2.4 of RCC.20) is supported.
* @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_CALL_COMPOSER
* <p>Possible values are,
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
*/
public static final String KEY_CAPABILITY_TYPE_CALL_COMPOSER_INT_ARRAY =
KEY_PREFIX + "capability_type_call_composer_int_array";
@@ -5718,7 +5709,7 @@
* <li>{@link #KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY}</li>
* </ul>
* <p> The values are defined in
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech}
*/
public static final String KEY_RCS_REQUIRES_PROVISIONING_BUNDLE =
KEY_PREFIX + "rcs_requires_provisioning_bundle";
@@ -5729,10 +5720,10 @@
* If not set, this RcsFeature should not service capability requests.
* @see RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE
* <p>Possible values are,
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
*/
public static final String KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY =
KEY_PREFIX + "capability_type_options_uce_int_array";
@@ -5744,10 +5735,10 @@
* requests using presence.
* @see RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE
* <p>Possible values are,
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
- * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+ * {@link ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
*/
public static final String KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY =
KEY_PREFIX + "capability_type_presence_uce_int_array";
@@ -5760,7 +5751,7 @@
defaults.putBoolean(KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
defaults.putBoolean(KEY_ENABLE_PRESENCE_PUBLISH_BOOL, false);
defaults.putStringArray(KEY_PUBLISH_SERVICE_DESC_FEATURE_TAG_MAP_OVERRIDE_STRING_ARRAY,
- new String[] {});
+ new String[0]);
defaults.putBoolean(KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL, false);
defaults.putBoolean(KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL, false);
defaults.putBoolean(KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL, false);
@@ -5885,7 +5876,7 @@
* <p>If {@code false}: hard disabled.
* If {@code true}: then depends on availability, etc.
*/
- public static final String KEY_CARRIER_VOLTE_ROAMING_AVAILABLE_BOOL =
+ public static final String KEY_CARRIER_VOLTE_ROAMING_AVAILABLE_BOOL =
KEY_PREFIX + "carrier_volte_roaming_available_bool";
/**
@@ -5896,7 +5887,7 @@
* will be sent in the dialed string in the SIP:INVITE.
* If {@code false}, *67 and *82 will be removed.
*/
- public static final String KEY_INCLUDE_CALLER_ID_SERVICE_CODES_IN_SIP_INVITE_BOOL =
+ public static final String KEY_INCLUDE_CALLER_ID_SERVICE_CODES_IN_SIP_INVITE_BOOL =
KEY_PREFIX + "include_caller_id_service_codes_in_sip_invite_bool";
/**
@@ -5940,7 +5931,6 @@
SESSION_REFRESHER_TYPE_UAC,
SESSION_REFRESHER_TYPE_UAS
})
-
public @interface SessionRefresherType {}
/**
@@ -5982,14 +5972,12 @@
public static final String KEY_SESSION_REFRESHER_TYPE_INT =
KEY_PREFIX + "session_refresher_type_int";
-
/** @hide */
@IntDef({
SESSION_PRIVACY_TYPE_HEADER,
SESSION_PRIVACY_TYPE_NONE,
SESSION_PRIVACY_TYPE_ID
})
-
public @interface SessionPrivacyType {}
/**
@@ -6027,7 +6015,7 @@
* If {@code true}, SIP 18x responses (other than SIP 183 response)
* are sent reliably.
*/
- public static final String KEY_PRACK_SUPPORTED_FOR_18X_BOOL =
+ public static final String KEY_PRACK_SUPPORTED_FOR_18X_BOOL =
KEY_PREFIX + "prack_supported_for_18x_bool";
/** @hide */
@@ -6035,7 +6023,6 @@
CONFERENCE_SUBSCRIBE_TYPE_IN_DIALOG,
CONFERENCE_SUBSCRIBE_TYPE_OUT_OF_DIALOG
})
-
public @interface ConferenceSubscribeType {}
/**
@@ -6056,7 +6043,7 @@
/**
* This is used to specify whether the SIP SUBSCRIBE to conference state events,
- * is sent in or out of the SIP INVITE dialog between the UE and the
+ * is sent in or out of the SIP INVITE dialog between the UE and the
* conference server.
*
* <p>Reference: IR.92 Section 2.3.3.
@@ -6081,7 +6068,7 @@
*
* <p>Reference: 3GPP TS 24.229
*/
- public static final String KEY_VOICE_QOS_PRECONDITION_SUPPORTED_BOOL =
+ public static final String KEY_VOICE_QOS_PRECONDITION_SUPPORTED_BOOL =
KEY_PREFIX + "voice_qos_precondition_supported_bool";
/**
@@ -6089,7 +6076,7 @@
*
* <p>If {@code true}: voice packets can be sent on default bearer. {@code false} otherwise.
*/
- public static final String KEY_VOICE_ON_DEFAULT_BEARER_SUPPORTED_BOOL =
+ public static final String KEY_VOICE_ON_DEFAULT_BEARER_SUPPORTED_BOOL =
KEY_PREFIX + "voice_on_default_bearer_supported_bool";
/**
@@ -6111,7 +6098,6 @@
PREALERTING_SRVCC_SUPPORT,
MIDCALL_SRVCC_SUPPORT
})
-
public @interface SrvccType {}
/**
@@ -6209,7 +6195,6 @@
SESSION_REFRESH_METHOD_INVITE,
SESSION_REFRESH_METHOD_UPDATE_PREFERRED
})
-
public @interface SessionRefreshMethod {}
/**
@@ -6244,7 +6229,7 @@
* determination of the originating party identity in OIP.
* {@code false} otherwise.
*/
- public static final String KEY_OIP_SOURCE_FROM_HEADER_BOOL =
+ public static final String KEY_OIP_SOURCE_FROM_HEADER_BOOL =
KEY_PREFIX + "oip_source_from_header_bool";
/**
@@ -6332,7 +6317,7 @@
* <p>Payload type is an integer in dynamic payload type range 96-127
* as per RFC RFC 3551 Section 6.
*/
- public static final String KEY_EVS_PAYLOAD_TYPE_INT_ARRAY =
+ public static final String KEY_EVS_PAYLOAD_TYPE_INT_ARRAY =
KEY_PREFIX + "evs_payload_type_int_array";
/**
@@ -6341,7 +6326,7 @@
* <p>Payload type is an integer in dynamic payload type range 96-127
* as per RFC RFC 3551 Section 6.
*/
- public static final String KEY_AMRWB_PAYLOAD_TYPE_INT_ARRAY =
+ public static final String KEY_AMRWB_PAYLOAD_TYPE_INT_ARRAY =
KEY_PREFIX + "amrwb_payload_type_int_array";
/**
@@ -6350,7 +6335,7 @@
* <p>Payload type is an integer in dynamic payload type range 96-127
* as per RFC RFC 3551 Section 6.
*/
- public static final String KEY_AMRNB_PAYLOAD_TYPE_INT_ARRAY =
+ public static final String KEY_AMRNB_PAYLOAD_TYPE_INT_ARRAY =
KEY_PREFIX + "amrnb_payload_type_int_array";
/**
@@ -6359,7 +6344,7 @@
* <p>Payload type is an integer in dynamic payload type range 96-127
* as per RFC RFC 3551 Section 6.
*/
- public static final String KEY_DTMFWB_PAYLOAD_TYPE_INT_ARRAY =
+ public static final String KEY_DTMFWB_PAYLOAD_TYPE_INT_ARRAY =
KEY_PREFIX + "dtmfwb_payload_type_int_array";
/**
@@ -6368,7 +6353,7 @@
* <p>Payload type is an integer in dynamic payload type range 96-127
* as per RFC RFC 3551 Section 6.
*/
- public static final String KEY_DTMFNB_PAYLOAD_TYPE_INT_ARRAY =
+ public static final String KEY_DTMFNB_PAYLOAD_TYPE_INT_ARRAY =
KEY_PREFIX + "dtmfnb_payload_type_int_array";
/**
@@ -6385,7 +6370,6 @@
public static final String KEY_VOICE_RTP_PACKET_LOSS_RATE_THRESHOLD_INT =
KEY_PREFIX + "rtp_packet_loss_rate_threshold_int";
-
/**
* This indicates the threshold for RTP jitter value in milliseconds (RFC3550). If measured
* jitter value crosses this, a callback with {@link MediaQualityStatus} will be invoked
@@ -6414,13 +6398,11 @@
public static final String KEY_VOICE_RTP_INACTIVITY_TIME_THRESHOLD_MILLIS_LONG =
KEY_PREFIX + "rtp_inactivity_time_threshold_millis_long";
-
/** @hide */
@IntDef({
BANDWIDTH_EFFICIENT,
OCTET_ALIGNED
})
-
public @interface AmrPayloadFormat {}
/** AMR NB/WB Payload format is bandwidth-efficient. */
@@ -6441,7 +6423,7 @@
*
* <p>Reference: RFC 4867 Section 8.1.
*/
- public static final String KEY_AMR_CODEC_ATTRIBUTE_PAYLOAD_FORMAT_INT =
+ public static final String KEY_AMR_CODEC_ATTRIBUTE_PAYLOAD_FORMAT_INT =
KEY_PREFIX + "amr_codec_attribute_payload_format_int";
/**
@@ -6456,7 +6438,7 @@
* <p>Possible values are subset of,
* [0,1,2,3,4,5,6,7,8] - AMRWB with the modes representing nine speech codec modes
* with bit rates of 6.6, 8.85, 12.65, 14.25, 15.85, 18.25, 19.85, 23.05, 23.85 kbps.
- * [0,1,2,3,4,5,6,7] - AMRNB with the modes representing eight speech codec modes
+ * [0,1,2,3,4,5,6,7] - AMRNB with the modes representing eight speech codec modes
* with bit rates of 4.75, 5.15, 5.90, 6.70, 7.40, 7.95, 10.2, 12.2 kbps.
*
* <p>If value is not specified, then it means device supports all
@@ -6464,7 +6446,7 @@
*
* <p>Reference: RFC 4867 Section 8.1, 3GPP 26.445 A.3.1
*/
- public static final String KEY_AMR_CODEC_ATTRIBUTE_MODESET_INT_ARRAY =
+ public static final String KEY_AMR_CODEC_ATTRIBUTE_MODESET_INT_ARRAY =
KEY_PREFIX + "amr_codec_attribute_modeset_int_array";
/**
@@ -6514,7 +6496,6 @@
EVS_OPERATIONAL_MODE_PRIMARY,
EVS_OPERATIONAL_MODE_AMRWB_IO
})
-
public @interface EvsOperationalMode {}
/** Indicates the EVS primary mode. 3GPP 26.445 Section 3.1 */
@@ -6549,7 +6530,6 @@
EVS_ENCODED_BW_TYPE_WB_SWB,
EVS_ENCODED_BW_TYPE_WB_SWB_FB
})
-
public @interface EvsEncodedBwType {}
/**
@@ -6625,7 +6605,7 @@
*
* <p>Reference: 3GPP 26.441 Table 1.
*/
- public static final String KEY_EVS_CODEC_ATTRIBUTE_BANDWIDTH_INT =
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_BANDWIDTH_INT =
KEY_PREFIX + "evs_codec_attribute_bandwidth_int";
/** @hide */
@@ -6643,7 +6623,6 @@
EVS_PRIMARY_MODE_BITRATE_96_0_KBPS,
EVS_PRIMARY_MODE_BITRATE_128_0_KBPS
})
-
public @interface EvsPrimaryModeBitRate {}
/** EVS primary mode with bitrate 5.9 kbps */
@@ -6709,14 +6688,14 @@
*
* <p>Reference: 3GPP 26.445 Section A.3.1
*/
- public static final String KEY_EVS_CODEC_ATTRIBUTE_BITRATE_INT_ARRAY =
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_BITRATE_INT_ARRAY =
KEY_PREFIX + "evs_codec_attribute_bitrate_int_array";
/**
* Specifies the Channel aware mode (ch-aw-recv) for the receive direction.
* This is applicable for EVS codec.
*
- * <p>Permissible values are -1, 0, 2, 3, 5, and 7.
+ * <p> Permissible values are -1, 0, 2, 3, 5, and 7.
* If this key is not specified, then the behavior is same as value 0
* (channel aware mode disabled).
* <p> If this key is configured, then device is expected to send
@@ -6724,7 +6703,7 @@
*
* <p>Reference: 3GPP TS 26.445 section 4.4.5, 3GPP 26.445 Section A.3.1
*/
- public static final String KEY_EVS_CODEC_ATTRIBUTE_CH_AW_RECV_INT =
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_CH_AW_RECV_INT =
KEY_PREFIX + "evs_codec_attribute_ch_aw_recv_int";
/**
@@ -6745,7 +6724,7 @@
*
* <p>Reference: 3GPP 26.445 Section A.3.1.
*/
- public static final String KEY_EVS_CODEC_ATTRIBUTE_HF_ONLY_INT =
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_HF_ONLY_INT =
KEY_PREFIX + "evs_codec_attribute_hf_only_int";
/**
@@ -6761,7 +6740,7 @@
* will apply.
* <p>Reference: 3GPP TS 26.445 Section A.3.1.
*/
- public static final String KEY_EVS_CODEC_ATTRIBUTE_DTX_BOOL =
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_DTX_BOOL =
KEY_PREFIX + "evs_codec_attribute_dtx_bool";
/**
@@ -6786,7 +6765,7 @@
*
* <p>Reference: RFC 3551
*/
- public static final String KEY_EVS_CODEC_ATTRIBUTE_CHANNELS_INT =
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_CHANNELS_INT =
KEY_PREFIX + "evs_codec_attribute_channels_int";
/**
@@ -6799,7 +6778,7 @@
*
* <p>Reference: 3GPP 26.445 Section A.3.1, 3GPP 26.114 Table 6.2a
*/
- public static final String KEY_EVS_CODEC_ATTRIBUTE_CMR_INT =
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_CMR_INT =
KEY_PREFIX + "codec_attribute_cmr_int";
/**
@@ -6813,7 +6792,7 @@
*
* <p>Reference: RFC 4867 Section 8.1.
*/
- public static final String KEY_CODEC_ATTRIBUTE_MODE_CHANGE_PERIOD_INT =
+ public static final String KEY_CODEC_ATTRIBUTE_MODE_CHANGE_PERIOD_INT =
KEY_PREFIX + "codec_attribute_mode_change_period_int";
/**
@@ -6827,7 +6806,7 @@
*
* <p>Reference: RFC 4867 Section 8.1.
*/
- public static final String KEY_CODEC_ATTRIBUTE_MODE_CHANGE_CAPABILITY_INT =
+ public static final String KEY_CODEC_ATTRIBUTE_MODE_CHANGE_CAPABILITY_INT =
KEY_PREFIX + "codec_attribute_mode_change_capability_int";
/**
@@ -6835,7 +6814,7 @@
* This attribute is applicable for EVS codec in AMR-WB IO mode
* and AMR-WB.
*
- * <p>Possible values are 0, 1. If value is 1, then the sender should only
+ * <p>Possible values are 0, 1. If value is 1, then the sender should only
* perform mode changes to the neighboring modes in the active codec mode set.
* If value is 0, then mode changes between any two modes
* in the active codec mode set is allowed.
@@ -6844,7 +6823,7 @@
*
* <p>Reference: RFC 4867 Section 8.1.
*/
- public static final String KEY_CODEC_ATTRIBUTE_MODE_CHANGE_NEIGHBOR_INT =
+ public static final String KEY_CODEC_ATTRIBUTE_MODE_CHANGE_NEIGHBOR_INT =
KEY_PREFIX + "codec_attribute_mode_change_neighbor_int";
/**
@@ -7008,7 +6987,7 @@
* <p>If {@code true}: SMS over IMS support available.
* {@code false}: otherwise.
*/
- public static final String KEY_SMS_OVER_IMS_SUPPORTED_BOOL =
+ public static final String KEY_SMS_OVER_IMS_SUPPORTED_BOOL =
KEY_PREFIX + "sms_over_ims_supported_bool";
/**
@@ -7018,7 +6997,7 @@
* <p>If {@code true}: allow SMS CSFB in case of SMS over PS failure.
* {@code false} otherwise.
*/
- public static final String KEY_SMS_CSFB_RETRY_ON_FAILURE_BOOL =
+ public static final String KEY_SMS_CSFB_RETRY_ON_FAILURE_BOOL =
KEY_PREFIX + "sms_csfb_retry_on_failure_bool";
/** @hide */
@@ -7026,7 +7005,6 @@
SMS_FORMAT_3GPP,
SMS_FORMAT_3GPP2
})
-
public @interface SmsFormat {}
/** SMS format is 3GPP. */
@@ -7205,7 +7183,7 @@
* <p>If {@code true}: text media can be sent on default bearer.
* {@code false} otherwise.
*/
- public static final String KEY_TEXT_ON_DEFAULT_BEARER_SUPPORTED_BOOL =
+ public static final String KEY_TEXT_ON_DEFAULT_BEARER_SUPPORTED_BOOL =
KEY_PREFIX + "text_on_default_bearer_supported_bool";
/**
@@ -7215,7 +7193,7 @@
* {@code false} otherwise.
* <p>Reference: 3GPP TS 24.229
*/
- public static final String KEY_TEXT_QOS_PRECONDITION_SUPPORTED_BOOL =
+ public static final String KEY_TEXT_QOS_PRECONDITION_SUPPORTED_BOOL =
KEY_PREFIX + "text_qos_precondition_supported_bool";
/**
@@ -7265,14 +7243,14 @@
* <p>Payload type is an integer in dynamic payload type range 96-127
* as per RFC RFC 3551 Section 6.
*/
- public static final String KEY_T140_PAYLOAD_TYPE_INT =
+ public static final String KEY_T140_PAYLOAD_TYPE_INT =
KEY_PREFIX + "t140_payload_type_int";
/** Integer representing payload type for RED/redundancy codec.
* <p>Payload type is an integer in dynamic payload type range 96-127
* as per RFC RFC 3551 Section 6.
*/
- public static final String KEY_RED_PAYLOAD_TYPE_INT =
+ public static final String KEY_RED_PAYLOAD_TYPE_INT =
KEY_PREFIX + "red_payload_type_int";
private static PersistableBundle getDefaults() {
@@ -7321,7 +7299,7 @@
* <p>If {@code true}: Allow UE to retry emergency call on
* IMS PDN if emergency PDN setup failed.{@code false} otherwise.
*/
- public static final String KEY_RETRY_EMERGENCY_ON_IMS_PDN_BOOL =
+ public static final String KEY_RETRY_EMERGENCY_ON_IMS_PDN_BOOL =
KEY_PREFIX + "retry_emergency_on_ims_pdn_bool";
/**
@@ -7331,7 +7309,7 @@
* <p>If {@code true}: Enter ECBM mode after E911 call is ended.
* {@code false} otherwise.
*/
- public static final String KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL =
+ public static final String KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL =
KEY_PREFIX + "emergency_callback_mode_supported_bool";
/**
@@ -7343,7 +7321,7 @@
*
* <p>Reference: 3GPP TS 24.229
*/
- public static final String KEY_EMERGENCY_QOS_PRECONDITION_SUPPORTED_BOOL =
+ public static final String KEY_EMERGENCY_QOS_PRECONDITION_SUPPORTED_BOOL =
KEY_PREFIX + "emergency_qos_precondition_supported_bool";
/**
@@ -7750,7 +7728,7 @@
defaults.putBoolean(KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL, false);
defaults.putBoolean(KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL, false);
defaults.putStringArray(KEY_EMERGENCY_CDMA_PREFERRED_NUMBERS_STRING_ARRAY,
- new String[] {});
+ new String[0]);
return defaults;
}
@@ -7771,7 +7749,7 @@
* <p>If {@code true}: video media can be sent on default bearer.
* {@code false} otherwise.
*/
- public static final String KEY_VIDEO_ON_DEFAULT_BEARER_SUPPORTED_BOOL =
+ public static final String KEY_VIDEO_ON_DEFAULT_BEARER_SUPPORTED_BOOL =
KEY_PREFIX + "video_on_default_bearer_supported_bool";
/**
@@ -7837,7 +7815,7 @@
* {@code false} otherwise.
* <p>Reference: 3GPP TS 24.229
*/
- public static final String KEY_VIDEO_QOS_PRECONDITION_SUPPORTED_BOOL =
+ public static final String KEY_VIDEO_QOS_PRECONDITION_SUPPORTED_BOOL =
KEY_PREFIX + "video_qos_precondition_supported_bool";
/**
@@ -7862,7 +7840,7 @@
* <p>Payload type is an integer in dynamic payload type range 96-127
* as per RFC RFC 3551 Section 6.
*/
- public static final String KEY_H264_PAYLOAD_TYPE_INT_ARRAY =
+ public static final String KEY_H264_PAYLOAD_TYPE_INT_ARRAY =
KEY_PREFIX + "h264_payload_type_int_array";
/**
@@ -7904,7 +7882,7 @@
*
* <p>Reference: RFC 6184 Section 5.4
*/
- public static final String KEY_VIDEO_CODEC_ATTRIBUTE_PACKETIZATION_MODE_INT =
+ public static final String KEY_VIDEO_CODEC_ATTRIBUTE_PACKETIZATION_MODE_INT =
KEY_PREFIX + "video_codec_attribute_packetization_mode_int";
/**
@@ -7918,7 +7896,7 @@
* <UL>
* <p>Reference: RFC 4566 Section 6, 3GPP 26.114 Section 6.2.3.2
*/
- public static final String KEY_VIDEO_CODEC_ATTRIBUTE_FRAME_RATE_INT =
+ public static final String KEY_VIDEO_CODEC_ATTRIBUTE_FRAME_RATE_INT =
KEY_PREFIX + "video_codec_attribute_frame_rate_int";
/**
@@ -7937,7 +7915,7 @@
* <p>Reference: RFC 4566 Section 6, 3GPP 26.114 Section 6.2.3.2
*
*/
- public static final String KEY_VIDEO_CODEC_ATTRIBUTE_RESOLUTION_INT_ARRAY =
+ public static final String KEY_VIDEO_CODEC_ATTRIBUTE_RESOLUTION_INT_ARRAY =
KEY_PREFIX + "video_codec_attribute_resolution_int_array";
/**
@@ -7950,7 +7928,7 @@
*
* <p>Reference: RFC 6184 Section 8.1, ITU-T Recommendation H.264
*/
- public static final String KEY_H264_VIDEO_CODEC_ATTRIBUTE_PROFILE_LEVEL_ID_STRING =
+ public static final String KEY_H264_VIDEO_CODEC_ATTRIBUTE_PROFILE_LEVEL_ID_STRING =
KEY_PREFIX + "h264_video_codec_attribute_profile_level_id_string";
private static PersistableBundle getDefaults() {
@@ -8018,7 +7996,7 @@
* List of MDNs for which Geo-location PIDF XML with country info
* needs to included for normal calls involving short code.
*/
- public static final String KEY_PIDF_SHORT_CODE_STRING_ARRAY =
+ public static final String KEY_PIDF_SHORT_CODE_STRING_ARRAY =
KEY_PREFIX + "pidf_short_code_string_array";
/**
@@ -8028,15 +8006,14 @@
* <p>If {@code false}: E911 call uses IMS PDN for E911 call over VoWiFi.
* If {@code true}: E911 call uses Emergency PDN for E911 call over VoWiFi.
*/
- public static final String KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL =
+ public static final String KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL =
KEY_PREFIX + "emergency_call_over_emergency_pdn_bool";
-
private static PersistableBundle getDefaults() {
PersistableBundle defaults = new PersistableBundle();
defaults.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, false);
- defaults.putStringArray(KEY_PIDF_SHORT_CODE_STRING_ARRAY, new String[] {});
+ defaults.putStringArray(KEY_PIDF_SHORT_CODE_STRING_ARRAY, new String[0]);
return defaults;
}
@@ -8083,7 +8060,7 @@
* If XCAP over UT fails, return error.
* if {@code true}, Use CSFB if XCAP over UT fails.
*/
- public static final String KEY_USE_CSFB_ON_XCAP_OVER_UT_FAILURE_BOOL =
+ public static final String KEY_USE_CSFB_ON_XCAP_OVER_UT_FAILURE_BOOL =
KEY_PREFIX + "use_csfb_on_xcap_over_ut_failure_bool";
/**
@@ -8095,7 +8072,7 @@
*
* Reference: IR.92 Section 5.5.1
*/
- public static final String KEY_UT_SUPPORTED_WHEN_PS_DATA_OFF_BOOL =
+ public static final String KEY_UT_SUPPORTED_WHEN_PS_DATA_OFF_BOOL =
KEY_PREFIX + "ut_supported_when_ps_data_off_bool";
/**
@@ -8105,7 +8082,7 @@
* <p>If {@code true}: Support Available.{@code false}: Otherwise.
* Reference: 3GPP 24.390.
*/
- public static final String KEY_NETWORK_INITIATED_USSD_OVER_IMS_SUPPORTED_BOOL =
+ public static final String KEY_NETWORK_INITIATED_USSD_OVER_IMS_SUPPORTED_BOOL =
KEY_PREFIX + "network_initiated_ussd_over_ims_supported_bool";
/**
@@ -8189,7 +8166,6 @@
SUPPLEMENTARY_SERVICE_CB_ACR,
SUPPLEMENTARY_SERVICE_CB_BIL
})
-
public @interface SsType {}
/** Communication Waiting (CW) support as per 3GPP 24.615. */
@@ -8428,7 +8404,6 @@
CALL_WAITING_SYNC_FIRST_CHANGE,
CALL_WAITING_SYNC_IMS_ONLY
})
-
public @interface CwSyncType {}
/**
@@ -8553,9 +8528,7 @@
SUPPLEMENTARY_SERVICE_CB_ACR,
SUPPLEMENTARY_SERVICE_CB_BIL
});
- defaults.putIntArray(
- KEY_UT_TERMINAL_BASED_SERVICES_INT_ARRAY,
- new int[] {});
+ defaults.putIntArray(KEY_UT_TERMINAL_BASED_SERVICES_INT_ARRAY, new int[0]);
defaults.putIntArray(
KEY_XCAP_OVER_UT_SUPPORTED_RATS_INT_ARRAY,
@@ -8739,7 +8712,6 @@
public static final String KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY =
KEY_PREFIX + "ike_session_encryption_aes_cbc_key_size_int_array";
-
/**
* List of supported key sizes for AES Counter (CTR) encryption mode of IKE session.
* Possible values -
@@ -8874,7 +8846,7 @@
public static final int EPDG_ADDRESS_PCO = 2;
/** Use cellular location to chose epdg server */
public static final int EPDG_ADDRESS_CELLULAR_LOC = 3;
- /* Use Visited Country FQDN rule*/
+ /** Use Visited Country FQDN rule*/
public static final int EPDG_ADDRESS_VISITED_COUNTRY = 4;
/** @hide */
@@ -9012,7 +8984,7 @@
defaults.putIntArray(
KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY,
new int[] {EPDG_ADDRESS_PLMN, EPDG_ADDRESS_STATIC});
- defaults.putStringArray(KEY_MCC_MNCS_STRING_ARRAY, new String[] {});
+ defaults.putStringArray(KEY_MCC_MNCS_STRING_ARRAY, new String[0]);
defaults.putInt(KEY_IKE_LOCAL_ID_TYPE_INT, ID_TYPE_RFC822_ADDR);
defaults.putInt(KEY_IKE_REMOTE_ID_TYPE_INT, ID_TYPE_FQDN);
defaults.putBoolean(KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL, false);
@@ -9035,8 +9007,7 @@
* level outside these boundaries is considered invalid.
* @hide
*/
- public static final String KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY =
- "gsm_rssi_thresholds_int_array";
+ public static final String KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY = "gsm_rssi_thresholds_int_array";
/**
* An interval in dB for {@link SignalThresholdInfo#SIGNAL_MEASUREMENT_TYPE_RSSI} measurement
@@ -9054,8 +9025,7 @@
* See Wireless Priority Service from https://www.fcc.gov/general/wireless-priority-service-wps
* @hide
*/
- public static final String KEY_SUPPORT_WPS_OVER_IMS_BOOL =
- "support_wps_over_ims_bool";
+ public static final String KEY_SUPPORT_WPS_OVER_IMS_BOOL = "support_wps_over_ims_bool";
/**
* The two digital number pattern of MMI code which is defined by carrier.
@@ -9103,8 +9073,7 @@
* When true, forwarded number is shown.
* When false, forwarded number is not shown.
*/
- public static final String KEY_SHOW_FORWARDED_NUMBER_BOOL =
- "show_forwarded_number_bool";
+ public static final String KEY_SHOW_FORWARDED_NUMBER_BOOL = "show_forwarded_number_bool";
/**
* The list of originating address of missed incoming call SMS. If the SMS has originator
@@ -9116,7 +9085,6 @@
public static final String KEY_MISSED_INCOMING_CALL_SMS_ORIGINATOR_STRING_ARRAY =
"missed_incoming_call_sms_originator_string_array";
-
/**
* String array of Apn Type configurations.
* The entries should be of form "APN_TYPE_NAME:priority".
@@ -9264,8 +9232,7 @@
*
* @hide
*/
- public static final String KEY_DEFAULT_RTT_MODE_INT =
- "default_rtt_mode_int";
+ public static final String KEY_DEFAULT_RTT_MODE_INT = "default_rtt_mode_int";
/**
* Indicates whether RTT is supported while roaming.
@@ -9291,10 +9258,9 @@
* seamlessly after an unattended reboot.
*
* The device configuration value {@code config_allow_pin_storage_for_unattended_reboot}
- * ultimately controls whether this carrier configuration option is used. Where
- * {@code config_allow_pin_storage_for_unattended_reboot} is false, the value of the
- * {@link #KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL} carrier configuration option is
- * ignored.
+ * ultimately controls whether this carrier configuration option is used. Where
+ * {@code config_allow_pin_storage_for_unattended_reboot} is false, the value of this
+ * carrier configuration is ignored.
*
* @hide
*/
@@ -9572,7 +9538,7 @@
"iwlan_handover_policy_string_array";
/** The default value for every variable. */
- private final static PersistableBundle sDefaults;
+ private static final PersistableBundle sDefaults;
static {
sDefaults = new PersistableBundle();
@@ -9682,17 +9648,17 @@
sDefaults.putBoolean(KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_TETHERING_BOOL, true);
sDefaults.putBoolean(KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL, false);
- sDefaults.putIntArray(KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY, new int[]{});
+ sDefaults.putIntArray(KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY, new int[0]);
sDefaults.putInt(KEY_VOLTE_REPLACEMENT_RAT_INT, 0);
sDefaults.putString(KEY_DEFAULT_SIM_CALL_MANAGER_STRING, "");
sDefaults.putString(KEY_VVM_DESTINATION_NUMBER_STRING, "");
sDefaults.putInt(KEY_VVM_PORT_NUMBER_INT, 0);
sDefaults.putString(KEY_VVM_TYPE_STRING, "");
sDefaults.putBoolean(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL, false);
- sDefaults.putString(KEY_VVM_CLIENT_PREFIX_STRING,"//VVM");
- sDefaults.putBoolean(KEY_VVM_SSL_ENABLED_BOOL,false);
+ sDefaults.putString(KEY_VVM_CLIENT_PREFIX_STRING, "//VVM");
+ sDefaults.putBoolean(KEY_VVM_SSL_ENABLED_BOOL, false);
sDefaults.putStringArray(KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY, null);
- sDefaults.putBoolean(KEY_VVM_LEGACY_MODE_ENABLED_BOOL,false);
+ sDefaults.putBoolean(KEY_VVM_LEGACY_MODE_ENABLED_BOOL, false);
sDefaults.putBoolean(KEY_VVM_PREFETCH_BOOL, true);
sDefaults.putString(KEY_CARRIER_VVM_PACKAGE_NAME_STRING, "");
sDefaults.putStringArray(KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY, null);
@@ -9849,7 +9815,6 @@
sDefaults.putStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_CARRIER_APP_REQUIRED_DURING_SIM_SETUP_BOOL, false);
-
// Default carrier app configurations
sDefaults.putStringArray(KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY,
new String[]{
@@ -9863,9 +9828,10 @@
//6: CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS
//8: CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER
});
- sDefaults.putStringArray(KEY_CARRIER_DEFAULT_ACTIONS_ON_DEFAULT_NETWORK_AVAILABLE, new String[] {
- String.valueOf(false) + ": 7", //7: CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER
- String.valueOf(true) + ": 8" //8: CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER
+ sDefaults.putStringArray(KEY_CARRIER_DEFAULT_ACTIONS_ON_DEFAULT_NETWORK_AVAILABLE,
+ new String[] {
+ false + ": 7", //7: CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER
+ true + ": 8" //8: CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER
});
sDefaults.putStringArray(KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY, null);
@@ -9879,9 +9845,9 @@
// Rat families: {GPRS, EDGE}, {EVDO, EVDO_A, EVDO_B}, {UMTS, HSPA, HSDPA, HSUPA, HSPAP},
// {LTE, LTE_CA}
- // Order is important - lowest precidence first
+ // Order is important - lowest precedence first
sDefaults.putStringArray(KEY_RATCHET_RAT_FAMILIES,
- new String[]{"1,2","7,8,12","3,11,9,10,15","14,19"});
+ new String[]{"1,2", "7,8,12", "3,11,9,10,15", "14,19"});
sDefaults.putBoolean(KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL, false);
sDefaults.putBoolean(KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL, false);
sDefaults.putBoolean(KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL, true);
@@ -9912,8 +9878,7 @@
sDefaults.putBoolean(KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL, false);
sDefaults.putBoolean(KEY_HIDE_PRESET_APN_DETAILS_BOOL, false);
sDefaults.putBoolean(KEY_SHOW_VIDEO_CALL_CHARGES_ALERT_DIALOG_BOOL, false);
- sDefaults.putStringArray(KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY,
- null);
+ sDefaults.putStringArray(KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_SUPPORT_IMS_CALL_FORWARDING_WHILE_ROAMING_BOOL, true);
sDefaults.putInt(KEY_LTE_EARFCNS_RSRP_BOOST_INT, 0);
sDefaults.putStringArray(KEY_BOOSTED_LTE_EARFCNS_STRING_ARRAY, null);
@@ -9991,27 +9956,27 @@
sDefaults.putIntArray(KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY,
// Boundaries: [-120 dBm, -25 dBm]
new int[] {
- -115, /* SIGNAL_STRENGTH_POOR */
+ -115, /* SIGNAL_STRENGTH_POOR */
-105, /* SIGNAL_STRENGTH_MODERATE */
- -95, /* SIGNAL_STRENGTH_GOOD */
- -85 /* SIGNAL_STRENGTH_GREAT */
+ -95, /* SIGNAL_STRENGTH_GOOD */
+ -85 /* SIGNAL_STRENGTH_GREAT */
});
// TODO(b/249896055): On enabling ECNO measurement part for Signal Bar level indication
- // system functionality,below values to be rechecked.
+ // system functionality, below values to be rechecked.
sDefaults.putIntArray(KEY_WCDMA_ECNO_THRESHOLDS_INT_ARRAY,
// Boundaries: [-24 dBm, 1 dBm]
new int[] {
-24, /* SIGNAL_STRENGTH_POOR */
-14, /* SIGNAL_STRENGTH_MODERATE */
- -6, /* SIGNAL_STRENGTH_GOOD */
- 1 /* SIGNAL_STRENGTH_GREAT */
+ -6, /* SIGNAL_STRENGTH_GOOD */
+ 1 /* SIGNAL_STRENGTH_GREAT */
});
sDefaults.putIntArray(KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY,
// Boundaries: [-140 dB, -44 dB]
new int[] {
-110, /* SIGNAL_STRENGTH_POOR */
- -90, /* SIGNAL_STRENGTH_MODERATE */
- -80, /* SIGNAL_STRENGTH_GOOD */
+ -90, /* SIGNAL_STRENGTH_MODERATE */
+ -80, /* SIGNAL_STRENGTH_GOOD */
-65, /* SIGNAL_STRENGTH_GREAT */
});
sDefaults.putIntArray(KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY,
@@ -10019,14 +9984,14 @@
new int[] {
-31, /* SIGNAL_STRENGTH_POOR */
-19, /* SIGNAL_STRENGTH_MODERATE */
- -7, /* SIGNAL_STRENGTH_GOOD */
- 6 /* SIGNAL_STRENGTH_GREAT */
+ -7, /* SIGNAL_STRENGTH_GOOD */
+ 6 /* SIGNAL_STRENGTH_GREAT */
});
sDefaults.putIntArray(KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY,
// Boundaries: [-23 dB, 40 dB]
new int[] {
-5, /* SIGNAL_STRENGTH_POOR */
- 5, /* SIGNAL_STRENGTH_MODERATE */
+ 5, /* SIGNAL_STRENGTH_MODERATE */
15, /* SIGNAL_STRENGTH_GOOD */
30 /* SIGNAL_STRENGTH_GREAT */
});
@@ -10120,8 +10085,7 @@
sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG, 60000);
sDefaults.putBoolean(KEY_ENABLE_4G_OPPORTUNISTIC_NETWORK_SCAN_BOOL, true);
sDefaults.putLong(KEY_TIME_TO_SWITCH_BACK_TO_PRIMARY_IF_OPPORTUNISTIC_OOS_LONG, 60000L);
- sDefaults.putLong(
- KEY_OPPORTUNISTIC_TIME_TO_SCAN_AFTER_CAPABILITY_SWITCH_TO_PRIMARY_LONG,
+ sDefaults.putLong(KEY_OPPORTUNISTIC_TIME_TO_SCAN_AFTER_CAPABILITY_SWITCH_TO_PRIMARY_LONG,
120000L);
sDefaults.putAll(ImsServiceEntitlement.getDefaults());
sDefaults.putAll(Gps.getDefaults());
@@ -10143,7 +10107,7 @@
new int[] {
-107, /* SIGNAL_STRENGTH_POOR */
-103, /* SIGNAL_STRENGTH_MODERATE */
- -97, /* SIGNAL_STRENGTH_GOOD */
+ -97, /* SIGNAL_STRENGTH_GOOD */
-89, /* SIGNAL_STRENGTH_GREAT */
});
sDefaults.putBoolean(KEY_SUPPORT_WPS_OVER_IMS_BOOL, true);
@@ -10235,7 +10199,7 @@
sDefaults.putBoolean(KEY_VONR_SETTING_VISIBILITY_BOOL, true);
sDefaults.putBoolean(KEY_VONR_ENABLED_BOOL, false);
sDefaults.putBoolean(KEY_VONR_ON_BY_DEFAULT_BOOL, true);
- sDefaults.putIntArray(KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY, new int[] {});
+ sDefaults.putIntArray(KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY, new int[0]);
sDefaults.putLong(KEY_PREMIUM_CAPABILITY_NOTIFICATION_DISPLAY_TIMEOUT_MILLIS_LONG,
TimeUnit.MINUTES.toMillis(30));
sDefaults.putLong(KEY_PREMIUM_CAPABILITY_NOTIFICATION_BACKOFF_HYSTERESIS_TIME_MILLIS_LONG,
@@ -10304,7 +10268,6 @@
public static final String KEY_AVOID_5GHZ_WIFI_DIRECT_FOR_LAA_BOOL =
KEY_PREFIX + "avoid_5ghz_wifi_direct_for_laa_bool";
-
private static PersistableBundle getDefaults() {
PersistableBundle defaults = new PersistableBundle();
defaults.putInt(KEY_HOTSPOT_MAX_CLIENT_COUNT, 0);
@@ -10351,8 +10314,7 @@
return loader.getConfigForSubIdWithFeature(subId, mContext.getOpPackageName(),
mContext.getAttributionTag());
} catch (RemoteException ex) {
- Rlog.e(TAG, "Error getting config for subId " + subId + ": "
- + ex.toString());
+ Rlog.e(TAG, "Error getting config for subId " + subId + ": " + ex);
}
return null;
}
@@ -10378,7 +10340,7 @@
* {@link TelephonyManager#hasCarrierPrivileges()}).
*
* @param subId The subscription ID on which the carrier config should be retrieved.
- * @param keys The carrier config keys to retrieve values.
+ * @param keys The carrier config keys to retrieve values.
* @return A {@link PersistableBundle} with key/value mapping for the specified configuration
* on success, or an empty (but never null) bundle on failure (for example, when the calling app
* has no permission).
@@ -10469,8 +10431,7 @@
}
loader.overrideConfig(subscriptionId, overrideValues, persistent);
} catch (RemoteException ex) {
- Rlog.e(TAG, "Error setting config for subId " + subscriptionId + ": "
- + ex.toString());
+ Rlog.e(TAG, "Error setting config for subId " + subscriptionId + ": " + ex);
}
}
@@ -10583,7 +10544,7 @@
}
loader.notifyConfigChangedForSubId(subId);
} catch (RemoteException ex) {
- Rlog.e(TAG, "Error reloading config for subId=" + subId + ": " + ex.toString());
+ Rlog.e(TAG, "Error reloading config for subId=" + subId + ": " + ex);
}
}
@@ -10607,7 +10568,7 @@
}
loader.updateConfigForPhoneId(phoneId, simState);
} catch (RemoteException ex) {
- Rlog.e(TAG, "Error updating config for phoneId=" + phoneId + ": " + ex.toString());
+ Rlog.e(TAG, "Error updating config for phoneId=" + phoneId + ": " + ex);
}
}
@@ -10629,8 +10590,7 @@
}
return loader.getDefaultCarrierServicePackageName();
} catch (RemoteException ex) {
- Rlog.e(TAG, "getDefaultCarrierServicePackageName ICarrierConfigLoader is null"
- + ex.toString());
+ Rlog.e(TAG, "getDefaultCarrierServicePackageName ICarrierConfigLoader is null" + ex);
ex.rethrowAsRuntimeException();
}
return "";
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
index 52ca7a2..75de476 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
@@ -114,6 +114,10 @@
@Test
override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
+ @FlakyTest(bugId = 266730606)
+ @Test
+ override fun entireScreenCovered() = super.entireScreenCovered()
+
companion object {
/**
* Creates the test configurations.
diff --git a/tools/lint/global/Android.bp b/tools/lint/global/Android.bp
index 3756abe..bedb7bd 100644
--- a/tools/lint/global/Android.bp
+++ b/tools/lint/global/Android.bp
@@ -38,12 +38,6 @@
java_test_host {
name: "AndroidGlobalLintCheckerTest",
- // TODO(b/239881504): Since this test was written, Android
- // Lint was updated, and now includes classes that were
- // compiled for java 15. The soong build doesn't support
- // java 15 yet, so we can't compile against "lint". Disable
- // the test until java 15 is supported.
- enabled: false,
srcs: ["checks/src/test/java/**/*.kt"],
static_libs: [
"AndroidGlobalLintChecker",
@@ -53,5 +47,19 @@
],
test_options: {
unit_test: true,
+ tradefed_options: [
+ {
+ // lint bundles in some classes that were built with older versions
+ // of libraries, and no longer load. Since tradefed tries to load
+ // all classes in the jar to look for tests, it crashes loading them.
+ // Exclude these classes from tradefed's search.
+ name: "exclude-paths",
+ value: "org/apache",
+ },
+ {
+ name: "exclude-paths",
+ value: "META-INF",
+ },
+ ],
},
}
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt
index 72de00f..dcfbe95 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt
@@ -29,6 +29,8 @@
const val BINDER_CLASS = "android.os.Binder"
const val IINTERFACE_INTERFACE = "android.os.IInterface"
+const val AIDL_PERMISSION_HELPER_SUFFIX = "_enforcePermission"
+
/**
* If a non java (e.g. c++) backend is enabled, the @EnforcePermission
* annotation cannot be used. At time of writing, the mechanism
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt
index 485765b..25d208d 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionFix.kt
@@ -36,6 +36,7 @@
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.UExpressionList
import org.jetbrains.uast.UIfExpression
+import org.jetbrains.uast.UMethod
import org.jetbrains.uast.UThrowExpression
import org.jetbrains.uast.UastBinaryOperator
import org.jetbrains.uast.evaluateString
@@ -46,29 +47,37 @@
* Helper class that facilitates the creation of lint auto fixes
*/
data class EnforcePermissionFix(
- val locations: List<Location>,
+ val manualCheckLocations: List<Location>,
val permissionNames: List<String>,
val errorLevel: Boolean,
val anyOf: Boolean,
) {
- fun toLintFix(annotationLocation: Location): LintFix {
- val removeFixes = this.locations.map {
- LintFix.create()
- .replace()
- .reformat(true)
- .range(it)
- .with("")
- .autoFix()
- .build()
+ fun toLintFix(context: JavaContext, node: UMethod): LintFix {
+ val methodLocation = context.getLocation(node)
+ val replaceOrRemoveFixes = manualCheckLocations.mapIndexed { index, manualCheckLocation ->
+ if (index == 0) {
+ // Replace the first manual check with a call to the helper method
+ getHelperMethodFix(node, manualCheckLocation, false)
+ } else {
+ // Remove all subsequent manual checks
+ LintFix.create()
+ .replace()
+ .reformat(true)
+ .range(manualCheckLocation)
+ .with("")
+ .autoFix()
+ .build()
+ }
}
+ // Annotate the method with @EnforcePermission(...)
val annotateFix = LintFix.create()
- .annotate(this.annotation)
- .range(annotationLocation)
+ .annotate(annotation)
+ .range(methodLocation)
.autoFix()
.build()
- return LintFix.create().composite(annotateFix, *removeFixes.toTypedArray())
+ return LintFix.create().composite(annotateFix, *replaceOrRemoveFixes.toTypedArray())
}
private val annotation: String
@@ -89,7 +98,50 @@
companion object {
/**
+ * Walks the expressions in a block, looking for simple permission checks.
+ *
+ * As soon as something other than a permission check is encountered, stop looking,
+ * as some other business logic is happening that prevents an automated fix.
+ */
+ fun fromBlockExpression(
+ context: JavaContext,
+ blockExpression: UBlockExpression
+ ): EnforcePermissionFix? {
+ try {
+ val singleFixes = mutableListOf<EnforcePermissionFix>()
+ for (expression in blockExpression.expressions) {
+ val fix = fromExpression(context, expression) ?: break
+ singleFixes.add(fix)
+ }
+ return compose(singleFixes)
+ } catch (e: AnyOfAllOfException) {
+ return null
+ }
+ }
+
+ /**
+ * Conditionally constructs EnforcePermissionFix from any UExpression
+ *
+ * @return EnforcePermissionFix if the expression boils down to a permission check,
+ * else null
+ */
+ fun fromExpression(
+ context: JavaContext,
+ expression: UExpression
+ ): EnforcePermissionFix? {
+ val trimmedExpression = expression.skipParenthesizedExprDown()
+ if (trimmedExpression is UIfExpression) {
+ return fromIfExpression(context, trimmedExpression)
+ }
+ findCallExpression(trimmedExpression)?.let {
+ return fromCallExpression(context, it)
+ }
+ return null
+ }
+
+ /**
* Conditionally constructs EnforcePermissionFix from a UCallExpression
+ *
* @return EnforcePermissionFix if the called method is annotated with @PermissionMethod, else null
*/
fun fromCallExpression(
@@ -111,6 +163,7 @@
/**
* Conditionally constructs EnforcePermissionFix from a UCallExpression
+ *
* @return EnforcePermissionFix IF AND ONLY IF:
* * The condition of the if statement compares the return value of a
* PermissionMethod to one of the PackageManager.PermissionResult values
@@ -172,7 +225,8 @@
}
- fun compose(individuals: List<EnforcePermissionFix>): EnforcePermissionFix {
+ fun compose(individuals: List<EnforcePermissionFix>): EnforcePermissionFix? {
+ if (individuals.isEmpty()) return null
val anyOfs = individuals.filter(EnforcePermissionFix::anyOf)
// anyOf/allOf should be consistent. If we encounter some @PermissionMethods that are anyOf
// and others that aren't, we don't know what to do.
@@ -180,7 +234,7 @@
throw AnyOfAllOfException()
}
return EnforcePermissionFix(
- individuals.flatMap(EnforcePermissionFix::locations),
+ individuals.flatMap(EnforcePermissionFix::manualCheckLocations),
individuals.flatMap(EnforcePermissionFix::permissionNames),
errorLevel = individuals.all(EnforcePermissionFix::errorLevel),
anyOf = anyOfs.isNotEmpty()
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt
index b65c0fc..df13af5 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionHelperDetector.kt
@@ -55,7 +55,7 @@
return
}
- val targetExpression = "${node.name}$HELPER_SUFFIX()"
+ val targetExpression = getHelperMethodCallSourceString(node)
val message =
"Method must start with $targetExpression or super.${node.name}(), if applicable"
@@ -85,22 +85,11 @@
val locationTarget = getLocationTarget(firstExpression)
val expressionLocation = context.getLocation(locationTarget)
- val indent = " ".repeat(expressionLocation.start?.column ?: 0)
-
- val fix = fix()
- .replace()
- .range(expressionLocation)
- .beginning()
- .with("$targetExpression;\n\n$indent")
- .reformat(true)
- .autoFix()
- .build()
-
context.report(
ISSUE_ENFORCE_PERMISSION_HELPER,
context.getLocation(node),
message,
- fix
+ getHelperMethodFix(node, expressionLocation),
)
}
}
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt
index 2239ea1..d41fee3 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt
@@ -17,6 +17,8 @@
package com.google.android.lint.aidl
import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.LintFix
+import com.android.tools.lint.detector.api.Location
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiReferenceList
import org.jetbrains.uast.UMethod
@@ -69,3 +71,26 @@
references != null &&
references.referenceElements.size == 1 &&
references.referenceElements[0].qualifiedName == qualifiedName
+
+fun getHelperMethodCallSourceString(node: UMethod) = "${node.name}$AIDL_PERMISSION_HELPER_SUFFIX()"
+
+fun getHelperMethodFix(
+ node: UMethod,
+ manualCheckLocation: Location,
+ prepend: Boolean = true
+): LintFix {
+ val helperMethodSource = getHelperMethodCallSourceString(node)
+ val indent = " ".repeat(manualCheckLocation.start?.column ?: 0)
+ val newText = "$helperMethodSource;${if (prepend) "\n\n$indent" else ""}"
+
+ val fix = LintFix.create()
+ .replace()
+ .range(manualCheckLocation)
+ .with(newText)
+ .reformat(true)
+ .autoFix()
+
+ if (prepend) fix.beginning()
+
+ return fix.build()
+}
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt
index 11a283a..c7be36e 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetector.kt
@@ -23,19 +23,13 @@
import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
-import com.google.android.lint.findCallExpression
import org.jetbrains.uast.UBlockExpression
-import org.jetbrains.uast.UElement
-import org.jetbrains.uast.UIfExpression
import org.jetbrains.uast.UMethod
-import org.jetbrains.uast.skipParenthesizedExprDown
/**
* Looks for methods implementing generated AIDL interface stubs
* that can have simple permission checks migrated to
* @EnforcePermission annotations
- *
- * TODO: b/242564870 (enable parse and autoFix of .aidl files)
*/
@Suppress("UnstableApiUsage")
class SimpleManualPermissionEnforcementDetector : AidlImplementationDetector() {
@@ -45,8 +39,8 @@
interfaceName: String,
body: UBlockExpression
) {
- val enforcePermissionFix = accumulateSimplePermissionCheckFixes(body, context) ?: return
- val lintFix = enforcePermissionFix.toLintFix(context.getLocation(node))
+ val enforcePermissionFix = EnforcePermissionFix.fromBlockExpression(context, body) ?: return
+ val lintFix = enforcePermissionFix.toLintFix(context, node)
val message =
"$interfaceName permission check ${
if (enforcePermissionFix.errorLevel) "should" else "can"
@@ -54,68 +48,19 @@
val incident = Incident(
ISSUE_SIMPLE_MANUAL_PERMISSION_ENFORCEMENT,
- enforcePermissionFix.locations.last(),
+ enforcePermissionFix.manualCheckLocations.last(),
message,
lintFix
)
- if (enforcePermissionFix.errorLevel) {
- incident.overrideSeverity(Severity.ERROR)
- }
+ // TODO(b/265014041): turn on errors once all code that would cause one is fixed
+ // if (enforcePermissionFix.errorLevel) {
+ // incident.overrideSeverity(Severity.ERROR)
+ // }
context.report(incident)
}
- /**
- * Walk the expressions in the method, looking for simple permission checks.
- *
- * If a single permission check is found at the beginning of the method,
- * this should be migrated to @EnforcePermission(value).
- *
- * If multiple consecutive permission checks are found,
- * these should be migrated to @EnforcePermission(allOf={value1, value2, ...})
- *
- * As soon as something other than a permission check is encountered, stop looking,
- * as some other business logic is happening that prevents an automated fix.
- */
- private fun accumulateSimplePermissionCheckFixes(
- methodBody: UBlockExpression,
- context: JavaContext
- ): EnforcePermissionFix? {
- try {
- val singleFixes = mutableListOf<EnforcePermissionFix>()
- for (expression in methodBody.expressions) {
- val fix = getPermissionCheckFix(
- expression.skipParenthesizedExprDown(),
- context) ?: break
- singleFixes.add(fix)
- }
- return when (singleFixes.size) {
- 0 -> null
- 1 -> singleFixes[0]
- else -> EnforcePermissionFix.compose(singleFixes)
- }
- } catch (e: AnyOfAllOfException) {
- return null
- }
- }
-
-
- /**
- * If an expression boils down to a permission check, return
- * the helper for creating a lint auto fix to @EnforcePermission
- */
- private fun getPermissionCheckFix(startingExpression: UElement?, context: JavaContext):
- EnforcePermissionFix? {
- if (startingExpression is UIfExpression) {
- return EnforcePermissionFix.fromIfExpression(context, startingExpression)
- }
- findCallExpression(startingExpression)?.let {
- return EnforcePermissionFix.fromCallExpression(context, it)
- }
- return null
- }
-
companion object {
private val EXPLANATION = """
@@ -142,7 +87,6 @@
SimpleManualPermissionEnforcementDetector::class.java,
Scope.JAVA_FILE_SCOPE
),
- enabledByDefault = false, // TODO: enable once b/241171714 is resolved
)
}
}
diff --git a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt
index 2ac550b..6b8e72cf 100644
--- a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt
+++ b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/SimpleManualPermissionEnforcementDetectorTest.kt
@@ -51,10 +51,10 @@
.run()
.expect(
"""
- src/Foo.java:7: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:7: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 1 errors, 0 warnings
+ 0 errors, 1 warnings
"""
)
.expectFixDiffs(
@@ -64,6 +64,7 @@
+ @android.annotation.EnforcePermission("android.permission.READ_CONTACTS")
@@ -7 +8
- mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
+ + test_enforcePermission();
"""
)
}
@@ -101,6 +102,7 @@
+ @android.annotation.EnforcePermission("android.permission.READ_CONTACTS")
@@ -7 +8
- mContext.enforceCallingPermission("android.permission.READ_CONTACTS", "foo");
+ + test_enforcePermission();
"""
)
}
@@ -138,6 +140,7 @@
+ @android.annotation.EnforcePermission("android.permission.READ_CONTACTS")
@@ -7 +8
- mContext.checkCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
+ + test_enforcePermission();
"""
)
}
@@ -165,10 +168,10 @@
.run()
.expect(
"""
- src/Foo.java:8: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:8: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
mContext.enforceCallingOrSelfPermission(
^
- 1 errors, 0 warnings
+ 0 errors, 1 warnings
"""
)
.expectFixDiffs(
@@ -179,6 +182,7 @@
@@ -8 +9
- mContext.enforceCallingOrSelfPermission(
- "android.permission.READ_CONTACTS", "foo");
+ + test_enforcePermission();
"""
)
}
@@ -205,19 +209,20 @@
.run()
.expect(
"""
- src/Foo.java:8: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:8: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_CONTACTS, "foo");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 1 errors, 0 warnings
+ 0 errors, 1 warnings
"""
)
.expectFixDiffs(
"""
- Fix for src/Foo.java line 7: Annotate with @EnforcePermission:
+ Fix for src/Foo.java line 8: Annotate with @EnforcePermission:
@@ -6 +6
+ @android.annotation.EnforcePermission("android.permission.READ_CONTACTS")
@@ -8 +9
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.READ_CONTACTS, "foo");
+ + test_enforcePermission();
"""
)
}
@@ -247,10 +252,10 @@
.run()
.expect(
"""
- src/Foo.java:10: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:10: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
mContext.enforceCallingOrSelfPermission(
^
- 1 errors, 0 warnings
+ 0 errors, 1 warnings
"""
)
.expectFixDiffs(
@@ -263,98 +268,101 @@
- "android.permission.READ_CONTACTS", "foo");
- mContext.enforceCallingOrSelfPermission(
- "android.permission.WRITE_CONTACTS", "foo");
+ + test_enforcePermission();
"""
)
}
fun testAllOf_mixedOrSelf_warning() {
lint().files(
- java(
- """
- import android.content.Context;
- import android.test.ITest;
- public class Foo {
- private Context mContext;
- private ITest itest = new ITest.Stub() {
- @Override
- public void test() throws android.os.RemoteException {
- mContext.enforceCallingOrSelfPermission(
- "android.permission.READ_CONTACTS", "foo");
- mContext.enforceCallingPermission(
- "android.permission.WRITE_CONTACTS", "foo");
- }
- };
- }
- """
- ).indented(),
- *stubs
+ java(
+ """
+ import android.content.Context;
+ import android.test.ITest;
+ public class Foo {
+ private Context mContext;
+ private ITest itest = new ITest.Stub() {
+ @Override
+ public void test() throws android.os.RemoteException {
+ mContext.enforceCallingOrSelfPermission(
+ "android.permission.READ_CONTACTS", "foo");
+ mContext.enforceCallingPermission(
+ "android.permission.WRITE_CONTACTS", "foo");
+ }
+ };
+ }
+ """
+ ).indented(),
+ *stubs
)
- .run()
- .expect(
- """
- src/Foo.java:10: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
- mContext.enforceCallingPermission(
- ^
- 0 errors, 1 warnings
- """
- )
- .expectFixDiffs(
- """
- Fix for src/Foo.java line 10: Annotate with @EnforcePermission:
- @@ -6 +6
- + @android.annotation.EnforcePermission(allOf={"android.permission.READ_CONTACTS", "android.permission.WRITE_CONTACTS"})
- @@ -8 +9
- - mContext.enforceCallingOrSelfPermission(
- - "android.permission.READ_CONTACTS", "foo");
- - mContext.enforceCallingPermission(
- - "android.permission.WRITE_CONTACTS", "foo");
- """
- )
+ .run()
+ .expect(
+ """
+ src/Foo.java:10: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ mContext.enforceCallingPermission(
+ ^
+ 0 errors, 1 warnings
+ """
+ )
+ .expectFixDiffs(
+ """
+ Fix for src/Foo.java line 10: Annotate with @EnforcePermission:
+ @@ -6 +6
+ + @android.annotation.EnforcePermission(allOf={"android.permission.READ_CONTACTS", "android.permission.WRITE_CONTACTS"})
+ @@ -8 +9
+ - mContext.enforceCallingOrSelfPermission(
+ - "android.permission.READ_CONTACTS", "foo");
+ - mContext.enforceCallingPermission(
+ - "android.permission.WRITE_CONTACTS", "foo");
+ + test_enforcePermission();
+ """
+ )
}
fun testAllOf_mixedEnforces_warning() {
lint().files(
- java(
- """
- import android.content.Context;
- import android.test.ITest;
- public class Foo {
- private Context mContext;
- private ITest itest = new ITest.Stub() {
- @Override
- public void test() throws android.os.RemoteException {
- mContext.enforceCallingOrSelfPermission(
- "android.permission.READ_CONTACTS", "foo");
- mContext.checkCallingOrSelfPermission(
- "android.permission.WRITE_CONTACTS", "foo");
- }
- };
- }
- """
- ).indented(),
- *stubs
+ java(
+ """
+ import android.content.Context;
+ import android.test.ITest;
+ public class Foo {
+ private Context mContext;
+ private ITest itest = new ITest.Stub() {
+ @Override
+ public void test() throws android.os.RemoteException {
+ mContext.enforceCallingOrSelfPermission(
+ "android.permission.READ_CONTACTS", "foo");
+ mContext.checkCallingOrSelfPermission(
+ "android.permission.WRITE_CONTACTS", "foo");
+ }
+ };
+ }
+ """
+ ).indented(),
+ *stubs
)
- .run()
- .expect(
- """
- src/Foo.java:10: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
- mContext.checkCallingOrSelfPermission(
- ^
- 0 errors, 1 warnings
- """
- )
- .expectFixDiffs(
- """
- Fix for src/Foo.java line 10: Annotate with @EnforcePermission:
- @@ -6 +6
- + @android.annotation.EnforcePermission(allOf={"android.permission.READ_CONTACTS", "android.permission.WRITE_CONTACTS"})
- @@ -8 +9
- - mContext.enforceCallingOrSelfPermission(
- - "android.permission.READ_CONTACTS", "foo");
- - mContext.checkCallingOrSelfPermission(
- - "android.permission.WRITE_CONTACTS", "foo");
- """
- )
+ .run()
+ .expect(
+ """
+ src/Foo.java:10: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ mContext.checkCallingOrSelfPermission(
+ ^
+ 0 errors, 1 warnings
+ """
+ )
+ .expectFixDiffs(
+ """
+ Fix for src/Foo.java line 10: Annotate with @EnforcePermission:
+ @@ -6 +6
+ + @android.annotation.EnforcePermission(allOf={"android.permission.READ_CONTACTS", "android.permission.WRITE_CONTACTS"})
+ @@ -8 +9
+ - mContext.enforceCallingOrSelfPermission(
+ - "android.permission.READ_CONTACTS", "foo");
+ - mContext.checkCallingOrSelfPermission(
+ - "android.permission.WRITE_CONTACTS", "foo");
+ + test_enforcePermission();
+ """
+ )
}
fun testPrecedingExpressions() {
@@ -389,7 +397,7 @@
public class Foo extends ITest.Stub {
private Context mContext;
- @android.content.pm.PermissionMethod(orSelf = true)
+ @android.annotation.PermissionMethod(orSelf = true)
private void helper() {
mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
}
@@ -406,10 +414,10 @@
.run()
.expect(
"""
- src/Foo.java:14: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:14: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
helper();
~~~~~~~~~
- 1 errors, 0 warnings
+ 0 errors, 1 warnings
"""
)
.expectFixDiffs(
@@ -419,6 +427,7 @@
+ @android.annotation.EnforcePermission("android.permission.READ_CONTACTS")
@@ -14 +15
- helper();
+ + test_enforcePermission();
"""
)
}
@@ -433,7 +442,7 @@
public class Foo extends ITest.Stub {
private Context mContext;
- @android.content.pm.PermissionMethod
+ @android.annotation.PermissionMethod
private void helper() {
mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
}
@@ -463,6 +472,7 @@
+ @android.annotation.EnforcePermission("android.permission.READ_CONTACTS")
@@ -14 +15
- helper();
+ + test_enforcePermission();
"""
)
}
@@ -477,7 +487,7 @@
public class Foo extends ITest.Stub {
private Context mContext;
- @android.content.pm.PermissionMethod(orSelf = true)
+ @android.annotation.PermissionMethod(orSelf = true)
private void helper() {
mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
mContext.enforceCallingOrSelfPermission("android.permission.WRITE_CONTACTS", "foo");
@@ -496,10 +506,10 @@
.run()
.expect(
"""
- src/Foo.java:16: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:16: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
mContext.enforceCallingOrSelfPermission("FOO", "foo");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 1 errors, 0 warnings
+ 0 errors, 1 warnings
"""
)
.expectFixDiffs(
@@ -510,6 +520,7 @@
@@ -15 +16
- helper();
- mContext.enforceCallingOrSelfPermission("FOO", "foo");
+ + test_enforcePermission();
"""
)
}
@@ -525,13 +536,13 @@
public class Foo extends ITest.Stub {
private Context mContext;
- @android.content.pm.PermissionMethod(orSelf = true)
+ @android.annotation.PermissionMethod(orSelf = true)
private void helperHelper() {
helper("android.permission.WRITE_CONTACTS");
}
- @android.content.pm.PermissionMethod(orSelf = true)
- private void helper(@android.content.pm.PermissionName String extraPermission) {
+ @android.annotation.PermissionMethod(orSelf = true)
+ private void helper(@android.annotation.PermissionName String extraPermission) {
mContext.enforceCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo");
}
@@ -547,10 +558,10 @@
.run()
.expect(
"""
- src/Foo.java:19: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:19: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
helperHelper();
~~~~~~~~~~~~~~~
- 1 errors, 0 warnings
+ 0 errors, 1 warnings
"""
)
.expectFixDiffs(
@@ -560,6 +571,7 @@
+ @android.annotation.EnforcePermission(allOf={"android.permission.WRITE_CONTACTS", "android.permission.READ_CONTACTS"})
@@ -19 +20
- helperHelper();
+ + test_enforcePermission();
"""
)
}
@@ -587,10 +599,10 @@
.run()
.expect(
"""
- src/Foo.java:7: Error: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ src/Foo.java:7: Warning: ITest permission check should be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
if (mContext.checkCallingOrSelfPermission("android.permission.READ_CONTACTS", "foo")
^
- 1 errors, 0 warnings
+ 0 errors, 1 warnings
"""
)
.expectFixDiffs(
@@ -603,76 +615,106 @@
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("yikes!");
- }
+ + test_enforcePermission();
"""
)
}
fun testIfExpression_orSelfFalse_warning() {
lint().files(
- java(
- """
- import android.content.Context;
- import android.test.ITest;
- public class Foo extends ITest.Stub {
- private Context mContext;
- @Override
- public void test() throws android.os.RemoteException {
- if (mContext.checkCallingPermission("android.permission.READ_CONTACTS", "foo")
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("yikes!");
- }
+ java(
+ """
+ import android.content.Context;
+ import android.test.ITest;
+ public class Foo extends ITest.Stub {
+ private Context mContext;
+ @Override
+ public void test() throws android.os.RemoteException {
+ if (mContext.checkCallingPermission("android.permission.READ_CONTACTS", "foo")
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("yikes!");
}
}
- """
- ).indented(),
- *stubs
+ }
+ """
+ ).indented(),
+ *stubs
)
- .run()
- .expect(
- """
- src/Foo.java:7: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
- if (mContext.checkCallingPermission("android.permission.READ_CONTACTS", "foo")
- ^
- 0 errors, 1 warnings
- """
- )
- .expectFixDiffs(
- """
- Fix for src/Foo.java line 7: Annotate with @EnforcePermission:
- @@ -5 +5
- + @android.annotation.EnforcePermission("android.permission.READ_CONTACTS")
- @@ -7 +8
- - if (mContext.checkCallingPermission("android.permission.READ_CONTACTS", "foo")
- - != PackageManager.PERMISSION_GRANTED) {
- - throw new SecurityException("yikes!");
- - }
- """
- )
+ .run()
+ .expect(
+ """
+ src/Foo.java:7: Warning: ITest permission check can be converted to @EnforcePermission annotation [SimpleManualPermissionEnforcement]
+ if (mContext.checkCallingPermission("android.permission.READ_CONTACTS", "foo")
+ ^
+ 0 errors, 1 warnings
+ """
+ )
+ .expectFixDiffs(
+ """
+ Fix for src/Foo.java line 7: Annotate with @EnforcePermission:
+ @@ -5 +5
+ + @android.annotation.EnforcePermission("android.permission.READ_CONTACTS")
+ @@ -7 +8
+ - if (mContext.checkCallingPermission("android.permission.READ_CONTACTS", "foo")
+ - != PackageManager.PERMISSION_GRANTED) {
+ - throw new SecurityException("yikes!");
+ - }
+ + test_enforcePermission();
+ """
+ )
}
fun testIfExpression_otherSideEffect_ignored() {
lint().files(
- java(
- """
- import android.content.Context;
- import android.test.ITest;
- public class Foo extends ITest.Stub {
- private Context mContext;
- @Override
- public void test() throws android.os.RemoteException {
- if (mContext.checkCallingPermission("android.permission.READ_CONTACTS", "foo")
- != PackageManager.PERMISSION_GRANTED) {
- doSomethingElse();
- throw new SecurityException("yikes!");
- }
+ java(
+ """
+ import android.content.Context;
+ import android.test.ITest;
+ public class Foo extends ITest.Stub {
+ private Context mContext;
+ @Override
+ public void test() throws android.os.RemoteException {
+ if (mContext.checkCallingPermission("android.permission.READ_CONTACTS", "foo")
+ != PackageManager.PERMISSION_GRANTED) {
+ doSomethingElse();
+ throw new SecurityException("yikes!");
}
}
- """
- ).indented(),
- *stubs
+ }
+ """
+ ).indented(),
+ *stubs
)
- .run()
- .expectClean()
+ .run()
+ .expectClean()
+ }
+
+ fun testIfExpression_inlinedWithSideEffect_ignored() {
+ lint().files(
+ java(
+ """
+ import android.content.Context;
+ import android.test.ITest;
+ public class Foo extends ITest.Stub {
+ private Context mContext;
+ @Override
+ public void test() throws android.os.RemoteException {
+ if (somethingElse() && mContext.checkCallingPermission("android.permission.READ_CONTACTS", "foo")
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("yikes!");
+ }
+ }
+
+ private boolean somethingElse() {
+ return true;
+ }
+ }
+ """
+ ).indented(),
+ *stubs
+ )
+ .run()
+ .expectClean()
}
fun testAnyOf_hardCodedAndVarArgs() {
@@ -685,13 +727,13 @@
public class Foo extends ITest.Stub {
private Context mContext;
- @android.content.pm.PermissionMethod(anyOf = true)
+ @android.annotation.PermissionMethod(anyOf = true)
private void helperHelper() {
helper("FOO", "BAR");
}
- @android.content.pm.PermissionMethod(anyOf = true, value = {"BAZ", "BUZZ"})
- private void helper(@android.content.pm.PermissionName String... extraPermissions) {}
+ @android.annotation.PermissionMethod(anyOf = true, value = {"BAZ", "BUZZ"})
+ private void helper(@android.annotation.PermissionName String... extraPermissions) {}
@Override
public void test() throws android.os.RemoteException {
@@ -718,6 +760,7 @@
+ @android.annotation.EnforcePermission(anyOf={"BAZ", "BUZZ", "FOO", "BAR"})
@@ -17 +18
- helperHelper();
+ + test_enforcePermission();
"""
)
}
@@ -733,13 +776,13 @@
public class Foo extends ITest.Stub {
private Context mContext;
- @android.content.pm.PermissionMethod
+ @android.annotation.PermissionMethod
private void allOfhelper() {
mContext.enforceCallingOrSelfPermission("FOO");
mContext.enforceCallingOrSelfPermission("BAR");
}
- @android.content.pm.PermissionMethod(anyOf = true, permissions = {"BAZ", "BUZZ"})
+ @android.annotation.PermissionMethod(anyOf = true, permissions = {"BAZ", "BUZZ"})
private void anyOfHelper() {}
@Override
@@ -761,17 +804,18 @@
java(
"""
import android.content.Context;
- import android.content.pm.PermissionName;import android.test.ITest;
+ import android.annotation.PermissionName;
+ import android.test.ITest;
public class Foo extends ITest.Stub {
private Context mContext;
- @android.content.pm.PermissionMethod(anyOf = true)
+ @android.annotation.PermissionMethod(anyOf = true)
private void anyOfCheck(@PermissionName String... permissions) {
allOfCheck("BAZ", "BUZZ");
}
- @android.content.pm.PermissionMethod
+ @android.annotation.PermissionMethod
private void allOfCheck(@PermissionName String... permissions) {}
@Override
diff --git a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt
index f6e58da..2ec8fdd 100644
--- a/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt
+++ b/tools/lint/global/checks/src/test/java/com/google/android/lint/aidl/Stubs.kt
@@ -5,84 +5,84 @@
val aidlStub: TestFile = java(
"""
- package android.test;
- public interface ITest extends android.os.IInterface {
- public static abstract class Stub extends android.os.Binder implements android.test.ITest {
- protected void test_enforcePermission() throws SecurityException {}
- }
- public void test() throws android.os.RemoteException;
+ package android.test;
+ public interface ITest extends android.os.IInterface {
+ public static abstract class Stub extends android.os.Binder implements android.test.ITest {
+ protected void test_enforcePermission() throws SecurityException {}
}
+ public void test() throws android.os.RemoteException;
+ }
"""
).indented()
val contextStub: TestFile = java(
"""
- package android.content;
- public class Context {
- @android.content.pm.PermissionMethod(orSelf = true)
- public void enforceCallingOrSelfPermission(@android.content.pm.PermissionName String permission, String message) {}
- @android.content.pm.PermissionMethod
- public void enforceCallingPermission(@android.content.pm.PermissionName String permission, String message) {}
- @android.content.pm.PermissionMethod(orSelf = true)
- public int checkCallingOrSelfPermission(@android.content.pm.PermissionName String permission, String message) {}
- @android.content.pm.PermissionMethod
- public int checkCallingPermission(@android.content.pm.PermissionName String permission, String message) {}
- }
+ package android.content;
+ public class Context {
+ @android.annotation.PermissionMethod(orSelf = true)
+ public void enforceCallingOrSelfPermission(@android.annotation.PermissionName String permission, String message) {}
+ @android.annotation.PermissionMethod
+ public void enforceCallingPermission(@android.annotation.PermissionName String permission, String message) {}
+ @android.annotation.PermissionMethod(orSelf = true)
+ public int checkCallingOrSelfPermission(@android.annotation.PermissionName String permission, String message) {}
+ @android.annotation.PermissionMethod
+ public int checkCallingPermission(@android.annotation.PermissionName String permission, String message) {}
+ }
"""
).indented()
val binderStub: TestFile = java(
"""
- package android.os;
- public class Binder {
- public static int getCallingUid() {}
- }
+ package android.os;
+ public class Binder {
+ public static int getCallingUid() {}
+ }
"""
).indented()
val permissionMethodStub: TestFile = java(
-"""
- package android.content.pm;
+ """
+ package android.annotation;
- import static java.lang.annotation.ElementType.METHOD;
- import static java.lang.annotation.RetentionPolicy.CLASS;
+ import static java.lang.annotation.ElementType.METHOD;
+ import static java.lang.annotation.RetentionPolicy.CLASS;
- import java.lang.annotation.Retention;
- import java.lang.annotation.Target;
+ import java.lang.annotation.Retention;
+ import java.lang.annotation.Target;
- @Retention(CLASS)
- @Target({METHOD})
- public @interface PermissionMethod {}
+ @Retention(CLASS)
+ @Target({METHOD})
+ public @interface PermissionMethod {}
"""
).indented()
val permissionNameStub: TestFile = java(
-"""
- package android.content.pm;
+ """
+ package android.annotation;
- import static java.lang.annotation.ElementType.FIELD;
- import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
- import static java.lang.annotation.ElementType.METHOD;
- import static java.lang.annotation.ElementType.PARAMETER;
- import static java.lang.annotation.RetentionPolicy.CLASS;
+ import static java.lang.annotation.ElementType.FIELD;
+ import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
+ import static java.lang.annotation.ElementType.METHOD;
+ import static java.lang.annotation.ElementType.PARAMETER;
+ import static java.lang.annotation.RetentionPolicy.CLASS;
- import java.lang.annotation.Retention;
- import java.lang.annotation.Target;
+ import java.lang.annotation.Retention;
+ import java.lang.annotation.Target;
- @Retention(CLASS)
- @Target({PARAMETER, METHOD, LOCAL_VARIABLE, FIELD})
- public @interface PermissionName {}
+ @Retention(CLASS)
+ @Target({PARAMETER, METHOD, LOCAL_VARIABLE, FIELD})
+ public @interface PermissionName {}
"""
).indented()
val manifestStub: TestFile = java(
"""
- package android;
+ package android;
- public final class Manifest {
- public static final class permission {
- public static final String READ_CONTACTS="android.permission.READ_CONTACTS";
- }
+ public final class Manifest {
+ public static final class permission {
+ public static final String READ_CONTACTS="android.permission.READ_CONTACTS";
}
+ }
""".trimIndent()
)
\ No newline at end of file