Merge "[WIFI] Update instructions for running tests"
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index a0e83da..bb94275 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -144,14 +144,18 @@
public void startTrackingRestrictedJobLocked(JobStatus jobStatus) {
// Don't need to start tracking the job. If the job needed network, it would already be
// tracked.
- updateConstraintsSatisfied(jobStatus);
+ if (jobStatus.hasConnectivityConstraint()) {
+ updateConstraintsSatisfied(jobStatus);
+ }
}
@Override
public void stopTrackingRestrictedJobLocked(JobStatus jobStatus) {
// Shouldn't stop tracking the job here. If the job was tracked, it still needs network,
// even after being unrestricted.
- updateConstraintsSatisfied(jobStatus);
+ if (jobStatus.hasConnectivityConstraint()) {
+ updateConstraintsSatisfied(jobStatus);
+ }
}
/**
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index ac66d1b..d59270c 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -223,7 +223,7 @@
public static final class SeekPoint {
/** A {@link SeekPoint} whose time and byte offset are both set to 0. */
- public static final @NonNull SeekPoint START = new SeekPoint(0, 0);
+ @NonNull public static final SeekPoint START = new SeekPoint(0, 0);
/** The time of the seek point, in microseconds. */
public final long timeUs;
@@ -241,7 +241,8 @@
}
@Override
- public @NonNull String toString() {
+ @NonNull
+ public String toString() {
return "[timeUs=" + timeUs + ", position=" + position + "]";
}
@@ -414,7 +415,8 @@
* @return A new instance.
* @throws IllegalArgumentException If an invalid name is provided.
*/
- public static @NonNull MediaParser createByName(
+ @NonNull
+ public static MediaParser createByName(
@NonNull String name, @NonNull OutputConsumer outputConsumer) {
String[] nameAsArray = new String[] {name};
assertValidNames(nameAsArray);
@@ -431,7 +433,8 @@
* default array of names is used.
* @return A new instance.
*/
- public static @NonNull MediaParser create(
+ @NonNull
+ public static MediaParser create(
@NonNull OutputConsumer outputConsumer, @NonNull String... extractorNames) {
assertValidNames(extractorNames);
if (extractorNames.length == 0) {
@@ -448,7 +451,8 @@
*
* <p>TODO: List which properties are taken into account. E.g. MimeType.
*/
- public static @NonNull List<String> getExtractorNames(@NonNull MediaFormat mediaFormat) {
+ @NonNull
+ public static List<String> getExtractorNames(@NonNull MediaFormat mediaFormat) {
throw new UnsupportedOperationException();
}
@@ -479,7 +483,8 @@
* @return The name of the backing extractor implementation, or null if the backing extractor
* implementation has not yet been selected.
*/
- public @Nullable String getExtractorName() {
+ @Nullable
+ public String getExtractorName() {
return mExtractorName;
}
diff --git a/apex/sdkextensions/framework/Android.bp b/apex/sdkextensions/framework/Android.bp
index dd17473..245a96b 100644
--- a/apex/sdkextensions/framework/Android.bp
+++ b/apex/sdkextensions/framework/Android.bp
@@ -32,6 +32,7 @@
libs: [ "framework-annotations-lib" ],
permitted_packages: [ "android.os.ext" ],
installable: true,
+ plugins: ["java_api_finder"],
visibility: [
"//frameworks/base/apex/sdkextensions",
"//frameworks/base/apex/sdkextensions/testing",
diff --git a/api/current.txt b/api/current.txt
index b3d136d..e614f17 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -12017,6 +12017,7 @@
field public static final String FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING = "android.hardware.camera.capability.manual_post_processing";
field public static final String FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR = "android.hardware.camera.capability.manual_sensor";
field public static final String FEATURE_CAMERA_CAPABILITY_RAW = "android.hardware.camera.capability.raw";
+ field public static final String FEATURE_CAMERA_CONCURRENT = "android.hardware.camera.concurrent";
field public static final String FEATURE_CAMERA_EXTERNAL = "android.hardware.camera.external";
field public static final String FEATURE_CAMERA_FLASH = "android.hardware.camera.flash";
field public static final String FEATURE_CAMERA_FRONT = "android.hardware.camera.front";
@@ -17174,6 +17175,7 @@
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> SCALER_AVAILABLE_MAX_DIGITAL_ZOOM;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> SCALER_AVAILABLE_ROTATE_AND_CROP_MODES;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> SCALER_CROPPING_TYPE;
+ field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.MandatoryStreamCombination[]> SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.MandatoryStreamCombination[]> SCALER_MANDATORY_STREAM_COMBINATIONS;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.StreamConfigurationMap> SCALER_STREAM_CONFIGURATION_MAP;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> SENSOR_AVAILABLE_TEST_PATTERN_MODES;
@@ -17263,6 +17265,8 @@
public final class CameraManager {
method @NonNull public android.hardware.camera2.CameraCharacteristics getCameraCharacteristics(@NonNull String) throws android.hardware.camera2.CameraAccessException;
method @NonNull public String[] getCameraIdList() throws android.hardware.camera2.CameraAccessException;
+ method @NonNull public java.util.Set<java.util.Set<java.lang.String>> getConcurrentStreamingCameraIds() throws android.hardware.camera2.CameraAccessException;
+ method @RequiresPermission(android.Manifest.permission.CAMERA) public boolean isConcurrentSessionConfigurationSupported(@NonNull java.util.Map<java.lang.String,android.hardware.camera2.params.SessionConfiguration>) throws android.hardware.camera2.CameraAccessException;
method @RequiresPermission(android.Manifest.permission.CAMERA) public void openCamera(@NonNull String, @NonNull android.hardware.camera2.CameraDevice.StateCallback, @Nullable android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method @RequiresPermission(android.Manifest.permission.CAMERA) public void openCamera(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraDevice.StateCallback) throws android.hardware.camera2.CameraAccessException;
method public void registerAvailabilityCallback(@NonNull android.hardware.camera2.CameraManager.AvailabilityCallback, @Nullable android.os.Handler);
@@ -45213,6 +45217,7 @@
method public void registerCallback(android.telecom.Call.Callback);
method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
method public void reject(boolean, String);
+ method public void reject(int);
method public void removeExtras(java.util.List<java.lang.String>);
method public void removeExtras(java.lang.String...);
method public void respondToRttRequest(int, boolean);
@@ -45228,6 +45233,8 @@
field public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS = "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
field public static final String EXTRA_SILENT_RINGING_REQUESTED = "android.telecom.extra.SILENT_RINGING_REQUESTED";
field public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS = "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS";
+ field public static final int REJECT_REASON_DECLINED = 1; // 0x1
+ field public static final int REJECT_REASON_UNWANTED = 2; // 0x2
field public static final int STATE_ACTIVE = 4; // 0x4
field public static final int STATE_AUDIO_PROCESSING = 12; // 0xc
field public static final int STATE_CONNECTING = 9; // 0x9
@@ -45495,6 +45502,7 @@
method public void onPostDialContinue(boolean);
method public void onPullExternalCall();
method public void onReject();
+ method public void onReject(int);
method public void onReject(String);
method public void onSeparate();
method public void onShowIncomingCallUi();
diff --git a/api/system-current.txt b/api/system-current.txt
index 82924d7d..cc4b122 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2519,7 +2519,7 @@
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
method public android.util.Pair<float[],float[]> getCurve();
method public float getShortTermModelLowerLuxMultiplier();
- method public long getShortTermModelTimeout();
+ method public long getShortTermModelTimeoutMillis();
method public float getShortTermModelUpperLuxMultiplier();
method public boolean shouldCollectColorSamples();
method public void writeToParcel(android.os.Parcel, int);
@@ -2536,7 +2536,7 @@
method public int getMaxCorrectionsByPackageName();
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setDescription(@Nullable String);
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelLowerLuxMultiplier(@FloatRange(from=0.0f) float);
- method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelTimeout(long);
+ method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelTimeoutMillis(long);
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelUpperLuxMultiplier(@FloatRange(from=0.0f) float);
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShouldCollectColorSamples(boolean);
}
@@ -7571,12 +7571,12 @@
}
public class WifiInfo implements android.os.Parcelable {
- method @Nullable public String getAppPackageName();
- method public double getRxSuccessRate();
+ method public double getLostTxPacketsPerSecond();
+ method @Nullable public String getRequestingPackageName();
+ method public double getRetriedTxPacketsPerSecond();
method public int getScore();
- method public double getTxBadRate();
- method public double getTxRetriesRate();
- method public double getTxSuccessRate();
+ method public double getSuccessfulRxPacketsPerSecond();
+ method public double getSuccessfulTxPacketsPerSecond();
method public boolean isEphemeral();
method public boolean isOsuAp();
method public boolean isPasspointAp();
@@ -7604,7 +7604,6 @@
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void connect(int, @Nullable android.net.wifi.WifiManager.ActionListener);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void disable(int, @Nullable android.net.wifi.WifiManager.ActionListener);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK}) public void disableEphemeralNetwork(@NonNull String);
- method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void enableVerboseLogging(int);
method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void factoryReset();
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void forget(int, @Nullable android.net.wifi.WifiManager.ActionListener);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.util.Pair<android.net.wifi.WifiConfiguration,java.util.Map<java.lang.Integer,java.util.List<android.net.wifi.ScanResult>>>> getAllMatchingWifiConfigs(@NonNull java.util.List<android.net.wifi.ScanResult>);
@@ -7616,7 +7615,6 @@
method @NonNull @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE}) public java.util.Map<android.net.wifi.WifiNetworkSuggestion,java.util.List<android.net.wifi.ScanResult>> getMatchingScanResults(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>, @Nullable java.util.List<android.net.wifi.ScanResult>);
method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE, android.Manifest.permission.READ_WIFI_CREDENTIAL}) public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.SoftApConfiguration getSoftApConfiguration();
- method public int getVerboseLoggingLevel();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void getWifiActivityEnergyInfoAsync(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.OnWifiActivityEnergyInfoListener);
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getWifiApState();
@@ -7626,6 +7624,7 @@
method @Deprecated public boolean isDeviceToDeviceRttSupported();
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public boolean isDualModeSupported();
method public boolean isPortableHotspotSupported();
+ method public boolean isVerboseLoggingEnabled();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled();
method public boolean isWifiScannerSupported();
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerNetworkRequestMatchCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.NetworkRequestMatchCallback);
@@ -7642,6 +7641,7 @@
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setMacRandomizationSettingPasspointEnabled(@NonNull String, boolean);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setMeteredOverridePasspoint(@NonNull String, int);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public boolean setSoftApConfiguration(@NonNull android.net.wifi.SoftApConfiguration);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setVerboseLoggingEnabled(boolean);
method @Deprecated @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public boolean setWifiConnectedNetworkScorer(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.WifiConnectedNetworkScorer);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsConfiguratorInitiator(@NonNull String, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
@@ -8606,9 +8606,6 @@
field public static final int STATUS_SUCCESS = 0; // 0x0
}
- @IntDef(prefix={"STATUS_"}, value={android.os.HwParcel.STATUS_SUCCESS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface HwParcel.Status {
- }
-
public interface IHwBinder {
method public boolean linkToDeath(android.os.IHwBinder.DeathRecipient, long);
method public android.os.IHwInterface queryLocalInterface(String);
@@ -9045,23 +9042,15 @@
}
public final class WifiActivityEnergyInfo implements android.os.Parcelable {
- ctor public WifiActivityEnergyInfo(long, int, long, long, long, long);
+ ctor public WifiActivityEnergyInfo(long, int, @IntRange(from=0) long, @IntRange(from=0) long, @IntRange(from=0) long, @IntRange(from=0) long);
method public int describeContents();
- method public long getControllerEnergyUsedMicroJoules();
- method public long getControllerIdleDurationMillis();
- method public long getControllerRxDurationMillis();
- method public long getControllerScanDurationMillis();
- method public long getControllerTxDurationMillis();
+ method @IntRange(from=0) public long getControllerEnergyUsedMicroJoules();
+ method @IntRange(from=0) public long getControllerIdleDurationMillis();
+ method @IntRange(from=0) public long getControllerRxDurationMillis();
+ method @IntRange(from=0) public long getControllerScanDurationMillis();
+ method @IntRange(from=0) public long getControllerTxDurationMillis();
method public int getStackState();
method public long getTimeSinceBootMillis();
- method public boolean isValid();
- method public void setControllerEnergyUsedMicroJoules(long);
- method public void setControllerIdleDurationMillis(long);
- method public void setControllerRxDurationMillis(long);
- method public void setControllerScanDurationMillis(long);
- method public void setControllerTxDurationMillis(long);
- method public void setStackState(int);
- method public void setTimeSinceBootMillis(long);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.os.connectivity.WifiActivityEnergyInfo> CREATOR;
field public static final int STACK_STATE_INVALID = 0; // 0x0
diff --git a/api/test-current.txt b/api/test-current.txt
index 37b117b..b35bca8 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1091,7 +1091,7 @@
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
method public android.util.Pair<float[],float[]> getCurve();
method public float getShortTermModelLowerLuxMultiplier();
- method public long getShortTermModelTimeout();
+ method public long getShortTermModelTimeoutMillis();
method public float getShortTermModelUpperLuxMultiplier();
method public boolean shouldCollectColorSamples();
method public void writeToParcel(android.os.Parcel, int);
@@ -1108,7 +1108,7 @@
method public int getMaxCorrectionsByPackageName();
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setDescription(@Nullable String);
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelLowerLuxMultiplier(@FloatRange(from=0.0f) float);
- method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelTimeout(long);
+ method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelTimeoutMillis(long);
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShortTermModelUpperLuxMultiplier(@FloatRange(from=0.0f) float);
method @NonNull public android.hardware.display.BrightnessConfiguration.Builder setShouldCollectColorSamples(boolean);
}
@@ -2218,9 +2218,6 @@
field public static final int STATUS_SUCCESS = 0; // 0x0
}
- @IntDef(prefix={"STATUS_"}, value={android.os.HwParcel.STATUS_SUCCESS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface HwParcel.Status {
- }
-
public interface IHwBinder {
method public boolean linkToDeath(android.os.IHwBinder.DeathRecipient, long);
method public android.os.IHwInterface queryLocalInterface(String);
diff --git a/api/test-lint-baseline.txt b/api/test-lint-baseline.txt
index a9c1836..f53548b 100644
--- a/api/test-lint-baseline.txt
+++ b/api/test-lint-baseline.txt
@@ -2451,8 +2451,6 @@
-PublicTypedef: android.os.HwParcel.Status:
-
PublicTypedef: android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability:
PublicTypedef: android.telephony.ims.feature.MmTelFeature.ProcessCallResult:
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index d9d5be6..7011724 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -137,7 +137,7 @@
DaveyOccurred davey_occurred = 58 [(allow_from_any_uid) = true];
OverlayStateChanged overlay_state_changed = 59;
ForegroundServiceStateChanged foreground_service_state_changed = 60;
- CallStateChanged call_state_changed = 61;
+ CallStateChanged call_state_changed = 61 [(module) = "telecom"];
KeyguardStateChanged keyguard_state_changed = 62 [(module) = "sysui"];
KeyguardBouncerStateChanged keyguard_bouncer_state_changed = 63 [(module) = "sysui"];
KeyguardBouncerPasswordEntered keyguard_bouncer_password_entered = 64 [(module) = "sysui"];
@@ -288,8 +288,8 @@
MediametricsNuPlayerReported mediametrics_nuplayer_reported = 199;
MediametricsRecorderReported mediametrics_recorder_reported = 200;
MediametricsDrmManagerReported mediametrics_drmmanager_reported = 201;
- CarPowerStateChanged car_power_state_changed = 203;
- GarageModeInfo garage_mode_info = 204;
+ CarPowerStateChanged car_power_state_changed = 203 [(module) = "car"];
+ GarageModeInfo garage_mode_info = 204 [(module) = "car"];
TestAtomReported test_atom_reported = 205 [(module) = "cts"];
ContentCaptureCallerMismatchReported content_capture_caller_mismatch_reported = 206;
ContentCaptureServiceEvents content_capture_service_events = 207;
@@ -324,7 +324,8 @@
AppCompatibilityChangeReported app_compatibility_change_reported =
228 [(allow_from_any_uid) = true];
PerfettoUploaded perfetto_uploaded = 229 [(module) = "perfetto"];
- VmsClientConnectionStateChanged vms_client_connection_state_changed = 230;
+ VmsClientConnectionStateChanged vms_client_connection_state_changed =
+ 230 [(module) = "car"];
MediaProviderScanEvent media_provider_scan_event = 233 [(module) = "mediaprovider"];
MediaProviderDeletionEvent media_provider_deletion_event = 234 [(module) = "mediaprovider"];
MediaProviderPermissionEvent media_provider_permission_event =
@@ -343,6 +344,10 @@
NotificationChannelModified notification_panel_modified = 246;
IntegrityCheckResultReported integrity_check_result_reported = 247;
IntegrityRulesPushed integrity_rules_pushed = 248;
+ CellBroadcastMessageReported cb_message_reported =
+ 249 [(module) = "cellbroadcast"];
+ CellBroadcastMessageError cb_message_error =
+ 250 [(module) = "cellbroadcast"];
}
// Pulled events will start at field 10000.
@@ -412,7 +417,7 @@
SurfaceflingerStatsGlobalInfo surfaceflinger_stats_global_info = 10062;
SurfaceflingerStatsLayerInfo surfaceflinger_stats_layer_info = 10063;
ProcessMemorySnapshot process_memory_snapshot = 10064;
- VmsClientStats vms_client_stats = 10065;
+ VmsClientStats vms_client_stats = 10065 [(module) = "car"];
NotificationRemoteViews notification_remote_views = 10066;
DangerousPermissionStateSampled dangerous_permission_state_sampled = 10067;
GraphicsStats graphics_stats = 10068;
@@ -8112,3 +8117,55 @@
// identify the rules.
optional string rule_version = 3;
}
+
+/**
+ * Logs when a cell broadcast message is received on the device.
+ *
+ * Logged from CellBroadcastService module:
+ * packages/modules/CellBroadcastService/src/com/android/cellbroadcastservice/
+ */
+message CellBroadcastMessageReported {
+ // The type of Cell Broadcast message
+ enum CbType {
+ UNKNOWN_TYPE = 0;
+ GSM = 1;
+ CDMA = 2;
+ CDMA_SPC = 3;
+ }
+
+ // GSM, CDMA, CDMA-SCP
+ optional CbType type = 1;
+}
+
+/**
+ * Logs when an error occurs while handling a cell broadcast message;
+ *
+ * Logged from CellBroadcastService module:
+ * packages/modules/CellBroadcastService/src/com/android/cellbroadcastservice/
+ */
+message CellBroadcastMessageError {
+ // The type of error raised when trying to handle a cell broadcast message
+ enum ErrorType {
+ UNKNOWN_TYPE = 0;
+ CDMA_DECODING_ERROR = 1;
+ CDMA_SCP_EMPTY = 2;
+ CDMA_SCP_HANDLING_ERROR = 3;
+ GSM_INVALID_HEADER_LENGTH = 4;
+ GSM_UNSUPPORTED_HEADER_MESSAGE_TYPE = 5;
+ GSM_UNSUPPORTED_HEADER_DATA_CODING_SCHEME = 6;
+ GSM_INVALID_PDU = 7;
+ GSM_INVALID_GEO_FENCING_DATA = 8;
+ GSM_UMTS_INVALID_WAC = 9;
+ FAILED_TO_INSERT_TO_DB = 10;
+ UNEXPECTED_GEOMETRY_FROM_FWK = 11;
+ UNEXPECTED_GSM_MESSAGE_TYPE_FROM_FWK = 12;
+ UNEXPECTED_CDMA_MESSAGE_TYPE_FROM_FWK = 13;
+ UNEXPECTED_CDMA_SCP_MESSAGE_TYPE_FROM_FWK = 14;
+ }
+
+ // What kind of error occurred
+ optional ErrorType type = 1;
+
+ // Exception message (or log message) associated with the error (max 1000 chars)
+ optional string exception_message = 2;
+}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 38ffb51..b64c001 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1960,6 +1960,15 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device's main front and back cameras can stream
+ * concurrently as described in {@link
+ * android.hardware.camera2.CameraManager#getConcurrentStreamingCameraIds()}
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_CAMERA_CONCURRENT = "android.hardware.camera.concurrent";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device is capable of communicating with
* consumer IR devices.
*/
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index dfc4f0f..b3a1ee2 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -2875,7 +2875,28 @@
@NonNull
public static final Key<int[]> SCALER_AVAILABLE_ROTATE_AND_CROP_MODES =
new Key<int[]>("android.scaler.availableRotateAndCropModes", int[].class);
-
+ /**
+ * <p>An array of mandatory concurrent stream combinations.
+ * This is an app-readable conversion of the concurrent mandatory stream combination
+ * {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.</p>
+ * <p>The array of
+ * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
+ * generated according to the documented
+ * {@link android.hardware.camera2.CameraDevice#createCaptureSession guideline} for each device
+ * which has its Id present in the set returned by
+ * {@link android.hardware.camera2.CameraManager#getConcurrentStreamingCameraIds}.
+ * Clients can use the array as a quick reference to find an appropriate camera stream
+ * combination.
+ * The mandatory stream combination array will be {@code null} in case the device is not a part
+ * of at least one set of combinations returned by
+ * {@link android.hardware.camera2.CameraManager#getConcurrentStreamingCameraIds}.</p>
+ * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+ */
+ @PublicKey
+ @NonNull
+ @SyntheticKey
+ public static final Key<android.hardware.camera2.params.MandatoryStreamCombination[]> SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS =
+ new Key<android.hardware.camera2.params.MandatoryStreamCombination[]>("android.scaler.mandatoryConcurrentStreamCombinations", android.hardware.camera2.params.MandatoryStreamCombination[].class);
/**
* <p>The area of the image sensor which corresponds to active pixels after any geometric
* distortion correction has been applied.</p>
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index cc06681..24d9311 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -680,6 +680,25 @@
* </table><br>
* </p>
*
+ *<p>Devices capable of streaming concurrently with other devices as described by
+ * {@link android.hardware.camera2.CameraManager#getConcurrentStreamingCameraIds} have the
+ * following guaranteed streams (when streaming concurrently with other devices)</p>
+ *
+ * <table>
+ * <tr><th colspan="5">Concurrent stream guaranteed configurations</th></tr>
+ * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
+ * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>In-app video / image processing.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>In-app viewfinder analysis.</td> </tr>
+ * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td>In-app video / processing with preview.</td> </tr>
+ * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV }</td><td id="rb">{@code MAXIMUM}</td> <td>In-app video / processing with preview.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV }</td><td id="rb">{@code MAXIMUM}</td> <td>Standard Recording.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p> For guaranteed concurrent stream configurations, MAXIMUM refers to the camera device's
+ * resolution for that format from {@link StreamConfigurationMap#getOutputSizes} or
+ * 720p(1280X720) whichever is lower. </p>
* <p>MONOCHROME-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES}
* includes {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME}) devices
* supporting {@link android.graphics.ImageFormat#Y8 Y8} support substituting {@code YUV}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 55025f0..9ee56a9 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -31,6 +31,9 @@
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.legacy.CameraDeviceUserShim;
import android.hardware.camera2.legacy.LegacyMetadataMapper;
+import android.hardware.camera2.params.SessionConfiguration;
+import android.hardware.camera2.utils.CameraIdAndSessionConfiguration;
+import android.hardware.camera2.utils.ConcurrentCameraIdCombination;
import android.os.Binder;
import android.os.DeadObjectException;
import android.os.Handler;
@@ -40,6 +43,7 @@
import android.os.ServiceSpecificException;
import android.os.SystemProperties;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import android.util.Size;
import android.view.Display;
@@ -48,6 +52,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -126,6 +131,66 @@
}
/**
+ * Return the list of combinations of currently connected camera devices identifiers, which
+ * support configuring camera device sessions concurrently.
+ *
+ * <p>The set of combinations may include camera devices that may be in use by other camera API
+ * clients.</p>
+ *
+ * <p>The set of combinations doesn't contain physical cameras that can only be used as
+ * part of a logical multi-camera device.</p>
+ *
+ * @return The set of combinations of currently connected camera devices, that may have
+ * sessions configured concurrently. The set of combinations will be empty if no such
+ * combinations are supported by the camera subsystem.
+ *
+ * @throws CameraAccessException if the camera device has been disconnected.
+ */
+ @NonNull
+ public Set<Set<String>> getConcurrentStreamingCameraIds() throws CameraAccessException {
+ return CameraManagerGlobal.get().getConcurrentStreamingCameraIds();
+ }
+
+ /**
+ * Checks whether the provided set of camera devices and their corresponding
+ * {@link SessionConfiguration} can be configured concurrently.
+ *
+ * <p>This method performs a runtime check of the given {@link SessionConfiguration} and camera
+ * id combinations. The result confirms whether or not the passed session configurations can be
+ * successfully used to create camera capture sessions concurrently, on the given camera
+ * devices using {@link CameraDevice#createCaptureSession(SessionConfiguration)}.
+ * </p>
+ *
+ * <p>The method can be called at any point before, during and after active capture sessions.
+ * It will not impact normal camera behavior in any way and must complete significantly
+ * faster than creating a regular or constrained capture session.</p>
+ *
+ * <p>Although this method is faster than creating a new capture session, it is not intended
+ * to be used for exploring the entire space of supported concurrent stream combinations. The
+ * available mandatory concurrent stream combinations may be obtained by querying
+ * {@link #getCameraCharacteristics} for the key
+ * SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS. </p>
+ *
+ * <p>Note that session parameters will be ignored and calls to
+ * {@link SessionConfiguration#setSessionParameters} are not required.</p>
+ *
+ * @return {@code true} if the given combination of session configurations and corresponding
+ * camera ids are concurrently supported by the camera sub-system,
+ * {@code false} otherwise.
+ *
+ * @throws IllegalArgumentException if the set of camera devices provided is not a subset of
+ * those returned by getConcurrentStreamingCameraIds()
+ * @throws CameraAccessException if one of the camera devices queried is no longer connected.
+ */
+ @RequiresPermission(android.Manifest.permission.CAMERA)
+ public boolean isConcurrentSessionConfigurationSupported(
+ @NonNull Map<String, SessionConfiguration> cameraIdAndSessionConfig)
+ throws CameraAccessException {
+ return CameraManagerGlobal.get().isConcurrentSessionConfigurationSupported(
+ cameraIdAndSessionConfig);
+ }
+
+ /**
* Register a callback to be notified about camera device availability.
*
* <p>Registering the same callback again will replace the handler with the
@@ -336,8 +401,10 @@
} catch (NumberFormatException e) {
Log.e(TAG, "Failed to parse camera Id " + cameraId + " to integer");
}
+ boolean hasConcurrentStreams =
+ CameraManagerGlobal.get().cameraIdHasConcurrentStreamsLocked(cameraId);
+ info.setHasMandatoryConcurrentStreams(hasConcurrentStreams);
info.setDisplaySize(displaySize);
-
characteristics = new CameraCharacteristics(info);
}
} catch (ServiceSpecificException e) {
@@ -964,6 +1031,9 @@
private final ArrayMap<String, ArrayList<String>> mUnavailablePhysicalDevices =
new ArrayMap<String, ArrayList<String>>();
+ private final Set<Set<String>> mConcurrentCameraIdCombinations =
+ new ArraySet<Set<String>>();
+
// Registered availablility callbacks and their executors
private final ArrayMap<AvailabilityCallback, Executor> mCallbackMap =
new ArrayMap<AvailabilityCallback, Executor>();
@@ -1068,7 +1138,22 @@
} catch (RemoteException e) {
// Camera service is now down, leave mCameraService as null
}
+
+ try {
+ ConcurrentCameraIdCombination[] cameraIdCombinations =
+ cameraService.getConcurrentStreamingCameraIds();
+ for (ConcurrentCameraIdCombination comb : cameraIdCombinations) {
+ mConcurrentCameraIdCombinations.add(comb.getConcurrentCameraIdCombination());
+ }
+ } catch (ServiceSpecificException e) {
+ // Unexpected failure
+ throw new IllegalStateException("Failed to get concurrent camera id combinations",
+ e);
+ } catch (RemoteException e) {
+ // Camera service died in all probability
+ }
}
+
private String[] extractCameraIdListLocked() {
String[] cameraIds = null;
int idCount = 0;
@@ -1089,6 +1174,31 @@
}
return cameraIds;
}
+
+ private Set<Set<String>> extractConcurrentCameraIdListLocked() {
+ Set<Set<String>> concurrentCameraIds = new ArraySet<Set<String>>();
+ for (Set<String> cameraIds : mConcurrentCameraIdCombinations) {
+ Set<String> extractedCameraIds = new ArraySet<String>();
+ for (String cameraId : cameraIds) {
+ // if the camera id status is NOT_PRESENT or ENUMERATING; skip the device.
+ // TODO: Would a device status NOT_PRESENT ever be in the map ? it gets removed
+ // in the callback anyway.
+ Integer status = mDeviceStatus.get(cameraId);
+ if (status == null) {
+ // camera id not present
+ continue;
+ }
+ if (status == ICameraServiceListener.STATUS_ENUMERATING
+ || status == ICameraServiceListener.STATUS_NOT_PRESENT) {
+ continue;
+ }
+ extractedCameraIds.add(cameraId);
+ }
+ concurrentCameraIds.add(extractedCameraIds);
+ }
+ return concurrentCameraIds;
+ }
+
private static void sortCameraIds(String[] cameraIds) {
// The sort logic must match the logic in
// libcameraservice/common/CameraProviderManager.cpp::getAPI1CompatibleCameraDeviceIds
@@ -1214,6 +1324,88 @@
return cameraIds;
}
+ public @NonNull Set<Set<String>> getConcurrentStreamingCameraIds() {
+ Set<Set<String>> concurrentStreamingCameraIds = null;
+ synchronized (mLock) {
+ // Try to make sure we have an up-to-date list of concurrent camera devices.
+ connectCameraServiceLocked();
+ concurrentStreamingCameraIds = extractConcurrentCameraIdListLocked();
+ }
+ // TODO: Some sort of sorting ?
+ return concurrentStreamingCameraIds;
+ }
+
+ public boolean isConcurrentSessionConfigurationSupported(
+ @NonNull Map<String, SessionConfiguration> cameraIdsAndSessionConfigurations)
+ throws CameraAccessException {
+
+ if (cameraIdsAndSessionConfigurations == null) {
+ throw new IllegalArgumentException("cameraIdsAndSessionConfigurations was null");
+ }
+
+ int size = cameraIdsAndSessionConfigurations.size();
+ if (size == 0) {
+ throw new IllegalArgumentException("camera id and session combination is empty");
+ }
+
+ synchronized (mLock) {
+ // Go through all the elements and check if the camera ids are valid at least /
+ // belong to one of the combinations returned by getConcurrentStreamingCameraIds()
+ boolean subsetFound = false;
+ for (Set<String> combination : mConcurrentCameraIdCombinations) {
+ if (combination.containsAll(cameraIdsAndSessionConfigurations.keySet())) {
+ subsetFound = true;
+ }
+ }
+ if (!subsetFound) {
+ throw new IllegalArgumentException(
+ "The set of camera ids provided is not a subset of"
+ + "getConcurrentStreamingCameraIds");
+ }
+ CameraIdAndSessionConfiguration [] cameraIdsAndConfigs =
+ new CameraIdAndSessionConfiguration[size];
+ int i = 0;
+ for (Map.Entry<String, SessionConfiguration> pair :
+ cameraIdsAndSessionConfigurations.entrySet()) {
+ cameraIdsAndConfigs[i] =
+ new CameraIdAndSessionConfiguration(pair.getKey(), pair.getValue());
+ i++;
+ }
+ try {
+ return mCameraService.isConcurrentSessionConfigurationSupported(
+ cameraIdsAndConfigs);
+ } catch (ServiceSpecificException e) {
+ throwAsPublicException(e);
+ } catch (RemoteException e) {
+ // Camera service died - act as if the camera was disconnected
+ throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
+ "Camera service is currently unavailable", e);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Helper function to find out if a camera id is in the set of combinations returned by
+ * getConcurrentStreamingCameraIds()
+ * @param cameraId the unique identifier of the camera device to query
+ * @return Whether the camera device was found in the set of combinations returned by
+ * getConcurrentStreamingCameraIds
+ */
+ public boolean cameraIdHasConcurrentStreamsLocked(String cameraId) {
+ if (!mDeviceStatus.containsKey(cameraId)) {
+ Log.e(TAG, "cameraIdHasConcurrentStreamsLocked called on non existing camera id");
+ return false;
+ }
+ for (Set<String> comb : mConcurrentCameraIdCombinations) {
+ if (comb.contains(cameraId)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public void setTorchMode(String cameraId, boolean enabled) throws CameraAccessException {
synchronized(mLock) {
@@ -1698,6 +1890,8 @@
cameraId);
}
+ mConcurrentCameraIdCombinations.clear();
+
scheduleCameraServiceReconnectionLocked();
}
}
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 3ae3d78..aefe66f 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -621,6 +621,16 @@
}
});
sGetCommandMap.put(
+ CameraCharacteristics.SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS.getNativeKey(),
+ new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getMandatoryConcurrentStreamCombinations();
+ }
+ });
+
+ sGetCommandMap.put(
CameraCharacteristics.CONTROL_MAX_REGIONS_AE.getNativeKey(), new GetCommand() {
@Override
@SuppressWarnings("unchecked")
@@ -1247,7 +1257,8 @@
return ret;
}
- private MandatoryStreamCombination[] getMandatoryStreamCombinations() {
+ private MandatoryStreamCombination[] getMandatoryStreamCombinationsHelper(
+ boolean getConcurrent) {
int[] capabilities = getBase(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
ArrayList<Integer> caps = new ArrayList<Integer>();
caps.ensureCapacity(capabilities.length);
@@ -1257,7 +1268,13 @@
int hwLevel = getBase(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
MandatoryStreamCombination.Builder build = new MandatoryStreamCombination.Builder(
mCameraId, hwLevel, mDisplaySize, caps, getStreamConfigurationMap());
- List<MandatoryStreamCombination> combs = build.getAvailableMandatoryStreamCombinations();
+
+ List<MandatoryStreamCombination> combs = null;
+ if (getConcurrent) {
+ combs = build.getAvailableMandatoryConcurrentStreamCombinations();
+ } else {
+ combs = build.getAvailableMandatoryStreamCombinations();
+ }
if ((combs != null) && (!combs.isEmpty())) {
MandatoryStreamCombination[] combArray = new MandatoryStreamCombination[combs.size()];
combArray = combs.toArray(combArray);
@@ -1267,6 +1284,17 @@
return null;
}
+ private MandatoryStreamCombination[] getMandatoryConcurrentStreamCombinations() {
+ if (!mHasMandatoryConcurrentStreams) {
+ return null;
+ }
+ return getMandatoryStreamCombinationsHelper(true);
+ }
+
+ private MandatoryStreamCombination[] getMandatoryStreamCombinations() {
+ return getMandatoryStreamCombinationsHelper(false);
+ }
+
private StreamConfigurationMap getStreamConfigurationMap() {
StreamConfiguration[] configurations = getBase(
CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
@@ -1614,6 +1642,7 @@
}
private int mCameraId = -1;
+ private boolean mHasMandatoryConcurrentStreams = false;
private Size mDisplaySize = new Size(0, 0);
/**
@@ -1628,6 +1657,18 @@
}
/**
+ * Set the current camera Id.
+ *
+ * @param hasMandatoryConcurrentStreams whether the metadata advertises mandatory concurrent
+ * streams.
+ *
+ * @hide
+ */
+ public void setHasMandatoryConcurrentStreams(boolean hasMandatoryConcurrentStreams) {
+ mHasMandatoryConcurrentStreams = hasMandatoryConcurrentStreams;
+ }
+
+ /**
* Set the current display size.
*
* @param displaySize The current display size.
@@ -1682,6 +1723,7 @@
public void swap(CameraMetadataNative other) {
nativeSwap(other);
mCameraId = other.mCameraId;
+ mHasMandatoryConcurrentStreams = other.mHasMandatoryConcurrentStreams;
mDisplaySize = other.mDisplaySize;
}
diff --git a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
index 23f18a8..41e1443 100644
--- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
+++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
@@ -16,30 +16,27 @@
package android.hardware.camera2.params;
-import static com.android.internal.util.Preconditions.*;
import static android.hardware.camera2.params.StreamConfigurationMap.checkArgumentFormat;
-import android.annotation.IntRange;
+import static com.android.internal.util.Preconditions.*;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.ImageFormat.Format;
import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraCharacteristics.Key;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.utils.HashCodeHelpers;
-import android.graphics.PixelFormat;
import android.media.CamcorderProfile;
-import android.util.Size;
import android.util.Log;
import android.util.Pair;
+import android.util.Size;
-import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -200,7 +197,6 @@
mDescription = description;
mIsReprocessable = isReprocessable;
}
-
/**
* Get the mandatory stream combination description.
*
@@ -271,7 +267,7 @@
mStreamsInformation.hashCode());
}
- private static enum SizeThreshold { VGA, PREVIEW, RECORD, MAXIMUM }
+ private static enum SizeThreshold { VGA, PREVIEW, RECORD, MAXIMUM, s720p }
private static enum ReprocessType { NONE, PRIVATE, YUV }
private static final class StreamTemplate {
public int mFormat;
@@ -653,6 +649,27 @@
/*reprocessType*/ ReprocessType.YUV),
};
+ private static StreamCombinationTemplate sConcurrentStreamCombinations[] = {
+ new StreamCombinationTemplate(new StreamTemplate [] {
+ new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s720p) },
+ "In-app video / image processing"),
+ new StreamCombinationTemplate(new StreamTemplate [] {
+ new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s720p) },
+ "preview / preview to GPU"),
+ new StreamCombinationTemplate(new StreamTemplate [] {
+ new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s720p),
+ new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s720p)},
+ "In-app video / image processing with preview"),
+ new StreamCombinationTemplate(new StreamTemplate [] {
+ new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s720p),
+ new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s720p)},
+ "In-app video / image processing with preview"),
+ new StreamCombinationTemplate(new StreamTemplate [] {
+ new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s720p),
+ new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s720p)},
+ "Standard Recording"),
+ };
+
/**
* Helper builder class to generate a list of available mandatory stream combinations.
* @hide
@@ -687,6 +704,64 @@
}
/**
+ * Retrieve a list of all available mandatory concurrent stream combinations.
+ * This method should only be called for devices which are listed in combinations returned
+ * by CameraManager.getConcurrentStreamingCameraIds.
+ *
+ * @return a non-modifiable list of supported mandatory concurrent stream combinations.
+ */
+ public @NonNull List<MandatoryStreamCombination>
+ getAvailableMandatoryConcurrentStreamCombinations() {
+ // Since concurrent streaming support is optional, we mandate these stream
+ // combinations regardless of camera device capabilities.
+ if (!isColorOutputSupported()) {
+ Log.v(TAG, "Device is not backward compatible!");
+ throw new IllegalArgumentException("Camera device which is not BACKWARD_COMPATIBLE"
+ + " cannot have mandatory concurrent streams");
+ }
+ Size size720p = new Size(1280, 720);
+
+ ArrayList<MandatoryStreamCombination> availableConcurrentStreamCombinations =
+ new ArrayList<MandatoryStreamCombination>();
+ availableConcurrentStreamCombinations.ensureCapacity(
+ sConcurrentStreamCombinations.length);
+ for (StreamCombinationTemplate combTemplate : sConcurrentStreamCombinations) {
+ ArrayList<MandatoryStreamInformation> streamsInfo =
+ new ArrayList<MandatoryStreamInformation>();
+ streamsInfo.ensureCapacity(combTemplate.mStreamTemplates.length);
+ for (StreamTemplate template : combTemplate.mStreamTemplates) {
+ MandatoryStreamInformation streamInfo;
+ List<Size> sizes = new ArrayList<Size>();
+ Size sizeChosen =
+ getMinSize(size720p,
+ getMaxSize(mStreamConfigMap.getOutputSizes(template.mFormat)));
+ sizes.add(sizeChosen);
+ try {
+ streamInfo = new MandatoryStreamInformation(sizes, template.mFormat);
+ } catch (IllegalArgumentException e) {
+ String cause = "No available sizes found for format: " + template.mFormat
+ + " size threshold: " + template.mSizeThreshold + " combination: "
+ + combTemplate.mDescription;
+ throw new RuntimeException(cause, e);
+ }
+ streamsInfo.add(streamInfo);
+ }
+
+ MandatoryStreamCombination streamCombination;
+ try {
+ streamCombination = new MandatoryStreamCombination(streamsInfo,
+ combTemplate.mDescription, /*isReprocess*/false);
+ } catch (IllegalArgumentException e) {
+ String cause = "No stream information for mandatory combination: "
+ + combTemplate.mDescription;
+ throw new RuntimeException(cause, e);
+ }
+ availableConcurrentStreamCombinations.add(streamCombination);
+ }
+ return Collections.unmodifiableList(availableConcurrentStreamCombinations);
+ }
+
+ /**
* Retrieve a list of all available mandatory stream combinations.
*
* @return a non-modifiable list of supported mandatory stream combinations or
@@ -965,6 +1040,18 @@
}
/**
+ * Return the lower size
+ */
+ public static @Nullable Size getMinSize(Size a, Size b) {
+ if (a == null || b == null) {
+ throw new IllegalArgumentException("sizes was empty");
+ }
+ if (a.getWidth() * a.getHeight() < b.getHeight() * b.getWidth()) {
+ return a;
+ }
+ return b;
+ }
+ /**
* Get the largest size by area.
*
* @param sizes an array of sizes, must have at least 1 element
diff --git a/core/java/android/hardware/camera2/utils/CameraIdAndSessionConfiguration.java b/core/java/android/hardware/camera2/utils/CameraIdAndSessionConfiguration.java
new file mode 100644
index 0000000..cdc037c
--- /dev/null
+++ b/core/java/android/hardware/camera2/utils/CameraIdAndSessionConfiguration.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.utils;
+
+import android.annotation.NonNull;
+import android.hardware.camera2.params.SessionConfiguration;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * CameraIdAndSessionConfiguration
+ *
+ * Includes the pair of a cameraId and its corresponding SessionConfiguration, to be used with
+ * ICameraService.isConcurrentSessionConfigurationSupported.
+ * @hide
+ */
+public class CameraIdAndSessionConfiguration implements Parcelable {
+
+ private String mCameraId;
+ private SessionConfiguration mSessionConfiguration;
+
+ public CameraIdAndSessionConfiguration(@NonNull String cameraId,
+ @NonNull SessionConfiguration sessionConfiguration) {
+ mCameraId = cameraId;
+ mSessionConfiguration = sessionConfiguration;
+ }
+
+ public static final @NonNull
+ Parcelable.Creator<CameraIdAndSessionConfiguration> CREATOR =
+ new Parcelable.Creator<CameraIdAndSessionConfiguration>() {
+ @Override
+ public CameraIdAndSessionConfiguration createFromParcel(Parcel in) {
+ return new CameraIdAndSessionConfiguration(in);
+ }
+
+ @Override
+ public CameraIdAndSessionConfiguration[] newArray(int size) {
+ return new CameraIdAndSessionConfiguration[size];
+ }
+ };
+
+ private CameraIdAndSessionConfiguration(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mCameraId);
+ mSessionConfiguration.writeToParcel(dest, flags);
+ }
+
+ /**
+ * helper for CREATOR
+ */
+ public void readFromParcel(Parcel in) {
+ mCameraId = in.readString();
+ mSessionConfiguration = SessionConfiguration.CREATOR.createFromParcel(in);
+ }
+
+ public @NonNull String getCameraId() {
+ return mCameraId;
+ }
+
+ public @NonNull SessionConfiguration getSessionConfiguration() {
+ return mSessionConfiguration;
+ }
+}
diff --git a/core/java/android/hardware/camera2/utils/ConcurrentCameraIdCombination.java b/core/java/android/hardware/camera2/utils/ConcurrentCameraIdCombination.java
new file mode 100644
index 0000000..8f4d636
--- /dev/null
+++ b/core/java/android/hardware/camera2/utils/ConcurrentCameraIdCombination.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.utils;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * ConcurrentCameraIdCombination
+ *
+ * Includes a list of camera ids that may have sessions configured concurrently.
+ * @hide
+ */
+public class ConcurrentCameraIdCombination implements Parcelable {
+
+ private Set<String> mConcurrentCameraIds = new HashSet<>();
+
+ public static final @NonNull
+ Parcelable.Creator<ConcurrentCameraIdCombination> CREATOR =
+ new Parcelable.Creator<ConcurrentCameraIdCombination>() {
+ @Override
+ public ConcurrentCameraIdCombination createFromParcel(Parcel in) {
+ return new ConcurrentCameraIdCombination(in);
+ }
+
+ @Override
+ public ConcurrentCameraIdCombination[] newArray(int size) {
+ return new ConcurrentCameraIdCombination[size];
+ }
+ };
+
+ private ConcurrentCameraIdCombination(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mConcurrentCameraIds.size());
+ for (String cameraId : mConcurrentCameraIds) {
+ dest.writeString(cameraId);
+ }
+ }
+
+ /**
+ * helper for CREATOR
+ */
+ public void readFromParcel(Parcel in) {
+ mConcurrentCameraIds.clear();
+ int cameraCombinationSize = in.readInt();
+ if (cameraCombinationSize < 0) {
+ throw new RuntimeException("cameraCombinationSize " + cameraCombinationSize
+ + " should not be negative");
+ }
+ for (int i = 0; i < cameraCombinationSize; i++) {
+ String cameraId = in.readString();
+ if (cameraId == null) {
+ throw new RuntimeException("Failed to read camera id from Parcel");
+ }
+ mConcurrentCameraIds.add(cameraId);
+ }
+ }
+
+ /**
+ * Get this concurrent camera id combination.
+ */
+ public Set<String> getConcurrentCameraIdCombination() {
+ return mConcurrentCameraIds;
+ }
+}
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index 13122d2..6412a0c 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -61,7 +61,7 @@
private static final String ATTR_MODEL_LOWER_BOUND = "model-lower-bound";
private static final String ATTR_MODEL_UPPER_BOUND = "model-upper-bound";
/**
- * Returned from {@link #getShortTermModelTimeout()} if no timeout has been set.
+ * Returned from {@link #getShortTermModelTimeoutMillis()} if no timeout has been set.
* In this case the device will use the default timeout available in the
* {@link BrightnessConfiguration} returned from
* {@link DisplayManager#getDefaultBrightnessConfiguration()}.
@@ -160,7 +160,7 @@
* {@link #getShortTermModelUpperLuxMultiplier()} to decide whether to keep any adjustment
* the user has made to adaptive brightness.
*/
- public long getShortTermModelTimeout() {
+ public long getShortTermModelTimeoutMillis() {
return mShortTermModelTimeout;
}
@@ -326,7 +326,7 @@
builder.setDescription(description);
final boolean shouldCollectColorSamples = in.readBoolean();
builder.setShouldCollectColorSamples(shouldCollectColorSamples);
- builder.setShortTermModelTimeout(in.readLong());
+ builder.setShortTermModelTimeoutMillis(in.readLong());
builder.setShortTermModelLowerLuxMultiplier(in.readFloat());
builder.setShortTermModelUpperLuxMultiplier(in.readFloat());
return builder.build();
@@ -487,7 +487,7 @@
builder.addCorrectionByCategory(category, correction);
}
builder.setShouldCollectColorSamples(shouldCollectColorSamples);
- builder.setShortTermModelTimeout(shortTermModelTimeout);
+ builder.setShortTermModelTimeoutMillis(shortTermModelTimeout);
builder.setShortTermModelLowerLuxMultiplier(shortTermModelLowerLuxMultiplier);
builder.setShortTermModelUpperLuxMultiplier(shortTermModelUpperLuxMultiplier);
return builder.build();
@@ -673,8 +673,8 @@
* adjustment the user has made to adaptive brightness.
*/
@NonNull
- public Builder setShortTermModelTimeout(long shortTermModelTimeout) {
- mShortTermModelTimeout = shortTermModelTimeout;
+ public Builder setShortTermModelTimeoutMillis(long shortTermModelTimeoutMillis) {
+ mShortTermModelTimeout = shortTermModelTimeoutMillis;
return this;
}
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index fb36e6f..228548a 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -38,6 +38,7 @@
public class HwParcel {
private static final String TAG = "HwParcel";
+ /** @hide */
@IntDef(prefix = { "STATUS_" }, value = {
STATUS_SUCCESS,
})
diff --git a/core/java/android/os/connectivity/WifiActivityEnergyInfo.java b/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
index 664b6c8..016cc2f 100644
--- a/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
+++ b/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
@@ -16,7 +16,9 @@
package android.os.connectivity;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.app.ActivityThread;
@@ -37,14 +39,20 @@
*/
@SystemApi
public final class WifiActivityEnergyInfo implements Parcelable {
- private long mTimeSinceBootMillis;
+ @ElapsedRealtimeLong
+ private final long mTimeSinceBootMillis;
@StackState
- private int mStackState;
- private long mControllerTxDurationMillis;
- private long mControllerRxDurationMillis;
- private long mControllerScanDurationMillis;
- private long mControllerIdleDurationMillis;
- private long mControllerEnergyUsedMicroJoules;
+ private final int mStackState;
+ @IntRange(from = 0)
+ private final long mControllerTxDurationMillis;
+ @IntRange(from = 0)
+ private final long mControllerRxDurationMillis;
+ @IntRange(from = 0)
+ private final long mControllerScanDurationMillis;
+ @IntRange(from = 0)
+ private final long mControllerIdleDurationMillis;
+ @IntRange(from = 0)
+ private final long mControllerEnergyUsedMicroJoules;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -67,7 +75,7 @@
/**
* Constructor.
*
- * @param timeSinceBootMillis the time since boot, in milliseconds.
+ * @param timeSinceBootMillis the elapsed real time since boot, in milliseconds.
* @param stackState The current state of the Wifi Stack. One of {@link #STACK_STATE_INVALID},
* {@link #STACK_STATE_STATE_ACTIVE}, {@link #STACK_STATE_STATE_SCANNING},
* or {@link #STACK_STATE_STATE_IDLE}.
@@ -78,23 +86,27 @@
* receiving.
*/
public WifiActivityEnergyInfo(
- long timeSinceBootMillis,
+ @ElapsedRealtimeLong long timeSinceBootMillis,
@StackState int stackState,
- long txDurationMillis,
- long rxDurationMillis,
- long scanDurationMillis,
- long idleDurationMillis) {
- mTimeSinceBootMillis = timeSinceBootMillis;
- mStackState = stackState;
- mControllerTxDurationMillis = txDurationMillis;
- mControllerRxDurationMillis = rxDurationMillis;
- mControllerScanDurationMillis = scanDurationMillis;
- mControllerIdleDurationMillis = idleDurationMillis;
+ @IntRange(from = 0) long txDurationMillis,
+ @IntRange(from = 0) long rxDurationMillis,
+ @IntRange(from = 0) long scanDurationMillis,
+ @IntRange(from = 0) long idleDurationMillis) {
+ this(timeSinceBootMillis,
+ stackState,
+ txDurationMillis,
+ rxDurationMillis,
+ scanDurationMillis,
+ idleDurationMillis,
+ calculateEnergyMicroJoules(txDurationMillis, rxDurationMillis, idleDurationMillis));
+ }
+
+ private static long calculateEnergyMicroJoules(
+ long txDurationMillis, long rxDurationMillis, long idleDurationMillis) {
final Context context = ActivityThread.currentActivityThread().getSystemContext();
if (context == null) {
- mControllerEnergyUsedMicroJoules = 0L;
- return;
+ return 0L;
}
// Calculate energy used using PowerProfile.
PowerProfile powerProfile = new PowerProfile(context);
@@ -106,10 +118,28 @@
PowerProfile.POWER_WIFI_CONTROLLER_TX);
final double voltage = powerProfile.getAveragePower(
PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
- final long energyUsedMicroJoules = (long) ((mControllerTxDurationMillis * txCurrent
- + mControllerRxDurationMillis * rxCurrent
- + mControllerIdleDurationMillis * rxIdleCurrent)
+
+ return (long) ((txDurationMillis * txCurrent
+ + rxDurationMillis * rxCurrent
+ + idleDurationMillis * rxIdleCurrent)
* voltage);
+ }
+
+ /** @hide */
+ public WifiActivityEnergyInfo(
+ @ElapsedRealtimeLong long timeSinceBootMillis,
+ @StackState int stackState,
+ @IntRange(from = 0) long txDurationMillis,
+ @IntRange(from = 0) long rxDurationMillis,
+ @IntRange(from = 0) long scanDurationMillis,
+ @IntRange(from = 0) long idleDurationMillis,
+ @IntRange(from = 0) long energyUsedMicroJoules) {
+ mTimeSinceBootMillis = timeSinceBootMillis;
+ mStackState = stackState;
+ mControllerTxDurationMillis = txDurationMillis;
+ mControllerRxDurationMillis = rxDurationMillis;
+ mControllerScanDurationMillis = scanDurationMillis;
+ mControllerIdleDurationMillis = idleDurationMillis;
mControllerEnergyUsedMicroJoules = energyUsedMicroJoules;
}
@@ -158,16 +188,12 @@
return 0;
}
- /** Get the timestamp (milliseconds since boot) of record creation. */
+ /** Get the timestamp (elapsed real time milliseconds since boot) of record creation. */
+ @ElapsedRealtimeLong
public long getTimeSinceBootMillis() {
return mTimeSinceBootMillis;
}
- /** Set the timestamp (milliseconds since boot) of record creation. */
- public void setTimeSinceBootMillis(long timeSinceBootMillis) {
- mTimeSinceBootMillis = timeSinceBootMillis;
- }
-
/**
* Get the Wifi stack reported state. One of {@link #STACK_STATE_INVALID},
* {@link #STACK_STATE_STATE_ACTIVE}, {@link #STACK_STATE_STATE_SCANNING},
@@ -178,66 +204,40 @@
return mStackState;
}
- /**
- * Set the Wifi stack reported state. One of {@link #STACK_STATE_INVALID},
- * {@link #STACK_STATE_STATE_ACTIVE}, {@link #STACK_STATE_STATE_SCANNING},
- * {@link #STACK_STATE_STATE_IDLE}.
- */
- public void setStackState(@StackState int stackState) {
- mStackState = stackState;
- }
-
/** Get the Wifi transmission duration, in milliseconds. */
+ @IntRange(from = 0)
public long getControllerTxDurationMillis() {
return mControllerTxDurationMillis;
}
- /** Set the Wifi transmission duration, in milliseconds. */
- public void setControllerTxDurationMillis(long controllerTxDurationMillis) {
- mControllerTxDurationMillis = controllerTxDurationMillis;
- }
-
/** Get the Wifi receive duration, in milliseconds. */
+ @IntRange(from = 0)
public long getControllerRxDurationMillis() {
return mControllerRxDurationMillis;
}
- /** Set the Wifi receive duration, in milliseconds. */
- public void setControllerRxDurationMillis(long controllerRxDurationMillis) {
- mControllerRxDurationMillis = controllerRxDurationMillis;
- }
-
/** Get the Wifi scan duration, in milliseconds. */
+ @IntRange(from = 0)
public long getControllerScanDurationMillis() {
return mControllerScanDurationMillis;
}
- /** Set the Wifi scan duration, in milliseconds. */
- public void setControllerScanDurationMillis(long controllerScanDurationMillis) {
- mControllerScanDurationMillis = controllerScanDurationMillis;
- }
-
/** Get the Wifi idle duration, in milliseconds. */
+ @IntRange(from = 0)
public long getControllerIdleDurationMillis() {
return mControllerIdleDurationMillis;
}
- /** Set the Wifi idle duration, in milliseconds. */
- public void setControllerIdleDurationMillis(long controllerIdleDurationMillis) {
- mControllerIdleDurationMillis = controllerIdleDurationMillis;
- }
-
/** Get the energy consumed by Wifi, in microjoules. */
+ @IntRange(from = 0)
public long getControllerEnergyUsedMicroJoules() {
return mControllerEnergyUsedMicroJoules;
}
- /** Set the energy consumed by Wifi, in microjoules. */
- public void setControllerEnergyUsedMicroJoules(long controllerEnergyUsedMicroJoules) {
- mControllerEnergyUsedMicroJoules = controllerEnergyUsedMicroJoules;
- }
-
- /** Returns true if the record is valid, false otherwise. */
+ /**
+ * Returns true if the record is valid, false otherwise.
+ * @hide
+ */
public boolean isValid() {
return mControllerTxDurationMillis >= 0
&& mControllerRxDurationMillis >= 0
diff --git a/core/java/android/service/controls/TokenProvider.aidl b/core/java/android/service/controls/TokenProvider.aidl
new file mode 100644
index 0000000..8f4b795
--- /dev/null
+++ b/core/java/android/service/controls/TokenProvider.aidl
@@ -0,0 +1,7 @@
+package android.service.controls;
+
+/** @hide */
+interface TokenProvider {
+ void setAuthToken(String token);
+ String getAccountName();
+}
\ No newline at end of file
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 7815864..26c8314 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -1259,6 +1259,7 @@
@Override
public IBinder onBind(Intent intent) {
if (TextToSpeech.Engine.INTENT_ACTION_TTS_SERVICE.equals(intent.getAction())) {
+ Binder.allowBlocking(mBinder.asBinder());
return mBinder;
}
return null;
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index de64573..b232efc 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -364,6 +364,12 @@
*/
public static final String NAV_BAR_HANDLE_FORCE_OPAQUE = "nav_bar_handle_force_opaque";
+ /**
+ * (boolean) Whether to force the Nav Bar handle to remain visible over the lockscreen.
+ */
+ public static final String NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN =
+ "nav_bar_handle_show_over_lockscreen";
+
private SystemUiDeviceConfigFlags() {
}
}
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index eb7d432..30e914d 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -34,7 +34,6 @@
#include <string>
#define DEBUG_PARCEL 0
-#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
static jclass gBitmap_class;
static jfieldID gBitmap_nativePtr;
@@ -587,7 +586,6 @@
android::Parcel* p = android::parcelForJavaObject(env, parcel);
- const bool isMutable = p->readInt32() != 0;
const SkColorType colorType = (SkColorType)p->readInt32();
const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
const uint32_t colorSpaceSize = p->readUint32();
@@ -636,11 +634,10 @@
// Map the bitmap in place from the ashmem region if possible otherwise copy.
sk_sp<Bitmap> nativeBitmap;
- if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
+ if (blob.fd() >= 0 && !blob.isMutable()) {
#if DEBUG_PARCEL
- ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
+ ALOGD("Bitmap.createFromParcel: mapped contents of bitmap from %s blob "
"(fds %s)",
- isMutable ? "mutable" : "immutable",
blob.isMutable() ? "mutable" : "immutable",
p->allowFds() ? "allowed" : "forbidden");
#endif
@@ -657,7 +654,7 @@
// Map the pixels in place and take ownership of the ashmem region. We must also respect the
// rowBytes value already set on the bitmap instead of attempting to compute our own.
nativeBitmap = Bitmap::createFrom(bitmap->info(), bitmap->rowBytes(), dupFd,
- const_cast<void*>(blob.data()), size, !isMutable);
+ const_cast<void*>(blob.data()), size, true);
if (!nativeBitmap) {
close(dupFd);
blob.release();
@@ -695,7 +692,7 @@
}
return createBitmap(env, nativeBitmap.release(),
- getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
+ getPremulBitmapCreateFlags(false), NULL, NULL, density);
#else
doThrowRE(env, "Cannot use parcels outside of Android");
return NULL;
@@ -703,9 +700,7 @@
}
static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
- jlong bitmapHandle,
- jboolean isMutable, jint density,
- jobject parcel) {
+ jlong bitmapHandle, jint density, jobject parcel) {
#ifdef __ANDROID__ // Layoutlib does not support parcel
if (parcel == NULL) {
SkDebugf("------- writeToParcel null parcel\n");
@@ -718,7 +713,6 @@
auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
bitmapWrapper->getSkBitmap(&bitmap);
- p->writeInt32(isMutable);
p->writeInt32(bitmap.colorType());
p->writeInt32(bitmap.alphaType());
SkColorSpace* colorSpace = bitmap.colorSpace();
@@ -745,7 +739,7 @@
// Transfer the underlying ashmem region if we have one and it's immutable.
android::status_t status;
int fd = bitmapWrapper->bitmap().getAshmemFd();
- if (fd >= 0 && !isMutable && p->allowFds()) {
+ if (fd >= 0 && p->allowFds()) {
#if DEBUG_PARCEL
ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
"immutable blob (fds %s)",
@@ -761,17 +755,14 @@
}
// Copy the bitmap to a new blob.
- bool mutableCopy = isMutable;
#if DEBUG_PARCEL
- ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
- isMutable ? "mutable" : "immutable",
- mutableCopy ? "mutable" : "immutable",
+ ALOGD("Bitmap.writeToParcel: copying bitmap into new blob (fds %s)",
p->allowFds() ? "allowed" : "forbidden");
#endif
size_t size = bitmap.computeByteSize();
android::Parcel::WritableBlob blob;
- status = p->writeBlob(size, mutableCopy, &blob);
+ status = p->writeBlob(size, false, &blob);
if (status) {
doThrowRE(env, "Could not copy bitmap to parcel blob.");
return JNI_FALSE;
@@ -1109,7 +1100,7 @@
{ "nativeCreateFromParcel",
"(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
(void*)Bitmap_createFromParcel },
- { "nativeWriteToParcel", "(JZILandroid/os/Parcel;)Z",
+ { "nativeWriteToParcel", "(JILandroid/os/Parcel;)Z",
(void*)Bitmap_writeToParcel },
{ "nativeExtractAlpha", "(JJ[I)Landroid/graphics/Bitmap;",
(void*)Bitmap_extractAlpha },
diff --git a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
index 895b22c..4370462 100644
--- a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
+++ b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
@@ -132,7 +132,7 @@
BrightnessConfiguration.Builder builder =
new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
builder.setShouldCollectColorSamples(true);
- builder.setShortTermModelTimeout(1234L);
+ builder.setShortTermModelTimeoutMillis(1234L);
builder.setShortTermModelLowerLuxMultiplier(0.9f);
builder.setShortTermModelUpperLuxMultiplier(0.2f);
builder.addCorrectionByCategory(3,
@@ -153,7 +153,7 @@
BrightnessConfiguration.Builder builder =
new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
builder.setShouldCollectColorSamples(true);
- builder.setShortTermModelTimeout(123L);
+ builder.setShortTermModelTimeoutMillis(123L);
builder.setShortTermModelLowerLuxMultiplier(0.4f);
builder.setShortTermModelUpperLuxMultiplier(0.8f);
builder.addCorrectionByCategory(3,
@@ -236,7 +236,7 @@
assertNotEquals(baseConfig, colorCollectionDiffers);
builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
- builder.setShortTermModelTimeout(300L);
+ builder.setShortTermModelTimeoutMillis(300L);
BrightnessConfiguration timeoutDiffers = builder.build();
assertNotEquals(baseConfig, timeoutDiffers);
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestRunner.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestRunner.java
index 70c266a..ac63853 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestRunner.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestRunner.java
@@ -58,7 +58,7 @@
}
// enable verbose wifi logging
((WifiManager)getContext().getSystemService(Context.WIFI_SERVICE))
- .enableVerboseLogging(1);
+ .setVerboseLoggingEnabled(true);
super.onCreate(icicle);
}
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index ac094ba..9c2e95f 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -2132,7 +2132,7 @@
public void writeToParcel(Parcel p, int flags) {
checkRecycled("Can't parcel a recycled bitmap");
noteHardwareBitmapSlowCall();
- if (!nativeWriteToParcel(mNativePtr, isMutable(), mDensity, p)) {
+ if (!nativeWriteToParcel(mNativePtr, mDensity, p)) {
throw new RuntimeException("native writeToParcel failed");
}
}
@@ -2285,7 +2285,6 @@
private static native Bitmap nativeCreateFromParcel(Parcel p);
// returns true on success
private static native boolean nativeWriteToParcel(long nativeBitmap,
- boolean isMutable,
int density,
Parcel p);
// returns a new bitmap built from the native bitmap's alpha, and the paint
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 9d4c24e..84dde05 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -1141,7 +1141,7 @@
} else if (isActive()) {
summary.append(getSummary(mContext, /* ssid */ null, getDetailedState(),
mInfo != null && mInfo.isEphemeral(),
- mInfo != null ? mInfo.getAppPackageName() : null));
+ mInfo != null ? mInfo.getRequestingPackageName() : null));
} else { // not active
if (mConfig != null && mConfig.hasNoInternetAccess()) {
int messageID = mConfig.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index ed4ff08..26abf71 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -226,7 +226,7 @@
mConnectivityManager = connectivityManager;
// check if verbose logging developer option has been turned on or off
- sVerboseLogging = mWifiManager != null && (mWifiManager.getVerboseLoggingLevel() > 0);
+ sVerboseLogging = mWifiManager != null && mWifiManager.isVerboseLoggingEnabled();
mFilter = filter;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
index b93b000..78ccba0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
@@ -102,10 +102,10 @@
if (accessPoint.getSpeed() != AccessPoint.Speed.NONE) {
visibility.append(" speed=").append(accessPoint.getSpeedLabel());
}
- visibility.append(String.format(" tx=%.1f,", info.getTxSuccessRate()));
- visibility.append(String.format("%.1f,", info.getTxRetriesRate()));
- visibility.append(String.format("%.1f ", info.getTxBadRate()));
- visibility.append(String.format("rx=%.1f", info.getRxSuccessRate()));
+ visibility.append(String.format(" tx=%.1f,", info.getSuccessfulTxPacketsPerSecond()));
+ visibility.append(String.format("%.1f,", info.getRetriedTxPacketsPerSecond()));
+ visibility.append(String.format("%.1f ", info.getLostTxPacketsPerSecond()));
+ visibility.append(String.format("rx=%.1f", info.getSuccessfulRxPacketsPerSecond()));
}
int maxRssi5 = INVALID_RSSI;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 03201ae..42f3cbb 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -507,7 +507,7 @@
WifiInfo wifiInfo = new WifiInfo();
wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(TEST_SSID));
wifiInfo.setEphemeral(true);
- wifiInfo.setAppPackageName(appPackageName);
+ wifiInfo.setRequestingPackageName(appPackageName);
wifiInfo.setRssi(rssi);
Context context = mock(Context.class);
diff --git a/packages/SystemUI/res/color/light_background.xml b/packages/SystemUI/res/color/light_background.xml
new file mode 100644
index 0000000..2effd99
--- /dev/null
+++ b/packages/SystemUI/res/color/light_background.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false"
+ android:color="@color/control_default_background" />
+ <item android:color="@color/GM2_yellow_50" />
+</selector>
diff --git a/packages/SystemUI/res/color/light_foreground.xml b/packages/SystemUI/res/color/light_foreground.xml
new file mode 100644
index 0000000..8143028
--- /dev/null
+++ b/packages/SystemUI/res/color/light_foreground.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false"
+ android:color="@color/control_default_foreground" />
+ <item android:color="@color/GM2_orange_900" />
+</selector>
diff --git a/packages/SystemUI/res/color/lock_background.xml b/packages/SystemUI/res/color/lock_background.xml
new file mode 100644
index 0000000..646fe5d
--- /dev/null
+++ b/packages/SystemUI/res/color/lock_background.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false"
+ android:color="@color/control_default_background" />
+ <item android:color="@color/GM2_blue_50" />
+</selector>
diff --git a/packages/SystemUI/res/color/lock_foreground.xml b/packages/SystemUI/res/color/lock_foreground.xml
new file mode 100644
index 0000000..3e05653
--- /dev/null
+++ b/packages/SystemUI/res/color/lock_foreground.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false"
+ android:color="@color/control_default_foreground" />
+ <item android:color="@color/GM2_blue_700" />
+</selector>
diff --git a/packages/SystemUI/res/color/unknown_foreground.xml b/packages/SystemUI/res/color/unknown_foreground.xml
new file mode 100644
index 0000000..bf028f1
--- /dev/null
+++ b/packages/SystemUI/res/color/unknown_foreground.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false"
+ android:color="@color/control_default_foreground" />
+ <item android:color="@color/GM2_blue_700" />
+ </selector>
diff --git a/packages/SystemUI/res/drawable/control_background.xml b/packages/SystemUI/res/drawable/control_background.xml
new file mode 100644
index 0000000..b246ea0
--- /dev/null
+++ b/packages/SystemUI/res/drawable/control_background.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright 2020, The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape>
+ <solid android:color="?android:attr/colorBackgroundFloating"/>
+ <corners android:radius="@dimen/control_corner_radius" />
+ </shape>
+ </item>
+ <item
+ android:id="@+id/clip_layer">
+ <clip
+ android:clipOrientation="horizontal"
+ android:drawable="@drawable/control_layer"/>
+ </item>
+</layer-list>
diff --git a/packages/SystemUI/res/drawable/control_layer.xml b/packages/SystemUI/res/drawable/control_layer.xml
new file mode 100644
index 0000000..fe8c4a4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/control_layer.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright 2020, The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@android:color/transparent"/>
+ <corners android:radius="@dimen/control_corner_radius" />
+</shape>
diff --git a/packages/SystemUI/res/drawable/control_no_favorites_background.xml b/packages/SystemUI/res/drawable/control_no_favorites_background.xml
new file mode 100644
index 0000000..1e282ad
--- /dev/null
+++ b/packages/SystemUI/res/drawable/control_no_favorites_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright 2020, The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <stroke android:width="1dp" android:color="?android:attr/colorBackgroundFloating"/>
+ <corners android:radius="@dimen/control_corner_radius" />
+</shape>
diff --git a/packages/SystemUI/res/drawable/ic_device_thermostat_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_device_thermostat_gm2_24px.xml
new file mode 100644
index 0000000..45a658f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_device_thermostat_gm2_24px.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M18,9h-5v2h5m3,-6h-8v2h8m-9,11.97c0.62,-0.83 1,-1.85 1,-2.97 0,-1.63 -0.79,-3.09 -2,-4V6c0,-1.66 -1.34,-3 -3,-3S5,4.34 5,6v6c-1.21,0.91 -2,2.37 -2,4 0,1.12 0.38,2.14 1,2.97V19h0.02c0.91,1.21 2.35,2 3.98,2s3.06,-0.79 3.98,-2H12v-0.03zM6.2,13.6L7,13V6c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v7l0.8,0.6c0.75,0.57 1.2,1.46 1.2,2.4H5c0,-0.94 0.45,-1.84 1.2,-2.4z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_light_off_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_light_off_gm2_24px.xml
new file mode 100644
index 0000000..78c3cc5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_light_off_gm2_24px.xml
@@ -0,0 +1,19 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M9,21v-1h6v1c0,0.55 -0.45,1 -1,1h-4c-0.55,0 -1,-0.45 -1,-1z"/>
+ <group>
+ <clip-path android:pathData="M0,0h24v24H0z M 0,0"/>
+ </group>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M12,2c-1.89,0 -3.6,0.75 -4.86,1.97l1.41,1.41C9.45,4.53 10.67,4 12,4c2.76,0 5,2.24 5,5 0,1.28 -0.5,2.5 -1.36,3.42l-0.02,0.02 1.41,1.41C18.25,12.6 19,10.89 19,9c0,-3.86 -3.14,-7 -7,-7z"
+ android:fillType="evenOdd"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M2.92,2.29L1.65,3.57l3.59,3.59C5.09,7.75 5,8.36 5,9c0,2.38 1.19,4.47 3,5.74V17c0,0.55 0.45,1 1,1h6c0.3,0 0.57,-0.13 0.75,-0.34L20.09,22l1.27,-1.27L2.92,2.29zM10,16v-2.3l-0.85,-0.6C7.8,12.16 7,10.63 7,9v-0.08L14.09,16H10z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_lock_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_lock_gm2_24px.xml
new file mode 100644
index 0000000..f4299e6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_lock_gm2_24px.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM9,6c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v2L9,8L9,6zM18,20L6,20L6,10h12v10zM12,17c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_lock_open_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_lock_open_gm2_24px.xml
new file mode 100644
index 0000000..59fe0a9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_lock_open_gm2_24px.xml
@@ -0,0 +1,12 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6h2c0,-1.66 1.34,-3 3,-3s3,1.34 3,3v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM18,20L6,20L6,10h12v10z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M12,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_more_vert.xml b/packages/SystemUI/res/drawable/ic_more_vert.xml
new file mode 100644
index 0000000..1309fa8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_more_vert.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_power_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_power_gm2_24px.xml
new file mode 100644
index 0000000..cd95719
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_power_gm2_24px.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M16,9v4.66l-3.5,3.51V19h-1v-1.83L8,13.65V9h8m0,-6h-2v4h-4V3H8v4h-0.01C6.9,6.99 6,7.89 6,8.98v5.52L9.5,18v3h5v-3l3.5,-3.51V9c0,-1.1 -0.9,-2 -2,-2V3z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_power_off_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_power_off_gm2_24px.xml
new file mode 100644
index 0000000..3eb7dd6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_power_off_gm2_24px.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M21.19,21.19L2.81,2.81 1.39,4.22l4.63,4.63L6,14.5 9.5,18v3h5v-3l0.34,-0.34 4.94,4.94 1.41,-1.41zM12.5,17.17L12.5,19h-1v-1.83L8,13.65v-2.83l5.42,5.42 -0.92,0.93zM11.83,9L8,5.17L8,3h2v4h4L14,3h2v4c1.1,0 2,0.9 2,2v5.49l-0.34,0.34L16,13.17L16,9h-4.17z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_power_settings_new_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_power_settings_new_gm2_24px.xml
new file mode 100644
index 0000000..f4edd87
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_power_settings_new_gm2_24px.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M11,2h2v10h-2zM18.37,5.64l-1.41,1.41c2.73,2.73 2.72,7.16 -0.01,9.89 -2.73,2.73 -7.17,2.73 -9.89,0.01 -2.73,-2.73 -2.74,-7.18 -0.01,-9.91l-1.41,-1.4c-3.51,3.51 -3.51,9.21 0.01,12.73 3.51,3.51 9.21,3.51 12.72,-0.01 3.51,-3.51 3.51,-9.2 0,-12.72z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_switches_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_switches_gm2_24px.xml
new file mode 100644
index 0000000..bb535ce
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_switches_gm2_24px.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M19,9h-8.02C10.06,7.79 8.63,7 7,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5c1.63,0 3.06,-0.79 3.98,-2H19c1.66,0 3,-1.34 3,-3S20.66,9 19,9zM19,13h-7.1c0.07,-0.32 0.1,-0.66 0.1,-1s-0.04,-0.68 -0.1,-1H19c0.55,0 1,0.45 1,1S19.55,13 19,13z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_vacuum_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_vacuum_gm2_24px.xml
new file mode 100644
index 0000000..86b9591
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_vacuum_gm2_24px.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M4,16c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3zM4,20c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1zM23,20v2h-7v-2h2.49L12.01,4.59C11.6,3.63 10.66,3 9.61,3 8.17,3 7,4.17 7,5.61L7,9h2c2.21,0 4,1.79 4,4v9L7.99,22c0.44,-0.58 0.76,-1.26 0.91,-2L11,20v-7c0,-1.1 -0.9,-2 -2,-2L4,11v3c-0.71,0 -1.39,0.15 -2,0.42L2,9h3L5,5.61C5,3.07 7.07,1 9.61,1c1.86,0 3.53,1.11 4.25,2.82L20.66,20L23,20z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_videocam_gm2_24px.xml b/packages/SystemUI/res/drawable/ic_videocam_gm2_24px.xml
new file mode 100644
index 0000000..687c9c4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_videocam_gm2_24px.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M18,10.48L18,6c0,-1.1 -0.9,-2 -2,-2L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-4.48l4,3.98v-11l-4,3.98zM16,9.69L16,18L4,18L4,6h12v3.69z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/controls_base_item.xml b/packages/SystemUI/res/layout/controls_base_item.xml
new file mode 100644
index 0000000..3c4c61e
--- /dev/null
+++ b/packages/SystemUI/res/layout/controls_base_item.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="@dimen/control_height"
+ android:padding="@dimen/control_padding"
+ android:clickable="true"
+ android:focusable="true"
+ android:layout_marginLeft="3dp"
+ android:layout_marginRight="3dp"
+ android:background="@drawable/control_background">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <TextView
+ android:id="@+id/status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="@dimen/control_status_normal"
+ android:textColor="?android:attr/textColorPrimary"
+ android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:paddingLeft="3dp"
+ app:layout_constraintBottom_toBottomOf="@+id/icon"
+ app:layout_constraintStart_toEndOf="@+id/icon" />
+
+ <TextView
+ android:id="@+id/status_extra"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="@dimen/control_status_normal"
+ android:textColor="?android:attr/textColorPrimary"
+ android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:paddingLeft="3dp"
+ app:layout_constraintBottom_toBottomOf="@+id/icon"
+ app:layout_constraintStart_toEndOf="@+id/status" />
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="18sp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:fontFamily="@*android:string/config_headlineFontFamily"
+ app:layout_constraintBottom_toTopOf="@+id/subtitle"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/icon" />
+
+ <TextView
+ android:id="@+id/subtitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="16sp"
+ android:textColor="?android:attr/textColorSecondary"
+ android:fontFamily="@*android:string/config_headlineFontFamily"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/packages/SystemUI/res/layout/controls_no_favorites.xml b/packages/SystemUI/res/layout/controls_no_favorites.xml
new file mode 100644
index 0000000..79672ca
--- /dev/null
+++ b/packages/SystemUI/res/layout/controls_no_favorites.xml
@@ -0,0 +1,18 @@
+<merge
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <TextView
+ android:id="@+id/controls_title"
+ android:text="@string/quick_controls_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:gravity="center"
+ android:textSize="25dp"
+ android:paddingTop="40dp"
+ android:paddingBottom="40dp"
+ android:layout_marginLeft="10dp"
+ android:layout_marginRight="10dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:fontFamily="@*android:string/config_headlineFontFamily"
+ android:background="@drawable/control_no_favorites_background"/>
+</merge>
diff --git a/packages/SystemUI/res/layout/controls_row.xml b/packages/SystemUI/res/layout/controls_row.xml
new file mode 100644
index 0000000..13a6b36
--- /dev/null
+++ b/packages/SystemUI/res/layout/controls_row.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/control_spacing" />
diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml
new file mode 100644
index 0000000..7804fe6
--- /dev/null
+++ b/packages/SystemUI/res/layout/controls_with_favorites.xml
@@ -0,0 +1,35 @@
+<merge
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:text="@string/quick_controls_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:gravity="center"
+ android:textSize="25dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:fontFamily="@*android:string/config_headlineFontFamily"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"/>
+ <ImageView
+ android:id="@+id/controls_more"
+ android:src="@drawable/ic_more_vert"
+ android:layout_width="34dp"
+ android:layout_height="24dp"
+ android:layout_marginEnd="10dp"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+ <LinearLayout
+ android:id="@+id/global_actions_controls_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" />
+</merge>
diff --git a/packages/SystemUI/res/layout/global_actions_grid_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_v2.xml
index 4cfb47e..6741484 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_v2.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_v2.xml
@@ -111,20 +111,7 @@
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/global_actions_panel">
- <TextView
- android:text="Home"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:gravity="center"
- android:textSize="25dp"
- android:textColor="?android:attr/textColorPrimary"
- android:fontFamily="@*android:string/config_headlineFontFamily" />
- <LinearLayout
- android:id="@+id/global_actions_controls_list"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" />
+
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 8dd2a8b..09058f2 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -200,18 +200,28 @@
<color name="GM2_grey_800">#3C4043</color>
<color name="GM2_grey_900">#202124</color>
+ <color name="GM2_red_50">#FCE8E6</color>
<color name="GM2_red_300">#F28B82</color>
<color name="GM2_red_500">#B71C1C</color>
<color name="GM2_red_700">#C5221F</color>
+ <color name="GM2_blue_50">#E8F0FE</color>
<color name="GM2_blue_200">#AECBFA</color>
<color name="GM2_blue_300">#8AB4F8</color>
+ <color name="GM2_blue_500">#FF4285F4</color>
<color name="GM2_blue_600">#1A73E8</color>
<color name="GM2_blue_700">#1967D2</color>
+ <color name="GM2_yellow_50">#FEF7E0</color>
<color name="GM2_yellow_500">#FFFBBC04</color>
+
<color name="GM2_green_500">#FF34A853</color>
- <color name="GM2_blue_500">#FF4285F4</color>
+
+ <color name="GM2_orange_900">#B06000</color>
<color name="magnification_border_color">#FF9900</color>
+
+ <!-- controls -->
+ <color name="control_default_foreground">?android:attr/textColorPrimary</color>
+ <color name="control_default_background">?android:attr/colorBackgroundFloating</color>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b40c5c0..cc58b20 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1181,5 +1181,12 @@
<dimen name="magnifier_up_down_controls_width">45dp</dimen>
<dimen name="magnifier_up_down_controls_height">40dp</dimen>
+ <!-- Home Controls -->
+ <dimen name="control_spacing">5dp</dimen>
+ <dimen name="control_corner_radius">15dp</dimen>
+ <dimen name="control_height">100dp</dimen>
+ <dimen name="control_padding">15dp</dimen>
+ <dimen name="control_status_normal">12dp</dimen>
+ <dimen name="control_status_expanded">18dp</dimen>
<dimen name="app_icon_size">32dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 44a7fda..1f13f8d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2546,4 +2546,7 @@
<string name="magnification_window_title">Magnification Window</string>
<!-- Title for Magnification Controls Window [CHAR LIMIT=NONE] -->
<string name="magnification_controls_title">Magnification Window Controls</string>
+
+ <!-- Quick Controls strings [CHAR LIMIT=30] -->
+ <string name="quick_controls_title">Quick Controls</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
new file mode 100644
index 0000000..81b5f36
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.controls.ui
+
+import android.content.Context
+import android.graphics.drawable.ClipDrawable
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.GradientDrawable
+import android.graphics.drawable.Icon
+import android.graphics.drawable.LayerDrawable
+import android.service.controls.Control
+import android.service.controls.DeviceTypes
+import android.service.controls.actions.BooleanAction
+import android.service.controls.actions.ControlAction
+import android.service.controls.actions.FloatAction
+import android.service.controls.templates.ControlTemplate
+import android.service.controls.templates.RangeTemplate
+import android.service.controls.templates.ToggleRangeTemplate
+import android.service.controls.templates.ToggleTemplate
+import android.util.TypedValue
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+
+import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.R
+
+private const val MIN_LEVEL = 0
+private const val MAX_LEVEL = 10000
+
+class ControlViewHolder(
+ val layout: ViewGroup,
+ val controlsController: ControlsController
+) {
+ val icon: ImageView = layout.requireViewById(R.id.icon)
+ val status: TextView = layout.requireViewById(R.id.status)
+ val statusExtra: TextView = layout.requireViewById(R.id.status_extra)
+ val title: TextView = layout.requireViewById(R.id.title)
+ val subtitle: TextView = layout.requireViewById(R.id.subtitle)
+ val context: Context = layout.getContext()
+ val clipLayer: ClipDrawable
+ val gd: GradientDrawable
+ lateinit var cws: ControlWithState
+
+ init {
+ val ld = layout.getBackground() as LayerDrawable
+ ld.mutate()
+ clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable
+ gd = clipLayer.getDrawable() as GradientDrawable
+ }
+
+ fun bindData(cws: ControlWithState) {
+ this.cws = cws
+
+ val (status, template) = cws.control?.let {
+ title.setText(it.getTitle())
+ subtitle.setText(it.getSubtitle())
+ Pair(it.getStatus(), it.getControlTemplate())
+ } ?: run {
+ title.setText(cws.ci.controlTitle)
+ subtitle.setText("")
+ Pair(Control.STATUS_UNKNOWN, ControlTemplate.NO_TEMPLATE)
+ }
+
+ findBehavior(status, template).apply(this, cws)
+ }
+
+ fun action(action: ControlAction) {
+ controlsController.action(cws.ci, action)
+ }
+
+ private fun findBehavior(status: Int, template: ControlTemplate): Behavior {
+ return when {
+ status == Control.STATUS_UNKNOWN -> UnknownBehavior()
+ template is ToggleTemplate -> ToggleTemplateBehavior()
+ template is ToggleRangeTemplate -> ToggleRangeTemplateBehavior()
+ else -> {
+ object : Behavior {
+ override fun apply(cvh: ControlViewHolder, cws: ControlWithState) {
+ cvh.status.setText(cws.control?.getStatusText())
+ cvh.applyRenderInfo(findRenderInfo(cws.ci.deviceType, false))
+ }
+ }
+ }
+ }
+ }
+
+ internal fun applyRenderInfo(ri: RenderInfo) {
+ val fg = context.getResources().getColorStateList(ri.foreground, context.getTheme())
+ val bg = context.getResources().getColorStateList(ri.background, context.getTheme())
+ status.setTextColor(fg)
+ statusExtra.setTextColor(fg)
+
+ icon.setImageIcon(Icon.createWithResource(context, ri.iconResourceId))
+ icon.setImageTintList(fg)
+
+ gd.setColor(bg)
+ }
+
+ fun setEnabled(enabled: Boolean) {
+ status.setEnabled(enabled)
+ icon.setEnabled(enabled)
+ }
+}
+
+private interface Behavior {
+ fun apply(cvh: ControlViewHolder, cws: ControlWithState)
+
+ fun findRenderInfo(deviceType: Int, isActive: Boolean): RenderInfo =
+ deviceRenderMap.getOrDefault(deviceType, unknownDeviceMap).getValue(isActive)
+}
+
+private class UnknownBehavior : Behavior {
+ override fun apply(cvh: ControlViewHolder, cws: ControlWithState) {
+ cvh.status.setText("Loading...")
+ cvh.applyRenderInfo(findRenderInfo(cws.ci.deviceType, false))
+ }
+}
+
+private class ToggleRangeTemplateBehavior : Behavior {
+ lateinit var clipLayer: Drawable
+ lateinit var template: ToggleRangeTemplate
+ lateinit var control: Control
+ lateinit var cvh: ControlViewHolder
+ lateinit var rangeTemplate: RangeTemplate
+ lateinit var statusExtra: TextView
+ lateinit var status: TextView
+ lateinit var context: Context
+
+ override fun apply(cvh: ControlViewHolder, cws: ControlWithState) {
+ this.control = cws.control!!
+ this.cvh = cvh
+
+ statusExtra = cvh.statusExtra
+ status = cvh.status
+
+ status.setText(control.getStatusText())
+
+ context = status.getContext()
+
+ cvh.layout.setOnTouchListener(ToggleRangeTouchListener())
+
+ val ld = cvh.layout.getBackground() as LayerDrawable
+ clipLayer = ld.findDrawableByLayerId(R.id.clip_layer)
+
+ template = control.getControlTemplate() as ToggleRangeTemplate
+ rangeTemplate = template.getRange()
+
+ val checked = template.isChecked()
+ val deviceType = control.getDeviceType()
+
+ updateRange((rangeTemplate.getCurrentValue() / 100.0f), checked)
+
+ cvh.setEnabled(checked)
+ cvh.applyRenderInfo(findRenderInfo(deviceType, checked))
+ }
+
+ fun toggle() {
+ cvh.action(BooleanAction(template.getTemplateId(), !template.isChecked()))
+
+ val nextLevel = if (template.isChecked()) MIN_LEVEL else MAX_LEVEL
+ clipLayer.setLevel(nextLevel)
+ }
+
+ fun beginUpdateRange() {
+ status.setVisibility(View.GONE)
+ statusExtra.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
+ .getDimensionPixelSize(R.dimen.control_status_expanded).toFloat())
+ }
+
+ fun updateRange(f: Float, checked: Boolean) {
+ clipLayer.setLevel(if (checked) (MAX_LEVEL * f).toInt() else MIN_LEVEL)
+
+ if (checked && f < 100.0f && f > 0.0f) {
+ statusExtra.setText("" + (f * 100.0).toInt() + "%")
+ statusExtra.setVisibility(View.VISIBLE)
+ } else {
+ statusExtra.setText("")
+ statusExtra.setVisibility(View.GONE)
+ }
+ }
+
+ fun endUpdateRange(f: Float) {
+ statusExtra.setText(" - " + (f * 100.0).toInt() + "%")
+
+ val newValue = rangeTemplate.getMinValue() +
+ (f * (rangeTemplate.getMaxValue() - rangeTemplate.getMinValue()))
+
+ statusExtra.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
+ .getDimensionPixelSize(R.dimen.control_status_normal).toFloat())
+ status.setVisibility(View.VISIBLE)
+
+ cvh.action(FloatAction(rangeTemplate.getTemplateId(), findNearestStep(newValue)))
+ }
+
+ fun findNearestStep(value: Float): Float {
+ var minDiff = 1000f
+
+ var f = rangeTemplate.getMinValue()
+ while (f <= rangeTemplate.getMaxValue()) {
+ val currentDiff = Math.abs(value - f)
+ if (currentDiff < minDiff) {
+ minDiff = currentDiff
+ } else {
+ return f - rangeTemplate.getStepValue()
+ }
+
+ f += rangeTemplate.getStepValue()
+ }
+
+ return rangeTemplate.getMaxValue()
+ }
+
+ inner class ToggleRangeTouchListener() : View.OnTouchListener {
+ private var initialTouchX: Float = 0.0f
+ private var initialTouchY: Float = 0.0f
+ private var isDragging: Boolean = false
+ private val minDragDiff = 20
+
+ override fun onTouch(v: View, e: MotionEvent): Boolean {
+ when (e.getActionMasked()) {
+ MotionEvent.ACTION_DOWN -> setupTouch(e)
+ MotionEvent.ACTION_MOVE -> detectDrag(v, e)
+ MotionEvent.ACTION_UP -> endTouch(v, e)
+ }
+
+ return true
+ }
+
+ private fun setupTouch(e: MotionEvent) {
+ initialTouchX = e.getX()
+ initialTouchY = e.getY()
+ }
+
+ private fun detectDrag(v: View, e: MotionEvent) {
+ val xDiff = Math.abs(e.getX() - initialTouchX)
+ val yDiff = Math.abs(e.getY() - initialTouchY)
+
+ if (xDiff < minDragDiff) {
+ isDragging = false
+ } else {
+ if (!isDragging) {
+ this@ToggleRangeTemplateBehavior.beginUpdateRange()
+ }
+ v.getParent().requestDisallowInterceptTouchEvent(true)
+ isDragging = true
+ if (yDiff > xDiff) {
+ endTouch(v, e)
+ } else {
+ val percent = Math.max(0.0f, Math.min(1.0f, e.getX() / v.getWidth()))
+ this@ToggleRangeTemplateBehavior.updateRange(percent, true)
+ }
+ }
+ }
+
+ private fun endTouch(v: View, e: MotionEvent) {
+ if (!isDragging) {
+ this@ToggleRangeTemplateBehavior.toggle()
+ } else {
+ val percent = Math.max(0.0f, Math.min(1.0f, e.getX() / v.getWidth()))
+ this@ToggleRangeTemplateBehavior.endUpdateRange(percent)
+ }
+
+ initialTouchX = 0.0f
+ initialTouchY = 0.0f
+ isDragging = false
+ }
+ }
+}
+
+private class ToggleTemplateBehavior : Behavior {
+ lateinit var clipLayer: Drawable
+ lateinit var template: ToggleTemplate
+ lateinit var control: Control
+ lateinit var cvh: ControlViewHolder
+ lateinit var context: Context
+ lateinit var status: TextView
+
+ override fun apply(cvh: ControlViewHolder, cws: ControlWithState) {
+ this.control = cws.control!!
+ this.cvh = cvh
+ status = cvh.status
+
+ status.setText(control.getStatusText())
+
+ cvh.layout.setOnClickListener(View.OnClickListener() { toggle() })
+
+ val ld = cvh.layout.getBackground() as LayerDrawable
+ clipLayer = ld.findDrawableByLayerId(R.id.clip_layer)
+
+ template = control.getControlTemplate() as ToggleTemplate
+
+ val checked = template.isChecked()
+ val deviceType = control.getDeviceType()
+
+ clipLayer.setLevel(if (checked) MAX_LEVEL else MIN_LEVEL)
+ cvh.setEnabled(checked)
+ cvh.applyRenderInfo(findRenderInfo(deviceType, checked))
+ }
+
+ fun toggle() {
+ cvh.action(BooleanAction(template.getTemplateId(), !template.isChecked()))
+
+ val nextLevel = if (template.isChecked()) MIN_LEVEL else MAX_LEVEL
+ clipLayer.setLevel(nextLevel)
+ }
+}
+
+internal data class RenderInfo(val iconResourceId: Int, val foreground: Int, val background: Int)
+
+private val unknownDeviceMap = mapOf(
+ false to RenderInfo(
+ R.drawable.ic_light_off_gm2_24px,
+ R.color.unknown_foreground,
+ R.color.unknown_foreground),
+ true to RenderInfo(
+ R.drawable.ic_lightbulb_outline_gm2_24px,
+ R.color.unknown_foreground,
+ R.color.unknown_foreground)
+)
+
+private val deviceRenderMap = mapOf<Int, Map<Boolean, RenderInfo>>(
+ DeviceTypes.TYPE_UNKNOWN to unknownDeviceMap,
+ DeviceTypes.TYPE_LIGHT to mapOf(
+ false to RenderInfo(
+ R.drawable.ic_light_off_gm2_24px,
+ R.color.light_foreground,
+ R.color.light_background),
+ true to RenderInfo(
+ R.drawable.ic_lightbulb_outline_gm2_24px,
+ R.color.light_foreground,
+ R.color.light_background)
+ ),
+ DeviceTypes.TYPE_THERMOSTAT to mapOf(
+ false to RenderInfo(
+ R.drawable.ic_device_thermostat_gm2_24px,
+ R.color.light_foreground,
+ R.color.light_background),
+ true to RenderInfo(
+ R.drawable.ic_device_thermostat_gm2_24px,
+ R.color.light_foreground,
+ R.color.light_background)
+ ),
+ DeviceTypes.TYPE_CAMERA to mapOf(
+ false to RenderInfo(
+ R.drawable.ic_videocam_gm2_24px,
+ R.color.light_foreground,
+ R.color.light_background),
+ true to RenderInfo(
+ R.drawable.ic_videocam_gm2_24px,
+ R.color.light_foreground,
+ R.color.light_background)
+ ),
+ DeviceTypes.TYPE_LOCK to mapOf(
+ false to RenderInfo(
+ R.drawable.ic_lock_open_gm2_24px,
+ R.color.lock_foreground,
+ R.color.lock_background),
+ true to RenderInfo(
+ R.drawable.ic_lock_gm2_24px,
+ R.color.lock_foreground,
+ R.color.lock_background)
+ ),
+ DeviceTypes.TYPE_SWITCH to mapOf(
+ false to RenderInfo(
+ R.drawable.ic_switches_gm2_24px,
+ R.color.lock_foreground,
+ R.color.lock_background),
+ true to RenderInfo(
+ R.drawable.ic_switches_gm2_24px,
+ R.color.lock_foreground,
+ R.color.lock_background)
+ ),
+ DeviceTypes.TYPE_OUTLET to mapOf(
+ false to RenderInfo(
+ R.drawable.ic_power_off_gm2_24px,
+ R.color.lock_foreground,
+ R.color.lock_background),
+ true to RenderInfo(
+ R.drawable.ic_power_gm2_24px,
+ R.color.lock_foreground,
+ R.color.lock_background)
+ )
+)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlWithState.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlWithState.kt
new file mode 100644
index 0000000..816f0b2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlWithState.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.controls.ui
+
+import android.service.controls.Control
+
+import com.android.systemui.controls.controller.ControlInfo
+
+/**
+ * A container for:
+ * <ul>
+ * <li>ControlInfo - Basic cached info about a Control
+ * <li>Control - Actual Control parcelable received directly from
+ * the participating application
+ * </ul>
+ */
+data class ControlWithState(val ci: ControlInfo, val control: Control?)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
index 0270c2b..b07a75d 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
@@ -19,12 +19,15 @@
import android.content.ComponentName
import android.service.controls.Control
import android.service.controls.actions.ControlAction
+import android.view.ViewGroup
interface ControlsUiController {
+ fun show(parent: ViewGroup)
+ fun hide()
fun onRefreshState(componentName: ComponentName, controls: List<Control>)
fun onActionResponse(
componentName: ComponentName,
controlId: String,
@ControlAction.ResponseResult response: Int
)
-}
\ No newline at end of file
+}
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 0ace126..926fb6e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -16,19 +16,204 @@
package com.android.systemui.controls.ui
+import android.accounts.Account
+import android.accounts.AccountManager
import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.ServiceConnection
+import android.os.IBinder
import android.service.controls.Control
+import android.service.controls.TokenProvider
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+
+import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.controls.controller.ControlInfo
+import com.android.systemui.controls.management.ControlsProviderSelectorActivity
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.R
+
+import dagger.Lazy
+
+import java.util.concurrent.Executor
import javax.inject.Inject
import javax.inject.Singleton
+private const val TAG = "ControlsUi"
+
+// TEMP CODE for MOCK
+private const val TOKEN = "https://www.googleapis.com/auth/assistant"
+private const val SCOPE = "oauth2:" + TOKEN
+private var tokenProviderConnection: TokenProviderConnection? = null
+class TokenProviderConnection(val cc: ControlsController, val context: Context)
+ : ServiceConnection {
+ private var mTokenProvider: TokenProvider? = null
+
+ override fun onServiceConnected(cName: ComponentName, binder: IBinder) {
+ Thread({
+ Log.i(TAG, "TokenProviderConnection connected")
+ mTokenProvider = TokenProvider.Stub.asInterface(binder)
+
+ val mLastAccountName = mTokenProvider?.getAccountName()
+
+ if (mLastAccountName == null || mLastAccountName.isEmpty()) {
+ Log.e(TAG, "NO ACCOUNT IS SET. Open HomeMock app")
+ } else {
+ mTokenProvider?.setAuthToken(getAuthToken(mLastAccountName))
+ cc.subscribeToFavorites()
+ }
+ }, "TokenProviderThread").start()
+ }
+
+ override fun onServiceDisconnected(cName: ComponentName) {
+ mTokenProvider = null
+ }
+
+ fun getAuthToken(accountName: String): String? {
+ val am = AccountManager.get(context)
+ val accounts = am.getAccountsByType("com.google")
+ if (accounts == null || accounts.size == 0) {
+ Log.w(TAG, "No com.google accounts found")
+ return null
+ }
+
+ var account: Account? = null
+ for (a in accounts) {
+ if (a.name.equals(accountName)) {
+ account = a
+ break
+ }
+ }
+
+ if (account == null) {
+ account = accounts[0]
+ }
+
+ try {
+ return am.blockingGetAuthToken(account!!, SCOPE, true)
+ } catch (e: Throwable) {
+ Log.e(TAG, "Error getting auth token", e)
+ return null
+ }
+ }
+}
+
@Singleton
-class ControlsUiControllerImpl @Inject constructor() : ControlsUiController {
+class ControlsUiControllerImpl @Inject constructor (
+ val controlsController: Lazy<ControlsController>,
+ val context: Context,
+ @Main val uiExecutor: Executor
+) : ControlsUiController {
+
+ private lateinit var controlInfos: List<ControlInfo>
+ private val controlsById = mutableMapOf<Pair<ComponentName, String>, ControlWithState>()
+ private val controlViewsById = mutableMapOf<String, ControlViewHolder>()
+ private lateinit var parent: ViewGroup
+
+ override fun show(parent: ViewGroup) {
+ Log.d(TAG, "show()")
+
+ this.parent = parent
+
+ controlInfos = controlsController.get().getFavoriteControls()
+
+ controlInfos.map {
+ ControlWithState(it, null)
+ }.associateByTo(controlsById) { Pair(it.ci.component, it.ci.controlId) }
+
+ if (controlInfos.isEmpty()) {
+ showInitialSetupView()
+ } else {
+ showControlsView()
+ }
+
+ // Temp code to pass auth
+ tokenProviderConnection = TokenProviderConnection(controlsController.get(), context)
+ val serviceIntent = Intent()
+ serviceIntent.setComponent(ComponentName("com.android.systemui.home.mock",
+ "com.android.systemui.home.mock.AuthService"))
+ context.bindService(serviceIntent, tokenProviderConnection!!, Context.BIND_AUTO_CREATE)
+ }
+
+ private fun showInitialSetupView() {
+ val inflater = LayoutInflater.from(context)
+ inflater.inflate(R.layout.controls_no_favorites, parent, true)
+
+ val textView = parent.requireViewById(R.id.controls_title) as TextView
+ textView.setOnClickListener {
+ val i = Intent()
+ i.setComponent(ComponentName(context, ControlsProviderSelectorActivity::class.java))
+ i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ context.startActivity(i)
+ }
+ }
+
+ private fun showControlsView() {
+ val inflater = LayoutInflater.from(context)
+ inflater.inflate(R.layout.controls_with_favorites, parent, true)
+
+ val listView = parent.requireViewById(R.id.global_actions_controls_list) as ViewGroup
+ var lastRow: ViewGroup = createRow(inflater, listView)
+ controlInfos.forEach {
+ Log.d(TAG, "favorited control id: " + it.controlId)
+ if (lastRow.getChildCount() == 2) {
+ lastRow = createRow(inflater, listView)
+ }
+ val item = inflater.inflate(
+ R.layout.controls_base_item, lastRow, false) as ViewGroup
+ lastRow.addView(item)
+ val cvh = ControlViewHolder(item, controlsController.get())
+ cvh.bindData(controlsById.get(Pair(it.component, it.controlId))!!)
+ controlViewsById.put(it.controlId, cvh)
+ }
+
+ val moreImageView = parent.requireViewById(R.id.controls_more) as View
+ moreImageView.setOnClickListener {
+ val i = Intent()
+ i.setComponent(ComponentName(context, ControlsProviderSelectorActivity::class.java))
+ i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ context.startActivity(i)
+ }
+ }
+
+ override fun hide() {
+ Log.d(TAG, "hide()")
+ controlsController.get().unsubscribe()
+ context.unbindService(tokenProviderConnection)
+ tokenProviderConnection = null
+
+ parent.removeAllViews()
+ controlsById.clear()
+ controlViewsById.clear()
+ }
override fun onRefreshState(componentName: ComponentName, controls: List<Control>) {
- TODO("not implemented")
+ Log.d(TAG, "onRefreshState()")
+ controls.forEach { c ->
+ controlsById.get(Pair(componentName, c.getControlId()))?.let {
+ Log.d(TAG, "onRefreshState() for id: " + c.getControlId())
+ val cws = ControlWithState(it.ci, c)
+ controlsById.put(Pair(componentName, c.getControlId()), cws)
+
+ uiExecutor.execute {
+ controlViewsById.get(c.getControlId())?.bindData(cws)
+ }
+ }
+ }
}
override fun onActionResponse(componentName: ComponentName, controlId: String, response: Int) {
+ Log.d(TAG, "onActionResponse()")
TODO("not implemented")
}
-}
\ No newline at end of file
+
+ private fun createRow(inflater: LayoutInflater, parent: ViewGroup): ViewGroup {
+ val row = inflater.inflate(R.layout.controls_row, parent, false) as ViewGroup
+ parent.addView(row)
+ return row
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 83f6d45..80d776a 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -93,12 +93,13 @@
import com.android.systemui.MultiListLayout.MultiListAdapter;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.controls.ui.ControlsUiController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
import com.android.systemui.plugins.GlobalActionsPanelPlugin;
-import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.BlurUtils;
+import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -183,6 +184,7 @@
private final IStatusBarService mStatusBarService;
private final NotificationShadeWindowController mNotificationShadeWindowController;
private GlobalActionsPanelPlugin mPanelPlugin;
+ private ControlsUiController mControlsUiController;
/**
* @param context everything needs a context :(
@@ -200,7 +202,8 @@
TelecomManager telecomManager, MetricsLogger metricsLogger,
BlurUtils blurUtils, SysuiColorExtractor colorExtractor,
IStatusBarService statusBarService,
- NotificationShadeWindowController notificationShadeWindowController) {
+ NotificationShadeWindowController notificationShadeWindowController,
+ ControlsUiController controlsUiController) {
mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
mWindowManagerFuncs = windowManagerFuncs;
mAudioManager = audioManager;
@@ -220,6 +223,7 @@
mSysuiColorExtractor = colorExtractor;
mStatusBarService = statusBarService;
mNotificationShadeWindowController = notificationShadeWindowController;
+ mControlsUiController = controlsUiController;
// receive broadcasts
IntentFilter filter = new IntentFilter();
@@ -455,9 +459,12 @@
mKeyguardManager.isDeviceLocked())
: null;
+ boolean showControls = !mKeyguardManager.isDeviceLocked() && isControlsEnabled(mContext);
+
ActionsDialog dialog = new ActionsDialog(mContext, mAdapter, panelViewController,
mBlurUtils, mSysuiColorExtractor, mStatusBarService,
- mNotificationShadeWindowController, isControlsEnabled(mContext));
+ mNotificationShadeWindowController,
+ showControls ? mControlsUiController : null);
dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
dialog.setKeyguardShowing(mKeyguardShowing);
@@ -1543,13 +1550,15 @@
private boolean mHadTopUi;
private final NotificationShadeWindowController mNotificationShadeWindowController;
private final BlurUtils mBlurUtils;
- private final boolean mControlsEnabled;
+
+ private ControlsUiController mControlsUiController;
+ private ViewGroup mControlsView;
ActionsDialog(Context context, MyAdapter adapter,
GlobalActionsPanelPlugin.PanelViewController plugin, BlurUtils blurUtils,
SysuiColorExtractor sysuiColorExtractor, IStatusBarService statusBarService,
NotificationShadeWindowController notificationShadeWindowController,
- boolean controlsEnabled) {
+ ControlsUiController controlsUiController) {
super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
mContext = context;
mAdapter = adapter;
@@ -1557,7 +1566,7 @@
mColorExtractor = sysuiColorExtractor;
mStatusBarService = statusBarService;
mNotificationShadeWindowController = notificationShadeWindowController;
- mControlsEnabled = controlsEnabled;
+ mControlsUiController = controlsUiController;
// Window initialization
Window window = getWindow();
@@ -1639,6 +1648,7 @@
private void initializeLayout() {
setContentView(getGlobalActionsLayoutId(mContext));
fixNavBarClipping();
+ mControlsView = findViewById(com.android.systemui.R.id.global_actions_controls);
mGlobalActionsLayout = findViewById(com.android.systemui.R.id.global_actions_view);
mGlobalActionsLayout.setOutsideTouchListener(view -> dismiss());
((View) mGlobalActionsLayout.getParent()).setOnClickListener(view -> dismiss());
@@ -1674,7 +1684,7 @@
}
private int getGlobalActionsLayoutId(Context context) {
- if (mControlsEnabled) {
+ if (mControlsUiController != null) {
return com.android.systemui.R.layout.global_actions_grid_v2;
}
@@ -1758,6 +1768,9 @@
mBlurUtils.radiusForRatio(animatedValue));
})
.start();
+ if (mControlsUiController != null) {
+ mControlsUiController.show(mControlsView);
+ }
}
@Override
@@ -1766,6 +1779,7 @@
return;
}
mShowing = false;
+ if (mControlsUiController != null) mControlsUiController.hide();
mGlobalActionsLayout.setTranslationX(0);
mGlobalActionsLayout.setTranslationY(0);
mGlobalActionsLayout.setAlpha(1);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 2fc7a9c..14eec59 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -18,6 +18,7 @@
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
@@ -53,6 +54,7 @@
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -371,6 +373,7 @@
private boolean mPulsing;
private boolean mLockLater;
+ private boolean mShowHomeOverLockscreen;
private boolean mWakeAndUnlocking;
private IKeyguardDrawnCallback mDrawnCallback;
@@ -703,6 +706,20 @@
mStatusBarKeyguardViewManagerLazy = statusBarKeyguardViewManagerLazy;
mDismissCallbackRegistry = dismissCallbackRegistry;
mUiBgExecutor = uiBgExecutor;
+ mShowHomeOverLockscreen = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN,
+ /* defaultValue = */ true);
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, mHandler::post,
+ new DeviceConfig.OnPropertiesChangedListener() {
+ @Override
+ public void onPropertiesChanged(DeviceConfig.Properties properties) {
+ if (properties.getKeyset().contains(NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN)) {
+ mShowHomeOverLockscreen = properties.getBoolean(
+ NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN, true /* defaultValue */);
+ }
+ }
+ });
}
public void userActivity() {
@@ -1972,7 +1989,10 @@
// windows that appear on top, ever
int flags = StatusBarManager.DISABLE_NONE;
if (forceHideHomeRecentsButtons || isShowingAndNotOccluded()) {
- flags |= StatusBarManager.DISABLE_HOME | StatusBarManager.DISABLE_RECENT;
+ if (!mShowHomeOverLockscreen) {
+ flags |= StatusBarManager.DISABLE_HOME;
+ }
+ flags |= StatusBarManager.DISABLE_RECENT;
}
if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 3e3ef0c..9e64748 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -302,14 +302,14 @@
mForceNavBarHandleOpaque = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_SYSTEMUI,
NAV_BAR_HANDLE_FORCE_OPAQUE,
- /* defaultValue = */ false);
+ /* defaultValue = */ true);
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, mHandler::post,
new DeviceConfig.OnPropertiesChangedListener() {
@Override
public void onPropertiesChanged(DeviceConfig.Properties properties) {
if (properties.getKeyset().contains(NAV_BAR_HANDLE_FORCE_OPAQUE)) {
mForceNavBarHandleOpaque = properties.getBoolean(
- NAV_BAR_HANDLE_FORCE_OPAQUE, /* defaultValue = */ false);
+ NAV_BAR_HANDLE_FORCE_OPAQUE, /* defaultValue = */ true);
}
}
});
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index cf996a5..fa91620 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -567,39 +567,41 @@
final long lastRxMs = mLastInfo.getControllerRxDurationMillis();
final long lastEnergy = mLastInfo.getControllerEnergyUsedMicroJoules();
- // We will modify the last info object to be the delta, and store the new
- // WifiActivityEnergyInfo object as our last one.
- final WifiActivityEnergyInfo delta = mLastInfo;
- delta.setTimeSinceBootMillis(latest.getTimeSinceBootMillis());
- delta.setStackState(latest.getStackState());
+ final long deltaTimeSinceBootMillis = latest.getTimeSinceBootMillis();
+ final int deltaStackState = latest.getStackState();
+ final long deltaControllerTxDurationMillis;
+ final long deltaControllerRxDurationMillis;
+ final long deltaControllerScanDurationMillis;
+ final long deltaControllerIdleDurationMillis;
+ final long deltaControllerEnergyUsedMicroJoules;
final long txTimeMs = latest.getControllerTxDurationMillis() - lastTxMs;
final long rxTimeMs = latest.getControllerRxDurationMillis() - lastRxMs;
final long idleTimeMs = latest.getControllerIdleDurationMillis() - lastIdleMs;
final long scanTimeMs = latest.getControllerScanDurationMillis() - lastScanMs;
+ final boolean wasReset;
if (txTimeMs < 0 || rxTimeMs < 0 || scanTimeMs < 0 || idleTimeMs < 0) {
// The stats were reset by the WiFi system (which is why our delta is negative).
// Returns the unaltered stats. The total on time should not exceed the time
- // duartion between reports.
+ // duration between reports.
final long totalOnTimeMs = latest.getControllerTxDurationMillis()
+ latest.getControllerRxDurationMillis()
+ latest.getControllerIdleDurationMillis();
if (totalOnTimeMs <= timePeriodMs + MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS) {
- delta.setControllerEnergyUsedMicroJoules(
- latest.getControllerEnergyUsedMicroJoules());
- delta.setControllerRxDurationMillis(latest.getControllerRxDurationMillis());
- delta.setControllerTxDurationMillis(latest.getControllerTxDurationMillis());
- delta.setControllerIdleDurationMillis(latest.getControllerIdleDurationMillis());
- delta.setControllerScanDurationMillis(latest.getControllerScanDurationMillis());
+ deltaControllerEnergyUsedMicroJoules = latest.getControllerEnergyUsedMicroJoules();
+ deltaControllerRxDurationMillis = latest.getControllerRxDurationMillis();
+ deltaControllerTxDurationMillis = latest.getControllerTxDurationMillis();
+ deltaControllerIdleDurationMillis = latest.getControllerIdleDurationMillis();
+ deltaControllerScanDurationMillis = latest.getControllerScanDurationMillis();
} else {
- delta.setControllerEnergyUsedMicroJoules(0);
- delta.setControllerRxDurationMillis(0);
- delta.setControllerTxDurationMillis(0);
- delta.setControllerIdleDurationMillis(0);
- delta.setControllerScanDurationMillis(0);
+ deltaControllerEnergyUsedMicroJoules = 0;
+ deltaControllerRxDurationMillis = 0;
+ deltaControllerTxDurationMillis = 0;
+ deltaControllerIdleDurationMillis = 0;
+ deltaControllerScanDurationMillis = 0;
}
- Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + delta);
+ wasReset = true;
} else {
final long totalActiveTimeMs = txTimeMs + rxTimeMs;
long maxExpectedIdleTimeMs;
@@ -634,21 +636,33 @@
maxExpectedIdleTimeMs = timePeriodMs - totalActiveTimeMs;
}
// These times seem to be the most reliable.
- delta.setControllerTxDurationMillis(txTimeMs);
- delta.setControllerRxDurationMillis(rxTimeMs);
- delta.setControllerScanDurationMillis(scanTimeMs);
+ deltaControllerTxDurationMillis = txTimeMs;
+ deltaControllerRxDurationMillis = rxTimeMs;
+ deltaControllerScanDurationMillis = scanTimeMs;
// WiFi calculates the idle time as a difference from the on time and the various
// Rx + Tx times. There seems to be some missing time there because this sometimes
// becomes negative. Just cap it at 0 and ensure that it is less than the expected idle
// time from the difference in timestamps.
// b/21613534
- delta.setControllerIdleDurationMillis(
- Math.min(maxExpectedIdleTimeMs, Math.max(0, idleTimeMs)));
- delta.setControllerEnergyUsedMicroJoules(
- Math.max(0, latest.getControllerEnergyUsedMicroJoules() - lastEnergy));
+ deltaControllerIdleDurationMillis =
+ Math.min(maxExpectedIdleTimeMs, Math.max(0, idleTimeMs));
+ deltaControllerEnergyUsedMicroJoules =
+ Math.max(0, latest.getControllerEnergyUsedMicroJoules() - lastEnergy);
+ wasReset = false;
}
mLastInfo = latest;
+ WifiActivityEnergyInfo delta = new WifiActivityEnergyInfo(
+ deltaTimeSinceBootMillis,
+ deltaStackState,
+ deltaControllerTxDurationMillis,
+ deltaControllerRxDurationMillis,
+ deltaControllerScanDurationMillis,
+ deltaControllerIdleDurationMillis,
+ deltaControllerEnergyUsedMicroJoules);
+ if (wasReset) {
+ Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + delta);
+ }
return delta;
}
}
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index aa39926..6ff2767 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -87,7 +87,7 @@
}
BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
luxLevels, brightnessLevelsNits);
- builder.setShortTermModelTimeout(shortTermModelTimeout);
+ builder.setShortTermModelTimeoutMillis(shortTermModelTimeout);
builder.setShortTermModelLowerLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
builder.setShortTermModelUpperLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange,
@@ -739,10 +739,10 @@
@Override
public long getShortTermModelTimeout() {
- if (mConfig.getShortTermModelTimeout() >= 0) {
- return mConfig.getShortTermModelTimeout();
+ if (mConfig.getShortTermModelTimeoutMillis() >= 0) {
+ return mConfig.getShortTermModelTimeoutMillis();
} else {
- return mDefaultConfig.getShortTermModelTimeout();
+ return mDefaultConfig.getShortTermModelTimeoutMillis();
}
}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 39d1a51..92e5a01 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -1268,6 +1268,7 @@
continue;
}
StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
.writeInt(managedProcess.uid)
.writeString(managedProcess.processName)
.writeInt(managedProcess.pid)
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index 1c88c40..e724e60 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -20,6 +20,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -27,6 +28,9 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.server.job.JobSchedulerService.FREQUENT_INDEX;
+import static com.android.server.job.JobSchedulerService.RARE_INDEX;
+import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -568,6 +572,48 @@
assertFalse(controller.isStandbyExceptionRequestedLocked(UID_RED));
}
+ @Test
+ public void testRestrictedJobTracking() {
+ final JobStatus networked = createJobStatus(createJob()
+ .setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1), 0)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_CELLULAR), UID_RED);
+ final JobStatus unnetworked = createJobStatus(createJob(), UID_BLUE);
+ networked.setStandbyBucket(FREQUENT_INDEX);
+ unnetworked.setStandbyBucket(FREQUENT_INDEX);
+
+ final Network cellularNet = new Network(101);
+ final NetworkCapabilities cellularCaps =
+ createCapabilities().addTransportType(TRANSPORT_CELLULAR);
+ reset(mConnManager);
+ answerNetwork(UID_RED, cellularNet, cellularCaps);
+ answerNetwork(UID_BLUE, cellularNet, cellularCaps);
+
+ final ConnectivityController controller = new ConnectivityController(mService);
+ controller.maybeStartTrackingJobLocked(networked, null);
+ controller.maybeStartTrackingJobLocked(unnetworked, null);
+
+ assertTrue(networked.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertFalse(unnetworked.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+
+ networked.setStandbyBucket(RESTRICTED_INDEX);
+ unnetworked.setStandbyBucket(RESTRICTED_INDEX);
+ controller.startTrackingRestrictedJobLocked(networked);
+ controller.startTrackingRestrictedJobLocked(unnetworked);
+ assertFalse(networked.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ // Unnetworked shouldn't be affected by ConnectivityController since it doesn't have a
+ // connectivity constraint.
+ assertFalse(unnetworked.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+
+ networked.setStandbyBucket(RARE_INDEX);
+ unnetworked.setStandbyBucket(RARE_INDEX);
+ controller.stopTrackingRestrictedJobLocked(networked);
+ controller.stopTrackingRestrictedJobLocked(unnetworked);
+ assertTrue(networked.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ // Unnetworked shouldn't be affected by ConnectivityController since it doesn't have a
+ // connectivity constraint.
+ assertFalse(unnetworked.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ }
+
private void answerNetwork(int uid, Network net, NetworkCapabilities caps) {
when(mConnManager.getActiveNetworkForUid(eq(uid))).thenReturn(net);
when(mConnManager.getNetworkCapabilities(eq(net))).thenReturn(caps);
diff --git a/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java b/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java
index 4d229ef..625766a 100644
--- a/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java
+++ b/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java
@@ -157,6 +157,8 @@
String expected =
"TestThread2 annotated stack trace:\n" +
" at java.lang.Object.wait(Native Method)\n" +
+ " at java.lang.Object.wait(Object.java:442)\n" +
+ " at java.lang.Object.wait(Object.java:568)\n" +
" at com.android.server.WatchdogDiagnosticsTest$TestThread2.y(" +
"WatchdogDiagnosticsTest.java:91)\n" +
" - locked <HASH> (a java.lang.String)\n" +
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index acf51f3..f54f8d1 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -265,6 +265,29 @@
public static final String EVENT_HANDOVER_FAILED =
"android.telecom.event.HANDOVER_FAILED";
+
+ /**
+ * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
+ * call because they have declined to answer it. This typically means that they are unable
+ * to answer the call at this time and would prefer it be sent to voicemail.
+ */
+ public static final int REJECT_REASON_DECLINED = 1;
+
+ /**
+ * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
+ * call because it is an unwanted call. This allows the user to indicate that they are
+ * rejecting a call because it is likely a nuisance call.
+ */
+ public static final int REJECT_REASON_UNWANTED = 2;
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = { "REJECT_REASON_" },
+ value = {REJECT_REASON_DECLINED, REJECT_REASON_UNWANTED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RejectReason {};
+
public static class Details {
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -1520,6 +1543,16 @@
}
/**
+ * Instructs the {@link ConnectionService} providing this {@link #STATE_RINGING} call that the
+ * user has chosen to reject the call and has indicated a reason why the call is being rejected.
+ *
+ * @param rejectReason the reason the call is being rejected.
+ */
+ public void reject(@RejectReason int rejectReason) {
+ mInCallAdapter.rejectCall(mTelecomCallId, rejectReason);
+ }
+
+ /**
* Instructs this {@code Call} to disconnect.
*/
public void disconnect() {
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index c934625..72c66d2 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -3037,6 +3037,17 @@
public void onReject() {}
/**
+ * Notifies this Connection, which is in {@link #STATE_RINGING}, of a request to reject.
+ * <p>
+ * For managed {@link ConnectionService}s, this will be called when the user rejects a call via
+ * the default dialer's {@link InCallService} using {@link Call#reject(int)}.
+ * @param rejectReason the reason the user provided for rejecting the call.
+ */
+ public void onReject(@android.telecom.Call.RejectReason int rejectReason) {
+ // to be implemented by ConnectionService.
+ }
+
+ /**
* Notifies this Connection, which is in {@link #STATE_RINGING}, of
* a request to reject with a message.
*/
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 440f044..00c2918 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -194,6 +194,7 @@
private static final int MSG_CREATE_CONFERENCE = 35;
private static final int MSG_CREATE_CONFERENCE_COMPLETE = 36;
private static final int MSG_CREATE_CONFERENCE_FAILED = 37;
+ private static final int MSG_REJECT_WITH_REASON = 38;
private static Connection sNullConnection;
@@ -450,6 +451,21 @@
}
@Override
+ public void rejectWithReason(String callId,
+ @android.telecom.Call.RejectReason int rejectReason, Session.Info sessionInfo) {
+ Log.startSession(sessionInfo, SESSION_REJECT);
+ try {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = callId;
+ args.argi1 = rejectReason;
+ args.arg2 = Log.createSubsession();
+ mHandler.obtainMessage(MSG_REJECT_WITH_REASON, args).sendToTarget();
+ } finally {
+ Log.endSession();
+ }
+ }
+
+ @Override
public void rejectWithMessage(String callId, String message, Session.Info sessionInfo) {
Log.startSession(sessionInfo, SESSION_REJECT_MESSAGE);
try {
@@ -1053,6 +1069,17 @@
}
break;
}
+ case MSG_REJECT_WITH_REASON: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_REJECT);
+ try {
+ reject((String) args.arg1, args.argi1);
+ } finally {
+ args.recycle();
+ Log.endSession();
+ }
+ break;
+ }
case MSG_REJECT_WITH_MESSAGE: {
SomeArgs args = (SomeArgs) msg.obj;
Log.continueSession((Session) args.arg3,
@@ -1981,6 +2008,11 @@
findConnectionForAction(callId, "reject").onReject(rejectWithMessage);
}
+ private void reject(String callId, @android.telecom.Call.RejectReason int rejectReason) {
+ Log.d(this, "reject %s with reason %d", callId, rejectReason);
+ findConnectionForAction(callId, "reject").onReject(rejectReason);
+ }
+
private void silence(String callId) {
Log.d(this, "silence %s", callId);
findConnectionForAction(callId, "silence").onSilence();
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 2612468..594c1eb 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -89,6 +89,19 @@
}
/**
+ * Instructs Telecom to reject the specified call.
+ *
+ * @param callId The identifier of the call to reject.
+ * @param rejectReason The reason the call was rejected.
+ */
+ public void rejectCall(String callId, @Call.RejectReason int rejectReason) {
+ try {
+ mAdapter.rejectCallWithReason(callId, rejectReason);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Instructs Telecom to disconnect the specified call.
*
* @param callId The identifier of the call to disconnect.
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 96f2483..4249dff 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -77,6 +77,8 @@
void reject(String callId, in Session.Info sessionInfo);
+ void rejectWithReason(String callId, int rejectReason, in Session.Info sessionInfo);
+
void rejectWithMessage(String callId, String message, in Session.Info sessionInfo);
void disconnect(String callId, in Session.Info sessionInfo);
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index 60745e4..eb2d714 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -34,6 +34,8 @@
void rejectCall(String callId, boolean rejectWithMessage, String textMessage);
+ void rejectCallWithReason(String callId, int rejectReason);
+
void disconnectCall(String callId);
void holdCall(String callId);
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index f4367da..e8f69ea 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -410,6 +410,13 @@
* Rejects an incoming call or session update.
*
* @param reason reason code to reject an incoming call, defined in {@link ImsReasonInfo}.
+ * The {@link android.telecom.InCallService} (dialer app) can use the
+ * {@link android.telecom.Call#reject(int)} API to reject a call while specifying
+ * a user-indicated reason for rejecting the call.
+ * Normal call declines ({@link android.telecom.Call#REJECT_REASON_DECLINED}) will
+ * map to {@link ImsReasonInfo#CODE_USER_DECLINE}.
+ * Unwanted calls ({@link android.telecom.Call#REJECT_REASON_UNWANTED}) will map
+ * to {@link ImsReasonInfo#CODE_SIP_USER_MARKED_UNWANTED}.
* {@link ImsCallSession.Listener#callSessionStartFailed}
*/
public void reject(int reason) {
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 419bcb1..f8d48c5 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -178,7 +178,7 @@
* If connected to a network suggestion or specifier, store the package name of the app,
* else null.
*/
- private String mAppPackageName;
+ private String mRequestingPackageName;
/**
* Running total count of lost (not ACKed) transmitted unicast data packets.
@@ -201,68 +201,68 @@
*/
public long rxSuccess;
- private double mTxBadRate;
+ private double mLostTxPacketsPerSecond;
/**
* Average rate of lost transmitted packets, in units of packets per second.
* @hide
*/
@SystemApi
- public double getTxBadRate() {
- return mTxBadRate;
+ public double getLostTxPacketsPerSecond() {
+ return mLostTxPacketsPerSecond;
}
/** @hide */
- public void setTxBadRate(double txBadRate) {
- mTxBadRate = txBadRate;
+ public void setLostTxPacketsPerSecond(double lostTxPacketsPerSecond) {
+ mLostTxPacketsPerSecond = lostTxPacketsPerSecond;
}
- private double mTxRetriesRate;
+ private double mTxRetriedTxPacketsPerSecond;
/**
* Average rate of transmitted retry packets, in units of packets per second.
* @hide
*/
@SystemApi
- public double getTxRetriesRate() {
- return mTxRetriesRate;
+ public double getRetriedTxPacketsPerSecond() {
+ return mTxRetriedTxPacketsPerSecond;
}
/** @hide */
- public void setTxRetriesRate(double txRetriesRate) {
- mTxRetriesRate = txRetriesRate;
+ public void setRetriedTxPacketsRate(double txRetriedTxPacketsPerSecond) {
+ mTxRetriedTxPacketsPerSecond = txRetriedTxPacketsPerSecond;
}
- private double mTxSuccessRate;
+ private double mSuccessfulTxPacketsPerSecond;
/**
* Average rate of successfully transmitted unicast packets, in units of packets per second.
* @hide
*/
@SystemApi
- public double getTxSuccessRate() {
- return mTxSuccessRate;
+ public double getSuccessfulTxPacketsPerSecond() {
+ return mSuccessfulTxPacketsPerSecond;
}
/** @hide */
- public void setTxSuccessRate(double txSuccessRate) {
- mTxSuccessRate = txSuccessRate;
+ public void setSuccessfulTxPacketsPerSecond(double successfulTxPacketsPerSecond) {
+ mSuccessfulTxPacketsPerSecond = successfulTxPacketsPerSecond;
}
- private double mRxSuccessRate;
+ private double mSuccessfulRxPacketsPerSecond;
/**
* Average rate of received unicast data packets, in units of packets per second.
* @hide
*/
@SystemApi
- public double getRxSuccessRate() {
- return mRxSuccessRate;
+ public double getSuccessfulRxPacketsPerSecond() {
+ return mSuccessfulRxPacketsPerSecond;
}
/** @hide */
- public void setRxSuccessRate(double rxSuccessRate) {
- mRxSuccessRate = rxSuccessRate;
+ public void setSuccessfulRxPacketsPerSecond(double successfulRxPacketsPerSecond) {
+ mSuccessfulRxPacketsPerSecond = successfulRxPacketsPerSecond;
}
/** @hide */
@@ -319,17 +319,17 @@
setMeteredHint(false);
setEphemeral(false);
setOsuAp(false);
- setAppPackageName(null);
+ setRequestingPackageName(null);
setFQDN(null);
setProviderFriendlyName(null);
txBad = 0;
txSuccess = 0;
rxSuccess = 0;
txRetries = 0;
- mTxBadRate = 0;
- mTxSuccessRate = 0;
- mRxSuccessRate = 0;
- mTxRetriesRate = 0;
+ mLostTxPacketsPerSecond = 0;
+ mSuccessfulTxPacketsPerSecond = 0;
+ mSuccessfulRxPacketsPerSecond = 0;
+ mTxRetriedTxPacketsPerSecond = 0;
score = 0;
}
@@ -353,8 +353,8 @@
mMeteredHint = source.mMeteredHint;
mEphemeral = source.mEphemeral;
mTrusted = source.mTrusted;
- mAppPackageName =
- source.mAppPackageName;
+ mRequestingPackageName =
+ source.mRequestingPackageName;
mOsuAp = source.mOsuAp;
mFqdn = source.mFqdn;
mProviderFriendlyName = source.mProviderFriendlyName;
@@ -362,10 +362,10 @@
txRetries = source.txRetries;
txSuccess = source.txSuccess;
rxSuccess = source.rxSuccess;
- mTxBadRate = source.mTxBadRate;
- mTxRetriesRate = source.mTxRetriesRate;
- mTxSuccessRate = source.mTxSuccessRate;
- mRxSuccessRate = source.mRxSuccessRate;
+ mLostTxPacketsPerSecond = source.mLostTxPacketsPerSecond;
+ mTxRetriedTxPacketsPerSecond = source.mTxRetriedTxPacketsPerSecond;
+ mSuccessfulTxPacketsPerSecond = source.mSuccessfulTxPacketsPerSecond;
+ mSuccessfulRxPacketsPerSecond = source.mSuccessfulRxPacketsPerSecond;
score = source.score;
mWifiStandard = source.mWifiStandard;
mMaxSupportedTxLinkSpeed = source.mMaxSupportedTxLinkSpeed;
@@ -777,8 +777,8 @@
}
/** {@hide} */
- public void setAppPackageName(@Nullable String packageName) {
- mAppPackageName = packageName;
+ public void setRequestingPackageName(@Nullable String packageName) {
+ mRequestingPackageName = packageName;
}
/**
@@ -788,8 +788,8 @@
* @hide
*/
@SystemApi
- public @Nullable String getAppPackageName() {
- return mAppPackageName;
+ public @Nullable String getRequestingPackageName() {
+ return mRequestingPackageName;
}
@@ -956,16 +956,16 @@
dest.writeInt(mTrusted ? 1 : 0);
dest.writeInt(score);
dest.writeLong(txSuccess);
- dest.writeDouble(mTxSuccessRate);
+ dest.writeDouble(mSuccessfulTxPacketsPerSecond);
dest.writeLong(txRetries);
- dest.writeDouble(mTxRetriesRate);
+ dest.writeDouble(mTxRetriedTxPacketsPerSecond);
dest.writeLong(txBad);
- dest.writeDouble(mTxBadRate);
+ dest.writeDouble(mLostTxPacketsPerSecond);
dest.writeLong(rxSuccess);
- dest.writeDouble(mRxSuccessRate);
+ dest.writeDouble(mSuccessfulRxPacketsPerSecond);
mSupplicantState.writeToParcel(dest, flags);
dest.writeInt(mOsuAp ? 1 : 0);
- dest.writeString(mAppPackageName);
+ dest.writeString(mRequestingPackageName);
dest.writeString(mFqdn);
dest.writeString(mProviderFriendlyName);
dest.writeInt(mWifiStandard);
@@ -1000,16 +1000,16 @@
info.mTrusted = in.readInt() != 0;
info.score = in.readInt();
info.txSuccess = in.readLong();
- info.mTxSuccessRate = in.readDouble();
+ info.mSuccessfulTxPacketsPerSecond = in.readDouble();
info.txRetries = in.readLong();
- info.mTxRetriesRate = in.readDouble();
+ info.mTxRetriedTxPacketsPerSecond = in.readDouble();
info.txBad = in.readLong();
- info.mTxBadRate = in.readDouble();
+ info.mLostTxPacketsPerSecond = in.readDouble();
info.rxSuccess = in.readLong();
- info.mRxSuccessRate = in.readDouble();
+ info.mSuccessfulRxPacketsPerSecond = in.readDouble();
info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in);
info.mOsuAp = in.readInt() != 0;
- info.mAppPackageName = in.readString();
+ info.mRequestingPackageName = in.readString();
info.mFqdn = in.readString();
info.mProviderFriendlyName = in.readString();
info.mWifiStandard = in.readInt();
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index fb3e794..c7475ee 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -4854,13 +4854,19 @@
/**
* Set Wi-Fi verbose logging level from developer settings.
*
- * @param verbose the verbose logging level to set. 0 will disable verbose logging, a positive
- * integer will enable verbose logging.
+ * @param enable true to enable verbose logging, false to disable.
*
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ public void setVerboseLoggingEnabled(boolean enable) {
+ enableVerboseLogging(enable ? 1 : 0);
+ }
+
+ /** @hide */
+ @UnsupportedAppUsage
+ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
public void enableVerboseLogging (int verbose) {
try {
mService.enableVerboseLogging(verbose);
@@ -4871,15 +4877,23 @@
}
/**
- * Get the persisted WiFi verbose logging level, set by {@link #enableVerboseLogging(int)}.
+ * Get the persisted Wi-Fi verbose logging level, set by
+ * {@link #setVerboseLoggingEnabled(boolean)}.
* No permissions are required to call this method.
*
- * @return 0 to indicate that verbose logging is disabled, a positive integer to indicate that
- * verbose logging is enabled.
+ * @return true to indicate that verbose logging is enabled, false to indicate that verbose
+ * logging is disabled.
*
* @hide
*/
@SystemApi
+ public boolean isVerboseLoggingEnabled() {
+ return getVerboseLoggingLevel() > 0;
+ }
+
+ /** @hide */
+ // TODO(b/145484145): remove once SUW stops calling this via reflection
+ @UnsupportedAppUsage
public int getVerboseLoggingLevel() {
try {
return mService.getVerboseLoggingLevel();
@@ -5204,7 +5218,7 @@
* level from wifi service.
*/
private void updateVerboseLoggingEnabledFromService() {
- mVerboseLoggingEnabled = getVerboseLoggingLevel() > 0;
+ mVerboseLoggingEnabled = isVerboseLoggingEnabled();
}
/**
diff --git a/wifi/tests/src/android/net/wifi/WifiInfoTest.java b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
index 04759ac..311bbc4 100644
--- a/wifi/tests/src/android/net/wifi/WifiInfoTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
@@ -64,7 +64,7 @@
writeWifiInfo.setOsuAp(true);
writeWifiInfo.setFQDN(TEST_FQDN);
writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME);
- writeWifiInfo.setAppPackageName(TEST_PACKAGE_NAME);
+ writeWifiInfo.setRequestingPackageName(TEST_PACKAGE_NAME);
writeWifiInfo.setWifiStandard(TEST_WIFI_STANDARD);
writeWifiInfo.setMaxSupportedTxLinkSpeedMbps(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS);
writeWifiInfo.setMaxSupportedRxLinkSpeedMbps(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS);
@@ -83,7 +83,7 @@
assertTrue(readWifiInfo.isTrusted());
assertTrue(readWifiInfo.isOsuAp());
assertTrue(readWifiInfo.isPasspointAp());
- assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getAppPackageName());
+ assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getRequestingPackageName());
assertEquals(TEST_FQDN, readWifiInfo.getPasspointFqdn());
assertEquals(TEST_PROVIDER_NAME, readWifiInfo.getPasspointProviderFriendlyName());
assertEquals(TEST_WIFI_STANDARD, readWifiInfo.getWifiStandard());