summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/media/framework/Android.bp4
-rw-r--r--apex/media/framework/api/system-current.txt34
-rw-r--r--apex/media/framework/java/android/media/MediaTranscodeManager.java673
-rw-r--r--cmds/app_process/Android.bp13
-rw-r--r--cmds/app_process/version-script32.txt15
-rw-r--r--cmds/app_process/version-script64.txt14
-rw-r--r--core/api/system-current.txt46
-rw-r--r--core/java/android/net/NetworkScore.aidl20
-rw-r--r--core/java/android/net/NetworkScore.java108
-rw-r--r--core/java/android/os/BatteryStats.java50
-rwxr-xr-xcore/java/android/os/Build.java2
-rw-r--r--core/java/android/os/connectivity/WifiActivityEnergyInfo.java4
-rw-r--r--core/java/android/widget/OWNERS2
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java278
-rw-r--r--core/java/com/android/internal/os/BluetoothPowerCalculator.java47
-rw-r--r--core/java/com/android/internal/os/WifiPowerCalculator.java129
-rw-r--r--core/java/com/android/internal/power/MeasuredEnergyStats.java6
-rw-r--r--core/java/com/android/internal/view/inline/OWNERS1
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java14
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java7
-rw-r--r--core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java1
-rw-r--r--core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java99
-rw-r--r--libs/hwui/Properties.cpp2
-rw-r--r--libs/hwui/Properties.h2
-rw-r--r--media/jni/soundpool/StreamManager.cpp6
-rw-r--r--packages/Connectivity/framework/api/module-lib-current.txt5
-rw-r--r--packages/Connectivity/framework/src/android/net/ConnectivityManager.java28
-rw-r--r--packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl3
-rw-r--r--packages/Connectivity/framework/src/android/net/Network.java6
-rw-r--r--packages/Connectivity/framework/src/android/net/NetworkAgent.java42
-rw-r--r--packages/Connectivity/framework/src/android/net/NetworkRequest.java11
-rw-r--r--packages/Connectivity/framework/src/android/net/ParseException.java9
-rw-r--r--packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl5
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/Utils.java5
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java5
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java4
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java70
-rw-r--r--services/core/java/com/android/server/am/BatteryExternalStatsWorker.java57
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java6
-rw-r--r--services/core/java/com/android/server/am/MeasuredEnergySnapshot.java25
-rw-r--r--services/core/java/com/android/server/clipboard/ClipboardService.java26
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkAgentInfo.java19
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java25
-rw-r--r--services/core/jni/com_android_server_SystemServer.cpp13
-rw-r--r--services/java/com/android/server/SystemServer.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/am/BatteryExternalStatsWorkerTest.java33
-rw-r--r--telecomm/java/android/telecom/CallDiagnosticService.java120
-rw-r--r--telecomm/java/android/telecom/CallDiagnostics.java374
-rw-r--r--telecomm/java/android/telecom/Connection.java6
-rw-r--r--telecomm/java/android/telecom/DiagnosticCall.java330
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt8
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java106
-rw-r--r--tests/net/java/com/android/server/connectivity/LingerMonitorTest.java6
-rw-r--r--tests/net/java/com/android/server/connectivity/VpnTest.java8
-rw-r--r--tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java2
57 files changed, 1836 insertions, 1112 deletions
diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp
index 3d129d8548eb..20ce13322fd2 100644
--- a/apex/media/framework/Android.bp
+++ b/apex/media/framework/Android.bp
@@ -135,6 +135,10 @@ java_sdk_library {
":updatable-media-srcs",
],
+ api_lint: {
+ enabled: false,
+ },
+
libs: [
"framework_media_annotation",
],
diff --git a/apex/media/framework/api/system-current.txt b/apex/media/framework/api/system-current.txt
index 6158e2ece55f..1d912ebc71fa 100644
--- a/apex/media/framework/api/system-current.txt
+++ b/apex/media/framework/api/system-current.txt
@@ -3,38 +3,19 @@ package android.media {
public final class MediaTranscodeManager {
method @Nullable public android.media.MediaTranscodeManager.TranscodingSession enqueueRequest(@NonNull android.media.MediaTranscodeManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodeManager.OnTranscodingFinishedListener);
- field public static final int PRIORITY_REALTIME = 1; // 0x1
- field public static final int TRANSCODING_TYPE_VIDEO = 1; // 0x1
}
@java.lang.FunctionalInterface public static interface MediaTranscodeManager.OnTranscodingFinishedListener {
method public void onTranscodingFinished(@NonNull android.media.MediaTranscodeManager.TranscodingSession);
}
- public static final class MediaTranscodeManager.TranscodingRequest {
+ public abstract static class MediaTranscodeManager.TranscodingRequest {
method public int getClientPid();
method public int getClientUid();
method @Nullable public android.os.ParcelFileDescriptor getDestinationFileDescriptor();
method @NonNull public android.net.Uri getDestinationUri();
- method public int getPriority();
method @Nullable public android.os.ParcelFileDescriptor getSourceFileDescriptor();
method @NonNull public android.net.Uri getSourceUri();
- method public int getType();
- method @Nullable public android.media.MediaFormat getVideoTrackFormat();
- }
-
- public static final class MediaTranscodeManager.TranscodingRequest.Builder {
- ctor public MediaTranscodeManager.TranscodingRequest.Builder();
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest build();
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setClientPid(int);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setClientUid(int);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setDestinationFileDescriptor(@NonNull android.os.ParcelFileDescriptor);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setDestinationUri(@NonNull android.net.Uri);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setPriority(int);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setSourceFileDescriptor(@NonNull android.os.ParcelFileDescriptor);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setSourceUri(@NonNull android.net.Uri);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setType(int);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setVideoTrackFormat(@NonNull android.media.MediaFormat);
}
public static class MediaTranscodeManager.TranscodingRequest.MediaFormatResolver {
@@ -71,5 +52,18 @@ package android.media {
method public void onProgressUpdate(@NonNull android.media.MediaTranscodeManager.TranscodingSession, @IntRange(from=0, to=100) int);
}
+ public static final class MediaTranscodeManager.VideoTranscodingRequest extends android.media.MediaTranscodeManager.TranscodingRequest {
+ method @NonNull public android.media.MediaFormat getVideoTrackFormat();
+ }
+
+ public static final class MediaTranscodeManager.VideoTranscodingRequest.Builder {
+ ctor public MediaTranscodeManager.VideoTranscodingRequest.Builder(@NonNull android.net.Uri, @NonNull android.net.Uri, @NonNull android.media.MediaFormat);
+ method @NonNull public android.media.MediaTranscodeManager.VideoTranscodingRequest build();
+ method @NonNull public android.media.MediaTranscodeManager.VideoTranscodingRequest.Builder setClientPid(int);
+ method @NonNull public android.media.MediaTranscodeManager.VideoTranscodingRequest.Builder setClientUid(int);
+ method @NonNull public android.media.MediaTranscodeManager.VideoTranscodingRequest.Builder setDestinationFileDescriptor(android.os.ParcelFileDescriptor);
+ method @NonNull public android.media.MediaTranscodeManager.VideoTranscodingRequest.Builder setSourceFileDescriptor(android.os.ParcelFileDescriptor);
+ }
+
}
diff --git a/apex/media/framework/java/android/media/MediaTranscodeManager.java b/apex/media/framework/java/android/media/MediaTranscodeManager.java
index 84332e5bbcf0..79e0d58cf495 100644
--- a/apex/media/framework/java/android/media/MediaTranscodeManager.java
+++ b/apex/media/framework/java/android/media/MediaTranscodeManager.java
@@ -50,27 +50,23 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
- MediaTranscodeManager provides an interface to the system's media transcoding service and can be
- used to transcode media files, e.g. transcoding a video from HEVC to AVC.
+ Android 12 introduces Compatible media transcoding feature. See
+ <a href="https://developer.android.com/about/versions/12/features#compatible_media_transcoding">
+ Compatible media transcoding</a>. MediaTranscodeManager provides an interface to the system's media
+ transcoding service and can be used to transcode media files, e.g. transcoding a video from HEVC to
+ AVC.
<h3>Transcoding Types</h3>
<h4>Video Transcoding</h4>
- When transcoding a video file, the video file could be of any of the following types:
- <ul>
- <li> Video file with single video track. </li>
- <li> Video file with multiple video track. </li>
- <li> Video file with multiple video tracks and audio tracks. </li>
- <li> Video file with video/audio tracks and metadata track. Note that metadata track will be passed
- through only if it could be recognized by {@link MediaExtractor}.
- TODO(hkuang): Finalize the metadata track behavior. </li>
- </ul>
+ When transcoding a video file, the video track will be transcoded based on the desired track format
+ and the audio track will be pass through without any modification.
<p class=note>
- Note that currently only support transcoding video file in mp4 format.
+ Note that currently only support transcoding video file in mp4 format and with single video track.
<h3>Transcoding Request</h3>
<p>
To transcode a media file, first create a {@link TranscodingRequest} through its builder class
- {@link TranscodingRequest.Builder}. Transcode requests are then enqueue to the manager through
+ {@link VideoTranscodingRequest.Builder}. Transcode requests are then enqueue to the manager through
{@link MediaTranscodeManager#enqueueRequest(
TranscodingRequest, Executor, OnTranscodingFinishedListener)}
TranscodeRequest are processed based on client process's priority and request priority. When a
@@ -82,23 +78,9 @@ import java.util.concurrent.Executors;
Here is an example where <code>Builder</code> is used to specify all parameters
<pre class=prettyprint>
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(srcUri)
- .setDestinationUri(dstUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(REALTIME)
- .setVideoTrackFormat(videoFormat)
- .build();
+ VideoTranscodingRequest request =
+ new VideoTranscodingRequest.Builder(srcUri, dstUri, videoFormat).build();
}</pre>
-
- TODO(hkuang): Add architecture diagram showing the transcoding service and api.
- TODO(hkuang): Add sample code when API is settled.
- TODO(hkuang): Clarify whether multiple video tracks is supported or not.
- TODO(hkuang): Clarify whether image/audio transcoding is supported or not.
- TODO(hkuang): Clarify what will happen if there is unrecognized track in the source.
- TODO(hkuang): Clarify whether supports scaling.
- TODO(hkuang): Clarify whether supports framerate conversion.
@hide
*/
@MinSdk(Build.VERSION_CODES.S)
@@ -116,68 +98,6 @@ public final class MediaTranscodeManager {
private static final float BPP = 0.25f;
/**
- * Default transcoding type.
- * @hide
- */
- public static final int TRANSCODING_TYPE_UNKNOWN = 0;
-
- /**
- * TRANSCODING_TYPE_VIDEO indicates that client wants to perform transcoding on a video file.
- * <p>Note that currently only support transcoding video file in mp4 format.
- */
- public static final int TRANSCODING_TYPE_VIDEO = 1;
-
- /**
- * TRANSCODING_TYPE_IMAGE indicates that client wants to perform transcoding on an image file.
- * @hide
- */
- public static final int TRANSCODING_TYPE_IMAGE = 2;
-
- /** @hide */
- @IntDef(prefix = {"TRANSCODING_TYPE_"}, value = {
- TRANSCODING_TYPE_UNKNOWN,
- TRANSCODING_TYPE_VIDEO,
- TRANSCODING_TYPE_IMAGE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TranscodingType {}
-
- /**
- * Default value.
- * @hide
- */
- public static final int PRIORITY_UNKNOWN = 0;
- /**
- * PRIORITY_REALTIME indicates that the transcoding request is time-critical and that the
- * client wants the transcoding result as soon as possible.
- * <p> Set PRIORITY_REALTIME only if the transcoding is time-critical as it will involve
- * performance penalty due to resource reallocation to prioritize the sessions with higher
- * priority.
- * TODO(hkuang): Add more description of this when priority is finalized.
- */
- public static final int PRIORITY_REALTIME = 1;
-
- /**
- * PRIORITY_OFFLINE indicates the transcoding is not time-critical and the client does not need
- * the transcoding result as soon as possible.
- * <p>Sessions with PRIORITY_OFFLINE will be scheduled behind PRIORITY_REALTIME. Always set to
- * PRIORITY_OFFLINE if client does not need the result as soon as possible and could accept
- * delay of the transcoding result.
- * @hide
- * TODO(hkuang): Add more description of this when priority is finalized.
- */
- public static final int PRIORITY_OFFLINE = 2;
-
- /** @hide */
- @IntDef(prefix = {"PRIORITY_"}, value = {
- PRIORITY_UNKNOWN,
- PRIORITY_REALTIME,
- PRIORITY_OFFLINE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TranscodingPriority {}
-
- /**
* Listener that gets notified when a transcoding operation has finished.
* This listener gets notified regardless of how the operation finished. It is up to the
* listener implementation to check the result and take appropriate action.
@@ -503,7 +423,79 @@ public final class MediaTranscodeManager {
}
}
- public static final class TranscodingRequest {
+ /**
+ * Abstract base class for all the TranscodingRequest.
+ * <p> TranscodingRequest encapsulates the desired configuration for the transcoding.
+ */
+ public abstract static class TranscodingRequest {
+ /**
+ *
+ * Default transcoding type.
+ * @hide
+ */
+ public static final int TRANSCODING_TYPE_UNKNOWN = 0;
+
+ /**
+ * TRANSCODING_TYPE_VIDEO indicates that client wants to perform transcoding on a video.
+ * <p>Note that currently only support transcoding video file in mp4 format.
+ * @hide
+ */
+ public static final int TRANSCODING_TYPE_VIDEO = 1;
+
+ /**
+ * TRANSCODING_TYPE_IMAGE indicates that client wants to perform transcoding on an image.
+ * @hide
+ */
+ public static final int TRANSCODING_TYPE_IMAGE = 2;
+
+ /** @hide */
+ @IntDef(prefix = {"TRANSCODING_TYPE_"}, value = {
+ TRANSCODING_TYPE_UNKNOWN,
+ TRANSCODING_TYPE_VIDEO,
+ TRANSCODING_TYPE_IMAGE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TranscodingType {}
+
+ /**
+ * Default value.
+ *
+ * @hide
+ */
+ public static final int PRIORITY_UNKNOWN = 0;
+ /**
+ * PRIORITY_REALTIME indicates that the transcoding request is time-critical and that the
+ * client wants the transcoding result as soon as possible.
+ * <p> Set PRIORITY_REALTIME only if the transcoding is time-critical as it will involve
+ * performance penalty due to resource reallocation to prioritize the sessions with higher
+ * priority.
+ *
+ * @hide
+ */
+ public static final int PRIORITY_REALTIME = 1;
+
+ /**
+ * PRIORITY_OFFLINE indicates the transcoding is not time-critical and the client does not
+ * need the transcoding result as soon as possible.
+ * <p>Sessions with PRIORITY_OFFLINE will be scheduled behind PRIORITY_REALTIME. Always set
+ * to
+ * PRIORITY_OFFLINE if client does not need the result as soon as possible and could accept
+ * delay of the transcoding result.
+ *
+ * @hide
+ *
+ */
+ public static final int PRIORITY_OFFLINE = 2;
+
+ /** @hide */
+ @IntDef(prefix = {"PRIORITY_"}, value = {
+ PRIORITY_UNKNOWN,
+ PRIORITY_REALTIME,
+ PRIORITY_OFFLINE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TranscodingPriority {}
+
/** Uri of the source media file. */
private @NonNull Uri mSourceUri;
@@ -537,22 +529,6 @@ public final class MediaTranscodeManager {
private @TranscodingPriority int mPriority = PRIORITY_UNKNOWN;
/**
- * Desired output video format of the destination file.
- * <p> If this is null, source file's video track will be passed through and copied to the
- * destination file.
- * <p>
- */
- private @Nullable MediaFormat mVideoTrackFormat = null;
-
- /**
- * Desired output audio format of the destination file.
- * <p> If this is null, source file's audio track will be passed through and copied to the
- * destination file.
- * @hide
- */
- private @Nullable MediaFormat mAudioTrackFormat = null;
-
- /**
* Desired image format for the destination file.
* <p> If this is null, source file's image track will be passed through and copied to the
* destination file.
@@ -563,6 +539,12 @@ public final class MediaTranscodeManager {
@VisibleForTesting
private TranscodingTestConfig mTestConfig = null;
+ /**
+ * Prevent public constructor access.
+ */
+ /* package private */ TranscodingRequest() {
+ }
+
private TranscodingRequest(Builder b) {
mSourceUri = b.mSourceUri;
mSourceFileDescriptor = b.mSourceFileDescriptor;
@@ -572,13 +554,13 @@ public final class MediaTranscodeManager {
mClientPid = b.mClientPid;
mPriority = b.mPriority;
mType = b.mType;
- mVideoTrackFormat = b.mVideoTrackFormat;
- mAudioTrackFormat = b.mAudioTrackFormat;
- mImageFormat = b.mImageFormat;
mTestConfig = b.mTestConfig;
}
- /** Return the type of the transcoding. */
+ /**
+ * Return the type of the transcoding.
+ * @hide
+ */
@TranscodingType
public int getType() {
return mType;
@@ -624,22 +606,16 @@ public final class MediaTranscodeManager {
return mDestinationFileDescriptor;
}
- /** Return priority of the transcoding. */
+ /**
+ * Return priority of the transcoding.
+ * @hide
+ */
@TranscodingPriority
public int getPriority() {
return mPriority;
}
/**
- * Return the video track format of the transcoding.
- * This will be null is the transcoding is not for video transcoding.
- */
- @Nullable
- public MediaFormat getVideoTrackFormat() {
- return mVideoTrackFormat;
- }
-
- /**
* Return TestConfig of the transcoding.
* @hide
*/
@@ -648,6 +624,8 @@ public final class MediaTranscodeManager {
return mTestConfig;
}
+ abstract void writeFormatToParcel(TranscodingRequestParcel parcel);
+
/* Writes the TranscodingRequest to a parcel. */
private TranscodingRequestParcel writeToParcel(@NonNull Context context) {
TranscodingRequestParcel parcel = new TranscodingRequestParcel();
@@ -671,7 +649,7 @@ public final class MediaTranscodeManager {
}
parcel.clientPackageName = packageName;
}
- parcel.requestedVideoTrackFormat = convertToVideoTrackFormat(mVideoTrackFormat);
+ writeFormatToParcel(parcel);
if (mTestConfig != null) {
parcel.isForTesting = true;
parcel.testConfig = mTestConfig;
@@ -679,71 +657,12 @@ public final class MediaTranscodeManager {
return parcel;
}
- /* Converts the MediaFormat to TranscodingVideoTrackFormat. */
- private static TranscodingVideoTrackFormat convertToVideoTrackFormat(MediaFormat format) {
- if (format == null) {
- throw new IllegalArgumentException("Invalid MediaFormat");
- }
-
- TranscodingVideoTrackFormat trackFormat = new TranscodingVideoTrackFormat();
-
- if (format.containsKey(MediaFormat.KEY_MIME)) {
- String mime = format.getString(MediaFormat.KEY_MIME);
- if (MediaFormat.MIMETYPE_VIDEO_AVC.equals(mime)) {
- trackFormat.codecType = TranscodingVideoCodecType.kAvc;
- } else if (MediaFormat.MIMETYPE_VIDEO_HEVC.equals(mime)) {
- trackFormat.codecType = TranscodingVideoCodecType.kHevc;
- } else {
- throw new UnsupportedOperationException("Only support transcode to avc/hevc");
- }
- }
-
- if (format.containsKey(MediaFormat.KEY_BIT_RATE)) {
- int bitrateBps = format.getInteger(MediaFormat.KEY_BIT_RATE);
- if (bitrateBps <= 0) {
- throw new IllegalArgumentException("Bitrate must be larger than 0");
- }
- trackFormat.bitrateBps = bitrateBps;
- }
-
- if (format.containsKey(MediaFormat.KEY_WIDTH) && format.containsKey(
- MediaFormat.KEY_HEIGHT)) {
- int width = format.getInteger(MediaFormat.KEY_WIDTH);
- int height = format.getInteger(MediaFormat.KEY_HEIGHT);
- if (width <= 0 || height <= 0) {
- throw new IllegalArgumentException("Width and height must be larger than 0");
- }
- // TODO(hkuang): Validate the aspect ratio after adding scaling.
- trackFormat.width = width;
- trackFormat.height = height;
- }
-
- if (format.containsKey(MediaFormat.KEY_PROFILE)) {
- int profile = format.getInteger(MediaFormat.KEY_PROFILE);
- if (profile <= 0) {
- throw new IllegalArgumentException("Invalid codec profile");
- }
- // TODO(hkuang): Validate the profile according to codec type.
- trackFormat.profile = profile;
- }
-
- if (format.containsKey(MediaFormat.KEY_LEVEL)) {
- int level = format.getInteger(MediaFormat.KEY_LEVEL);
- if (level <= 0) {
- throw new IllegalArgumentException("Invalid codec level");
- }
- // TODO(hkuang): Validate the level according to codec type.
- trackFormat.level = level;
- }
-
- return trackFormat;
- }
-
/**
- * Builder class for {@link TranscodingRequest} objects.
- * Use this class to configure and create a <code>TranscodingRequest</code> instance.
+ * Builder to build a {@link TranscodingRequest} object.
+ *
+ * @param <T> The subclass to be built.
*/
- public static final class Builder {
+ abstract static class Builder<T extends Builder<T>> {
private @NonNull Uri mSourceUri;
private @NonNull Uri mDestinationUri;
private @Nullable ParcelFileDescriptor mSourceFileDescriptor = null;
@@ -752,80 +671,68 @@ public final class MediaTranscodeManager {
private int mClientPid = -1;
private @TranscodingType int mType = TRANSCODING_TYPE_UNKNOWN;
private @TranscodingPriority int mPriority = PRIORITY_UNKNOWN;
- private @Nullable MediaFormat mVideoTrackFormat;
- private @Nullable MediaFormat mAudioTrackFormat;
- private @Nullable MediaFormat mImageFormat;
private TranscodingTestConfig mTestConfig;
+ abstract T self();
+
/**
- * Specifies the uri of source media file.
+ * Creates a builder for building {@link TranscodingRequest}s.
*
* Client must set the source Uri. If client also provides the source fileDescriptor
* through is provided by {@link #setSourceFileDescriptor(ParcelFileDescriptor)},
* TranscodingSession will use the fd instead of calling back to the client to open the
* sourceUri.
+ *
+ *
+ * @param type The transcoding type.
* @param sourceUri Content uri for the source media file.
- * @return The same builder instance.
- * @throws IllegalArgumentException if Uri is null or empty.
+ * @param destinationUri Content uri for the destination media file.
+ *
*/
- @NonNull
- public Builder setSourceUri(@NonNull Uri sourceUri) {
+ private Builder(@TranscodingType int type, @NonNull Uri sourceUri,
+ @NonNull Uri destinationUri) {
+ mType = type;
+
if (sourceUri == null || Uri.EMPTY.equals(sourceUri)) {
throw new IllegalArgumentException(
"You must specify a non-empty source Uri.");
}
mSourceUri = sourceUri;
- return this;
+
+ if (destinationUri == null || Uri.EMPTY.equals(destinationUri)) {
+ throw new IllegalArgumentException(
+ "You must specify a non-empty destination Uri.");
+ }
+ mDestinationUri = destinationUri;
}
/**
* Specifies the fileDescriptor opened from the source media file.
*
* This call is optional. If the source fileDescriptor is provided, TranscodingSession
- * will use it directly instead of opening the uri from {@link #setSourceUri(Uri)}. It
- * is client's responsibility to make sure the fileDescriptor is opened from the source
- * uri.
+ * will use it directly instead of opening the uri from {@link #Builder(int, Uri, Uri)}.
+ * It is client's responsibility to make sure the fileDescriptor is opened from the
+ * source uri.
* @param fileDescriptor a {@link ParcelFileDescriptor} opened from source media file.
* @return The same builder instance.
* @throws IllegalArgumentException if fileDescriptor is invalid.
*/
@NonNull
- public Builder setSourceFileDescriptor(@NonNull ParcelFileDescriptor fileDescriptor) {
+ public T setSourceFileDescriptor(@NonNull ParcelFileDescriptor fileDescriptor) {
if (fileDescriptor == null || fileDescriptor.getFd() < 0) {
throw new IllegalArgumentException(
"Invalid source descriptor.");
}
mSourceFileDescriptor = fileDescriptor;
- return this;
- }
-
- /**
- * Specifies the uri of the destination media file.
- *
- * Client must set the destination Uri. If client also provides the destination
- * fileDescriptor through {@link #setDestinationFileDescriptor(ParcelFileDescriptor)},
- * TranscodingSession will use the fd instead of calling back to the client to open the
- * destinationUri.
- * @param destinationUri Content uri for the destination media file.
- * @return The same builder instance.
- * @throws IllegalArgumentException if Uri is null or empty.
- */
- @NonNull
- public Builder setDestinationUri(@NonNull Uri destinationUri) {
- if (destinationUri == null || Uri.EMPTY.equals(destinationUri)) {
- throw new IllegalArgumentException(
- "You must specify a non-empty destination Uri.");
- }
- mDestinationUri = destinationUri;
- return this;
+ return self();
}
/**
* Specifies the fileDescriptor opened from the destination media file.
*
* This call is optional. If the destination fileDescriptor is provided,
- * TranscodingSession will use it directly instead of opening the uri from
- * {@link #setDestinationUri(Uri)} upon transcoding starts. It is client's
+ * TranscodingSession will use it directly instead of opening the source uri from
+ * {@link #Builder(int, Uri, Uri)} upon transcoding starts. It is client's
* responsibility to make sure the fileDescriptor is opened from the destination uri.
* @param fileDescriptor a {@link ParcelFileDescriptor} opened from destination media
* file.
@@ -833,46 +740,54 @@ public final class MediaTranscodeManager {
* @throws IllegalArgumentException if fileDescriptor is invalid.
*/
@NonNull
- public Builder setDestinationFileDescriptor(
+ public T setDestinationFileDescriptor(
@NonNull ParcelFileDescriptor fileDescriptor) {
if (fileDescriptor == null || fileDescriptor.getFd() < 0) {
throw new IllegalArgumentException(
"Invalid destination descriptor.");
}
mDestinationFileDescriptor = fileDescriptor;
- return this;
+ return self();
}
/**
* Specify the UID of the client that this request is for.
+ * <p>
+ * Only privilege caller with android.permission.WRITE_MEDIA_STORAGE could forward the
+ * pid. Note that the permission check happens on the service side upon starting the
+ * transcoding. If the client does not have the permission, the transcoding will fail.
+ *
* @param uid client Uid.
* @return The same builder instance.
* @throws IllegalArgumentException if uid is invalid.
- * TODO(hkuang): Check the permission if it is allowed.
*/
@NonNull
- public Builder setClientUid(int uid) {
+ public T setClientUid(int uid) {
if (uid < 0) {
throw new IllegalArgumentException("Invalid Uid");
}
mClientUid = uid;
- return this;
+ return self();
}
/**
- * Specify the PID of the client that this request is for.
+ * Specify the pid of the client that this request is for.
+ * <p>
+ * Only privilege caller with android.permission.WRITE_MEDIA_STORAGE could forward the
+ * pid. Note that the permission check happens on the service side upon starting the
+ * transcoding. If the client does not have the permission, the transcoding will fail.
+ *
* @param pid client Pid.
* @return The same builder instance.
* @throws IllegalArgumentException if pid is invalid.
- * TODO(hkuang): Check the permission if it is allowed.
*/
@NonNull
- public Builder setClientPid(int pid) {
+ public T setClientPid(int pid) {
if (pid < 0) {
throw new IllegalArgumentException("Invalid pid");
}
mClientPid = pid;
- return this;
+ return self();
}
/**
@@ -881,64 +796,15 @@ public final class MediaTranscodeManager {
* @param priority Must be one of the {@code PRIORITY_*}
* @return The same builder instance.
* @throws IllegalArgumentException if flags is invalid.
+ * @hide
*/
@NonNull
- public Builder setPriority(@TranscodingPriority int priority) {
+ public T setPriority(@TranscodingPriority int priority) {
if (priority != PRIORITY_OFFLINE && priority != PRIORITY_REALTIME) {
throw new IllegalArgumentException("Invalid priority: " + priority);
}
mPriority = priority;
- return this;
- }
-
- /**
- * Specifies the type of transcoding.
- * <p> Clients must provide the source and destination that corresponds to the
- * transcoding type.
- *
- * @param type Must be one of the {@code TRANSCODING_TYPE_*}
- * @return The same builder instance.
- * @throws IllegalArgumentException if flags is invalid.
- */
- @NonNull
- public Builder setType(@TranscodingType int type) {
- if (type != TRANSCODING_TYPE_VIDEO && type != TRANSCODING_TYPE_IMAGE) {
- throw new IllegalArgumentException("Invalid transcoding type");
- }
- mType = type;
- return this;
- }
-
- /**
- * Specifies the desired video track format in the destination media file.
- * <p>Client could only specify the settings that matters to them, e.g. codec format or
- * bitrate. And by default, transcoding will preserve the original video's
- * settings(bitrate, framerate, resolution) if not provided.
- * <p>Note that some settings may silently fail to apply if the device does not
- * support them.
- * TODO(hkuang): Add MediaTranscodeUtil to help client generate transcoding setting.
- * TODO(hkuang): Add MediaTranscodeUtil to check if the setting is valid.
- *
- * @param videoFormat MediaFormat containing the settings that client wants override in
- * the original video's video track.
- * @return The same builder instance.
- * @throws IllegalArgumentException if videoFormat is invalid.
- */
- @NonNull
- public Builder setVideoTrackFormat(@NonNull MediaFormat videoFormat) {
- if (videoFormat == null) {
- throw new IllegalArgumentException("videoFormat must not be null");
- }
-
- // Check if the MediaFormat is for video by looking at the MIME type.
- String mime = videoFormat.containsKey(MediaFormat.KEY_MIME)
- ? videoFormat.getString(MediaFormat.KEY_MIME) : null;
- if (mime == null || !mime.startsWith("video/")) {
- throw new IllegalArgumentException("Invalid video format: wrong mime type");
- }
-
- mVideoTrackFormat = videoFormat;
- return this;
+ return self();
}
/**
@@ -949,44 +815,9 @@ public final class MediaTranscodeManager {
*/
@VisibleForTesting
@NonNull
- public Builder setTestConfig(@NonNull TranscodingTestConfig config) {
+ public T setTestConfig(@NonNull TranscodingTestConfig config) {
mTestConfig = config;
- return this;
- }
-
- /**
- * @return a new {@link TranscodingRequest} instance successfully initialized with all
- * the parameters set on this <code>Builder</code>.
- * @throws UnsupportedOperationException if the parameters set on the
- * <code>Builder</code> were incompatible, or if they are not supported by the
- * device.
- */
- @NonNull
- public TranscodingRequest build() {
- if (mSourceUri == null) {
- throw new UnsupportedOperationException("Source URI must not be null");
- }
-
- if (mDestinationUri == null) {
- throw new UnsupportedOperationException("Destination URI must not be null");
- }
-
- if (mPriority == PRIORITY_UNKNOWN) {
- throw new UnsupportedOperationException("Must specify transcoding priority");
- }
-
- // Only support video transcoding now.
- if (mType != TRANSCODING_TYPE_VIDEO) {
- throw new UnsupportedOperationException("Only supports video transcoding now");
- }
-
- // Must provide video track format for video transcoding.
- if (mType == TRANSCODING_TYPE_VIDEO && mVideoTrackFormat == null) {
- throw new UnsupportedOperationException(
- "Must provide video track format for video transcoding");
- }
-
- return new TranscodingRequest(this);
+ return self();
}
}
@@ -1201,6 +1032,206 @@ public final class MediaTranscodeManager {
}
/**
+ * VideoTranscodingRequest encapsulates the configuration for transcoding a video.
+ */
+ public static final class VideoTranscodingRequest extends TranscodingRequest {
+ /**
+ * Desired output video format of the destination file.
+ * <p> If this is null, source file's video track will be passed through and copied to the
+ * destination file.
+ */
+ private @Nullable MediaFormat mVideoTrackFormat = null;
+
+ /**
+ * Desired output audio format of the destination file.
+ * <p> If this is null, source file's audio track will be passed through and copied to the
+ * destination file.
+ */
+ private @Nullable MediaFormat mAudioTrackFormat = null;
+
+ private VideoTranscodingRequest(VideoTranscodingRequest.Builder builder) {
+ super(builder);
+ mVideoTrackFormat = builder.mVideoTrackFormat;
+ mAudioTrackFormat = builder.mAudioTrackFormat;
+ }
+
+ /**
+ * Return the video track format of the transcoding.
+ * This will be null if client has not specified the video track format.
+ */
+ @NonNull
+ public MediaFormat getVideoTrackFormat() {
+ return mVideoTrackFormat;
+ }
+
+ @Override
+ void writeFormatToParcel(TranscodingRequestParcel parcel) {
+ parcel.requestedVideoTrackFormat = convertToVideoTrackFormat(mVideoTrackFormat);
+ }
+
+ /* Converts the MediaFormat to TranscodingVideoTrackFormat. */
+ private static TranscodingVideoTrackFormat convertToVideoTrackFormat(MediaFormat format) {
+ if (format == null) {
+ throw new IllegalArgumentException("Invalid MediaFormat");
+ }
+
+ TranscodingVideoTrackFormat trackFormat = new TranscodingVideoTrackFormat();
+
+ if (format.containsKey(MediaFormat.KEY_MIME)) {
+ String mime = format.getString(MediaFormat.KEY_MIME);
+ if (MediaFormat.MIMETYPE_VIDEO_AVC.equals(mime)) {
+ trackFormat.codecType = TranscodingVideoCodecType.kAvc;
+ } else if (MediaFormat.MIMETYPE_VIDEO_HEVC.equals(mime)) {
+ trackFormat.codecType = TranscodingVideoCodecType.kHevc;
+ } else {
+ throw new UnsupportedOperationException("Only support transcode to avc/hevc");
+ }
+ }
+
+ if (format.containsKey(MediaFormat.KEY_BIT_RATE)) {
+ int bitrateBps = format.getInteger(MediaFormat.KEY_BIT_RATE);
+ if (bitrateBps <= 0) {
+ throw new IllegalArgumentException("Bitrate must be larger than 0");
+ }
+ trackFormat.bitrateBps = bitrateBps;
+ }
+
+ if (format.containsKey(MediaFormat.KEY_WIDTH) && format.containsKey(
+ MediaFormat.KEY_HEIGHT)) {
+ int width = format.getInteger(MediaFormat.KEY_WIDTH);
+ int height = format.getInteger(MediaFormat.KEY_HEIGHT);
+ if (width <= 0 || height <= 0) {
+ throw new IllegalArgumentException("Width and height must be larger than 0");
+ }
+ // TODO: Validate the aspect ratio after adding scaling.
+ trackFormat.width = width;
+ trackFormat.height = height;
+ }
+
+ if (format.containsKey(MediaFormat.KEY_PROFILE)) {
+ int profile = format.getInteger(MediaFormat.KEY_PROFILE);
+ if (profile <= 0) {
+ throw new IllegalArgumentException("Invalid codec profile");
+ }
+ // TODO: Validate the profile according to codec type.
+ trackFormat.profile = profile;
+ }
+
+ if (format.containsKey(MediaFormat.KEY_LEVEL)) {
+ int level = format.getInteger(MediaFormat.KEY_LEVEL);
+ if (level <= 0) {
+ throw new IllegalArgumentException("Invalid codec level");
+ }
+ // TODO: Validate the level according to codec type.
+ trackFormat.level = level;
+ }
+
+ return trackFormat;
+ }
+
+ /**
+ * Builder class for {@link VideoTranscodingRequest}.
+ */
+ public static final class Builder extends
+ TranscodingRequest.Builder<VideoTranscodingRequest.Builder> {
+ /**
+ * Desired output video format of the destination file.
+ * <p> If this is null, source file's video track will be passed through and
+ * copied to the destination file.
+ */
+ private @Nullable MediaFormat mVideoTrackFormat = null;
+
+ /**
+ * Desired output audio format of the destination file.
+ * <p> If this is null, source file's audio track will be passed through and copied
+ * to the destination file.
+ */
+ private @Nullable MediaFormat mAudioTrackFormat = null;
+
+ /**
+ * Creates a builder for building {@link VideoTranscodingRequest}s.
+ *
+ * <p> Client could only specify the settings that matters to them, e.g. codec format or
+ * bitrate. And by default, transcoding will preserve the original video's settings
+ * (bitrate, framerate, resolution) if not provided.
+ * <p>Note that some settings may silently fail to apply if the device does not support
+ * them.
+ * @param sourceUri Content uri for the source media file.
+ * @param destinationUri Content uri for the destination media file.
+ * @param videoFormat MediaFormat containing the settings that client wants override in
+ * the original video's video track.
+ * @throws IllegalArgumentException if videoFormat is invalid.
+ */
+ public Builder(@NonNull Uri sourceUri, @NonNull Uri destinationUri,
+ @NonNull MediaFormat videoFormat) {
+ super(TRANSCODING_TYPE_VIDEO, sourceUri, destinationUri);
+ setVideoTrackFormat(videoFormat);
+ }
+
+ @Override
+ @NonNull
+ public Builder setClientUid(int uid) {
+ super.setClientUid(uid);
+ return self();
+ }
+
+ @Override
+ @NonNull
+ public Builder setClientPid(int pid) {
+ super.setClientPid(pid);
+ return self();
+ }
+
+ @Override
+ @NonNull
+ public Builder setSourceFileDescriptor(ParcelFileDescriptor fd) {
+ super.setSourceFileDescriptor(fd);
+ return self();
+ }
+
+ @Override
+ @NonNull
+ public Builder setDestinationFileDescriptor(ParcelFileDescriptor fd) {
+ super.setDestinationFileDescriptor(fd);
+ return self();
+ }
+
+ private void setVideoTrackFormat(@NonNull MediaFormat videoFormat) {
+ if (videoFormat == null) {
+ throw new IllegalArgumentException("videoFormat must not be null");
+ }
+
+ // Check if the MediaFormat is for video by looking at the MIME type.
+ String mime = videoFormat.containsKey(MediaFormat.KEY_MIME)
+ ? videoFormat.getString(MediaFormat.KEY_MIME) : null;
+ if (mime == null || !mime.startsWith("video/")) {
+ throw new IllegalArgumentException("Invalid video format: wrong mime type");
+ }
+
+ mVideoTrackFormat = videoFormat;
+ }
+
+ /**
+ * @return a new {@link TranscodingRequest} instance successfully initialized
+ * with all the parameters set on this <code>Builder</code>.
+ * @throws UnsupportedOperationException if the parameters set on the
+ * <code>Builder</code> were incompatible, or
+ * if they are not supported by the
+ * device.
+ */
+ @NonNull
+ public VideoTranscodingRequest build() {
+ return new VideoTranscodingRequest(this);
+ }
+
+ @Override
+ VideoTranscodingRequest.Builder self() {
+ return this;
+ }
+ }
+ }
+
+ /**
* Handle to an enqueued transcoding operation. An instance of this class represents a single
* enqueued transcoding operation. The caller can use that instance to query the status or
* progress, and to get the result once the operation has completed.
diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp
index 4e5b3bac5713..0eff83c99282 100644
--- a/cmds/app_process/Android.bp
+++ b/cmds/app_process/Android.bp
@@ -22,13 +22,9 @@ cc_binary {
multilib: {
lib32: {
- // TODO(b/142944043): Remove version script when libsigchain is a DSO.
- version_script: "version-script32.txt",
suffix: "32",
},
lib64: {
- // TODO(b/142944043): Remove version script when libsigchain is a DSO.
- version_script: "version-script64.txt",
suffix: "64",
},
},
@@ -43,6 +39,13 @@ cc_binary {
"libhidlbase",
"liblog",
"libnativeloader",
+
+ // Even though app_process doesn't call into libsigchain, we need to
+ // make sure it's in the DT list of app_process, as we want all code
+ // in app_process and the libraries it loads to find libsigchain
+ // symbols before libc symbols.
+ "libsigchain",
+
"libutils",
// This is a list of libraries that need to be included in order to avoid
@@ -52,8 +55,6 @@ cc_binary {
"libwilhelm",
],
- whole_static_libs: ["libsigchain"],
-
compile_multilib: "both",
cflags: [
diff --git a/cmds/app_process/version-script32.txt b/cmds/app_process/version-script32.txt
deleted file mode 100644
index 70810e0b7173..000000000000
--- a/cmds/app_process/version-script32.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-global:
- EnsureFrontOfChain;
- AddSpecialSignalHandlerFn;
- RemoveSpecialSignalHandlerFn;
- SkipAddSignalHandler;
- bsd_signal;
- sigaction;
- sigaction64;
- signal;
- sigprocmask;
- sigprocmask64;
-local:
- *;
-};
diff --git a/cmds/app_process/version-script64.txt b/cmds/app_process/version-script64.txt
deleted file mode 100644
index 7bcd76b50f87..000000000000
--- a/cmds/app_process/version-script64.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-global:
- EnsureFrontOfChain;
- AddSpecialSignalHandlerFn;
- RemoveSpecialSignalHandlerFn;
- SkipAddSignalHandler;
- sigaction;
- sigaction64;
- signal;
- sigprocmask;
- sigprocmask64;
-local:
- *;
-};
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 54c666314f98..0eb5553e11fa 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -10452,11 +10452,32 @@ package android.telecom {
method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onBluetoothCallQualityReportReceived(@NonNull android.telecom.BluetoothCallQualityReport);
method public abstract void onCallAudioStateChanged(@NonNull android.telecom.CallAudioState);
- method @NonNull public abstract android.telecom.DiagnosticCall onInitializeDiagnosticCall(@NonNull android.telecom.Call.Details);
- method public abstract void onRemoveDiagnosticCall(@NonNull android.telecom.DiagnosticCall);
+ method @NonNull public abstract android.telecom.CallDiagnostics onInitializeCallDiagnostics(@NonNull android.telecom.Call.Details);
+ method public abstract void onRemoveCallDiagnostics(@NonNull android.telecom.CallDiagnostics);
field public static final String SERVICE_INTERFACE = "android.telecom.CallDiagnosticService";
}
+ public abstract class CallDiagnostics {
+ ctor public CallDiagnostics();
+ method public final void clearDiagnosticMessage(int);
+ method public final void displayDiagnosticMessage(int, @NonNull CharSequence);
+ method public abstract void onCallDetailsChanged(@NonNull android.telecom.Call.Details);
+ method @Nullable public abstract CharSequence onCallDisconnected(int, int);
+ method @Nullable public abstract CharSequence onCallDisconnected(@NonNull android.telephony.ims.ImsReasonInfo);
+ method public abstract void onCallQualityReceived(@NonNull android.telephony.CallQuality);
+ method public abstract void onReceiveDeviceToDeviceMessage(int, int);
+ method public final void sendDeviceToDeviceMessage(int, int);
+ field public static final int BATTERY_STATE_CHARGING = 3; // 0x3
+ field public static final int BATTERY_STATE_GOOD = 2; // 0x2
+ field public static final int BATTERY_STATE_LOW = 1; // 0x1
+ field public static final int COVERAGE_GOOD = 2; // 0x2
+ field public static final int COVERAGE_POOR = 1; // 0x1
+ field public static final int MESSAGE_CALL_AUDIO_CODEC = 2; // 0x2
+ field public static final int MESSAGE_CALL_NETWORK_TYPE = 1; // 0x1
+ field public static final int MESSAGE_DEVICE_BATTERY_STATE = 3; // 0x3
+ field public static final int MESSAGE_DEVICE_NETWORK_COVERAGE = 4; // 0x4
+ }
+
public static class CallScreeningService.CallResponse.Builder {
method @NonNull @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT) public android.telecom.CallScreeningService.CallResponse.Builder setShouldScreenCallViaAudioProcessing(boolean);
}
@@ -10517,25 +10538,8 @@ package android.telecom {
method public final void addExistingConnection(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.Connection, @NonNull android.telecom.Conference);
}
- public abstract class DiagnosticCall {
- ctor public DiagnosticCall();
- method public final void clearDiagnosticMessage(int);
- method public final void displayDiagnosticMessage(int, @NonNull CharSequence);
- method public abstract void onCallDetailsChanged(@NonNull android.telecom.Call.Details);
- method @Nullable public abstract CharSequence onCallDisconnected(int, int);
- method @Nullable public abstract CharSequence onCallDisconnected(@NonNull android.telephony.ims.ImsReasonInfo);
- method public abstract void onCallQualityReceived(@NonNull android.telephony.CallQuality);
- method public abstract void onReceiveDeviceToDeviceMessage(int, int);
- method public final void sendDeviceToDeviceMessage(int, int);
- field public static final int BATTERY_STATE_CHARGING = 3; // 0x3
- field public static final int BATTERY_STATE_GOOD = 2; // 0x2
- field public static final int BATTERY_STATE_LOW = 1; // 0x1
- field public static final int COVERAGE_GOOD = 2; // 0x2
- field public static final int COVERAGE_POOR = 1; // 0x1
- field public static final int MESSAGE_CALL_AUDIO_CODEC = 2; // 0x2
- field public static final int MESSAGE_CALL_NETWORK_TYPE = 1; // 0x1
- field public static final int MESSAGE_DEVICE_BATTERY_STATE = 3; // 0x3
- field public static final int MESSAGE_DEVICE_NETWORK_COVERAGE = 4; // 0x4
+ @Deprecated public abstract class DiagnosticCall extends android.telecom.CallDiagnostics {
+ ctor @Deprecated public DiagnosticCall();
}
public abstract class InCallService extends android.app.Service {
diff --git a/core/java/android/net/NetworkScore.aidl b/core/java/android/net/NetworkScore.aidl
new file mode 100644
index 000000000000..af12dcf7f17a
--- /dev/null
+++ b/core/java/android/net/NetworkScore.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+parcelable NetworkScore;
+
diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java
new file mode 100644
index 000000000000..f47801002296
--- /dev/null
+++ b/core/java/android/net/NetworkScore.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Object representing the quality of a network as perceived by the user.
+ *
+ * A NetworkScore object represents the characteristics of a network that affects how good the
+ * network is considered for a particular use.
+ * @hide
+ */
+// TODO : @SystemApi when the implementation is complete
+public final class NetworkScore implements Parcelable {
+ // This will be removed soon. Do *NOT* depend on it for any new code that is not part of
+ // a migration.
+ private final int mLegacyInt;
+
+ /** @hide */
+ NetworkScore(final int legacyInt) {
+ this.mLegacyInt = legacyInt;
+ }
+
+ private NetworkScore(@NonNull final Parcel in) {
+ mLegacyInt = in.readInt();
+ }
+
+ public int getLegacyInt() {
+ return mLegacyInt;
+ }
+
+ @Override
+ public String toString() {
+ return "Score(" + mLegacyInt + ")";
+ }
+
+ @Override
+ public void writeToParcel(@NonNull final Parcel dest, final int flags) {
+ dest.writeInt(mLegacyInt);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull public static final Creator<NetworkScore> CREATOR = new Creator<>() {
+ @Override
+ @NonNull
+ public NetworkScore createFromParcel(@NonNull final Parcel in) {
+ return new NetworkScore(in);
+ }
+
+ @Override
+ @NonNull
+ public NetworkScore[] newArray(int size) {
+ return new NetworkScore[size];
+ }
+ };
+
+ /**
+ * A builder for NetworkScore.
+ */
+ public static final class Builder {
+ private static final int INVALID_LEGACY_INT = Integer.MIN_VALUE;
+ private int mLegacyInt = INVALID_LEGACY_INT;
+
+ /**
+ * Sets the legacy int for this score.
+ *
+ * Do not rely on this. It will be gone by the time S is released.
+ *
+ * @param score the legacy int
+ * @return this
+ */
+ @NonNull
+ public Builder setLegacyInt(final int score) {
+ mLegacyInt = score;
+ return this;
+ }
+
+ /**
+ * Builds this NetworkScore.
+ * @return The built NetworkScore object.
+ */
+ @NonNull
+ public NetworkScore build() {
+ return new NetworkScore(mLegacyInt);
+ }
+ }
+}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 4c26e2f33fb2..fa6472ee4a79 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -986,13 +986,13 @@ public abstract class BatteryStats implements Parcelable {
public abstract void getDeferredJobsLineLocked(StringBuilder sb, int which);
/**
- * Returns the battery consumption (in microcoulombs) of the screen while on and uid active,
+ * Returns the battery consumption (in microcoulombs) of bluetooth for this uid,
* derived from on device power measurement data.
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
*
* {@hide}
*/
- public abstract long getScreenOnMeasuredBatteryConsumptionUC();
+ public abstract long getBluetoothMeasuredBatteryConsumptionUC();
/**
* Returns the battery consumption (in microcoulombs) of the uid's cpu usage, derived from
@@ -1004,6 +1004,24 @@ public abstract class BatteryStats implements Parcelable {
public abstract long getCpuMeasuredBatteryConsumptionUC();
/**
+ * Returns the battery consumption (in microcoulombs) of the screen while on and uid active,
+ * derived from on device power measurement data.
+ * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
+ *
+ * {@hide}
+ */
+ public abstract long getScreenOnMeasuredBatteryConsumptionUC();
+
+ /**
+ * Returns the battery consumption (in microcoulombs) of wifi for this uid,
+ * derived from on device power measurement data.
+ * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
+ *
+ * {@hide}
+ */
+ public abstract long getWifiMeasuredBatteryConsumptionUC();
+
+ /**
* Returns the battery consumption (in microcoulombs) used by this uid for each
* {@link android.hardware.power.stats.EnergyConsumer.ordinal} of (custom) energy consumer
* type {@link android.hardware.power.stats.EnergyConsumerType#OTHER}).
@@ -2505,11 +2523,29 @@ public abstract class BatteryStats implements Parcelable {
};
/**
- * Returned value if power data is unavailable
+ * Returned value if power data is unavailable.
+ *
+ * {@hide}
+ */
+ public static final long POWER_DATA_UNAVAILABLE = -1L;
+
+ /**
+ * Returns the battery consumption (in microcoulombs) of bluetooth, derived from on
+ * device power measurement data.
+ * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
*
* {@hide}
*/
- public static final long POWER_DATA_UNAVAILABLE = -1;
+ public abstract long getBluetoothMeasuredBatteryConsumptionUC();
+
+ /**
+ * Returns the battery consumption (in microcoulombs) of the cpu, derived from on device power
+ * measurement data.
+ * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
+ *
+ * {@hide}
+ */
+ public abstract long getCpuMeasuredBatteryConsumptionUC();
/**
* Returns the battery consumption (in microcoulombs) of the screen while on, derived from on
@@ -2530,13 +2566,13 @@ public abstract class BatteryStats implements Parcelable {
public abstract long getScreenDozeMeasuredBatteryConsumptionUC();
/**
- * Returns the battery consumption (in microcoulombs) of the cpu, derived from on device power
- * measurement data.
+ * Returns the battery consumption (in microcoulombs) of wifi, derived from on
+ * device power measurement data.
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
*
* {@hide}
*/
- public abstract long getCpuMeasuredBatteryConsumptionUC();
+ public abstract long getWifiMeasuredBatteryConsumptionUC();
/**
* Returns the battery consumption (in microcoulombs) that each
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 0d9f715c11d4..a2edc93c6e5e 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -140,7 +140,7 @@ public class Build {
*/
@UnsupportedAppUsage
@TestApi
- public static final boolean IS_EMULATOR = getString("ro.kernel.qemu").equals("1");
+ public static final boolean IS_EMULATOR = getString("ro.boot.qemu").equals("1");
/**
* A hardware serial number, if available. Alphanumeric only, case-insensitive.
diff --git a/core/java/android/os/connectivity/WifiActivityEnergyInfo.java b/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
index 016cc2f3cdad..ad74a9f5c906 100644
--- a/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
+++ b/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
@@ -110,7 +110,7 @@ public final class WifiActivityEnergyInfo implements Parcelable {
}
// Calculate energy used using PowerProfile.
PowerProfile powerProfile = new PowerProfile(context);
- final double rxIdleCurrent = powerProfile.getAveragePower(
+ final double idleCurrent = powerProfile.getAveragePower(
PowerProfile.POWER_WIFI_CONTROLLER_IDLE);
final double rxCurrent = powerProfile.getAveragePower(
PowerProfile.POWER_WIFI_CONTROLLER_RX);
@@ -121,7 +121,7 @@ public final class WifiActivityEnergyInfo implements Parcelable {
return (long) ((txDurationMillis * txCurrent
+ rxDurationMillis * rxCurrent
- + idleDurationMillis * rxIdleCurrent)
+ + idleDurationMillis * idleCurrent)
* voltage);
}
diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS
index 718076b49f77..64570a8ad155 100644
--- a/core/java/android/widget/OWNERS
+++ b/core/java/android/widget/OWNERS
@@ -5,6 +5,8 @@ alanv@google.com
adamp@google.com
aurimas@google.com
siyamed@google.com
+mount@google.com
+njawad@google.com
per-file TextView.java, EditText.java, Editor.java = siyamed@google.com, nona@google.com, clarabayarri@google.com
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 11466f4bc042..33b55ac2f0a0 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -169,7 +169,7 @@ public class BatteryStatsImpl extends BatteryStats {
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- static final int VERSION = 194;
+ static final int VERSION = 195;
// The maximum number of names wakelocks we will keep track of
// per uid; once the limit is reached, we batch the remaining wakelocks
@@ -1009,8 +1009,12 @@ public class BatteryStatsImpl extends BatteryStats {
protected @Nullable MeasuredEnergyStats mGlobalMeasuredEnergyStats;
/** Last known screen state. Needed for apportioning display energy. */
int mScreenStateAtLastEnergyMeasurement = Display.STATE_UNKNOWN;
+ /** Bluetooth Power calculator for attributing measured bluetooth charge consumption to uids */
+ @Nullable BluetoothPowerCalculator mBluetoothPowerCalculator = null;
/** Cpu Power calculator for attributing measured cpu charge consumption to uids */
@Nullable CpuPowerCalculator mCpuPowerCalculator = null;
+ /** Wifi Power calculator for attributing measured wifi charge consumption to uids */
+ @Nullable WifiPowerCalculator mWifiPowerCalculator = null;
/**
* These provide time bases that discount the time the device is plugged
@@ -6967,6 +6971,16 @@ public class BatteryStatsImpl extends BatteryStats {
}
@Override
+ public long getBluetoothMeasuredBatteryConsumptionUC() {
+ return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH);
+ }
+
+ @Override
+ public long getCpuMeasuredBatteryConsumptionUC() {
+ return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
+ }
+
+ @Override
public long getScreenOnMeasuredBatteryConsumptionUC() {
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
}
@@ -6977,8 +6991,8 @@ public class BatteryStatsImpl extends BatteryStats {
}
@Override
- public long getCpuMeasuredBatteryConsumptionUC() {
- return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
+ public long getWifiMeasuredBatteryConsumptionUC() {
+ return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI);
}
/**
@@ -7815,6 +7829,26 @@ public class BatteryStatsImpl extends BatteryStats {
return mUidMeasuredEnergyStats.getAccumulatedCustomBucketCharges();
}
+ @Override
+ public long getBluetoothMeasuredBatteryConsumptionUC() {
+ return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH);
+ }
+
+ @Override
+ public long getCpuMeasuredBatteryConsumptionUC() {
+ return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
+ }
+
+ @Override
+ public long getScreenOnMeasuredBatteryConsumptionUC() {
+ return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
+ }
+
+ @Override
+ public long getWifiMeasuredBatteryConsumptionUC() {
+ return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_WIFI);
+ }
+
/**
* Gets the minimum of the uid's foreground activity time and its PROCESS_STATE_TOP time
* since last marked. Also sets the mark time for both these timers.
@@ -8482,16 +8516,6 @@ public class BatteryStatsImpl extends BatteryStats {
}
}
- @Override
- public long getScreenOnMeasuredBatteryConsumptionUC() {
- return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
- }
-
- @Override
- public long getCpuMeasuredBatteryConsumptionUC() {
- return getMeasuredBatteryConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_CPU);
- }
-
void initNetworkActivityLocked() {
detachIfNotNull(mNetworkByteActivityCounters);
mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
@@ -11437,7 +11461,7 @@ public class BatteryStatsImpl extends BatteryStats {
* @param info The energy information from the WiFi controller.
*/
public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
- long elapsedRealtimeMs, long uptimeMs) {
+ final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
if (DEBUG_ENERGY) {
Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
}
@@ -11459,9 +11483,21 @@ public class BatteryStatsImpl extends BatteryStats {
if (delta != null) {
mNetworkStatsPool.release(delta);
}
+ if (mIgnoreNextExternalStats) {
+ // TODO: Strictly speaking, we should re-mark all 5 timers for each uid (and the
+ // global one) here like we do for display. But I'm not sure it's worth the
+ // complicated code for a codepath that shouldn't ever actually happen in real
+ // life.
+ }
return;
}
+ final ArrayMap<Uid, Double> uidEstimatedConsumptionMah =
+ (mGlobalMeasuredEnergyStats != null
+ && mWifiPowerCalculator != null && consumedChargeUC > 0) ?
+ new ArrayMap<>() : null;
+ double totalEstimatedConsumptionMah = 0;
+
SparseLongArray rxPackets = new SparseLongArray();
SparseLongArray txPackets = new SparseLongArray();
long totalTxPackets = 0;
@@ -11496,6 +11532,7 @@ public class BatteryStatsImpl extends BatteryStats {
mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
entry.rxPackets);
+ // TODO(b/182845426): What if u was a mapped isolated uid? Shouldn't we sum?
rxPackets.put(u.getUid(), entry.rxPackets);
// Sum the total number of packets so that the Rx Power can
@@ -11515,12 +11552,42 @@ public class BatteryStatsImpl extends BatteryStats {
mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
entry.txPackets);
+ // TODO(b/182845426): What if u was a mapped isolated uid? Shouldn't we sum?
txPackets.put(u.getUid(), entry.txPackets);
// Sum the total number of packets so that the Tx Power can
// be evenly distributed amongst the apps.
totalTxPackets += entry.txPackets;
}
+
+ // Calculate consumed energy for this uid. Only do so if WifiReporting isn't
+ // enabled (if it is, we'll do it later instead using info).
+ if (uidEstimatedConsumptionMah != null && info == null && !mHasWifiReporting) {
+ final long uidRunningMs = u.mWifiRunningTimer
+ .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
+ if (uidRunningMs > 0) u.mWifiRunningTimer.setMark(elapsedRealtimeMs);
+
+ final long uidScanMs = u.mWifiScanTimer
+ .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
+ if (uidScanMs > 0) u.mWifiScanTimer.setMark(elapsedRealtimeMs);
+
+ long uidBatchScanMs = 0;
+ for (int bn = 0; bn < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bn++) {
+ if (u.mWifiBatchedScanTimer[bn] != null) {
+ long bnMs = u.mWifiBatchedScanTimer[bn]
+ .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
+ if (bnMs > 0) {
+ u.mWifiBatchedScanTimer[bn].setMark(elapsedRealtimeMs);
+ }
+ uidBatchScanMs += bnMs;
+ }
+ }
+
+ addDoubleToUidMap(uidEstimatedConsumptionMah, u,
+ mWifiPowerCalculator.calcPowerWithoutControllerDataMah(
+ entry.rxPackets, entry.txPackets,
+ uidRunningMs, uidScanMs, uidBatchScanMs));
+ }
}
mNetworkStatsPool.release(delta);
delta = null;
@@ -11581,15 +11648,14 @@ public class BatteryStatsImpl extends BatteryStats {
for (int i = 0; i < uidStatsSize; i++) {
final Uid uid = mUidStats.valueAt(i);
- long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
+ final long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000) / 1000;
+ long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
+ long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs; // not final
if (scanTimeSinceMarkMs > 0) {
// Set the new mark so that next time we get new data since this point.
uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
- long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
- long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
-
// Our total scan time is more than the reported Tx/Rx time.
// This is possible because the cost of a scan is approximate.
// Let's normalize the result so that we evenly blame each app
@@ -11623,6 +11689,7 @@ public class BatteryStatsImpl extends BatteryStats {
// Distribute evenly the power consumed while Idle to each app holding a WiFi
// lock.
+ long myIdleTimeMs = 0;
final long wifiLockTimeSinceMarkMs =
uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
elapsedRealtimeMs * 1000) / 1000;
@@ -11630,8 +11697,7 @@ public class BatteryStatsImpl extends BatteryStats {
// Set the new mark so that next time we get new data since this point.
uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
- final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
- / totalWifiLockTimeMs;
+ myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs) / totalWifiLockTimeMs;
if (DEBUG_ENERGY) {
Slog.d(TAG, " IdleTime for UID " + uid.getUid() + ": "
+ myIdleTimeMs + " ms");
@@ -11639,6 +11705,12 @@ public class BatteryStatsImpl extends BatteryStats {
uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
.addCountLocked(myIdleTimeMs);
}
+
+ if (uidEstimatedConsumptionMah != null) {
+ double uidEstMah = mWifiPowerCalculator.calcPowerFromControllerDataMah(
+ scanRxTimeSinceMarkMs, scanTxTimeSinceMarkMs, myIdleTimeMs);
+ addDoubleToUidMap(uidEstimatedConsumptionMah, uid, uidEstMah);
+ }
}
if (DEBUG_ENERGY) {
@@ -11658,6 +11730,11 @@ public class BatteryStatsImpl extends BatteryStats {
}
uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
.addCountLocked(myTxTimeMs);
+ if (uidEstimatedConsumptionMah != null) {
+ addDoubleToUidMap(uidEstimatedConsumptionMah, uid,
+ mWifiPowerCalculator.calcPowerFromControllerDataMah(
+ 0, myTxTimeMs, 0));
+ }
}
// Distribute the remaining Rx power appropriately between all apps that received
@@ -11672,6 +11749,11 @@ public class BatteryStatsImpl extends BatteryStats {
}
uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
.addCountLocked(myRxTimeMs);
+ if (uidEstimatedConsumptionMah != null) {
+ addDoubleToUidMap(uidEstimatedConsumptionMah, uid,
+ mWifiPowerCalculator.calcPowerFromControllerDataMah(
+ myRxTimeMs, 0, 0));
+ }
}
// Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
@@ -11690,10 +11772,11 @@ public class BatteryStatsImpl extends BatteryStats {
// POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
final double opVolt = mPowerProfile.getAveragePower(
PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
+ double controllerMaMs = 0;
if (opVolt != 0) {
// We store the power drain as mAms.
- mWifiActivity.getPowerCounter().addCountLocked(
- (long) (info.getControllerEnergyUsedMicroJoules() / opVolt));
+ controllerMaMs = info.getControllerEnergyUsedMicroJoules() / opVolt;
+ mWifiActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
}
// Converting uWs to mAms.
// Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms
@@ -11705,6 +11788,29 @@ public class BatteryStatsImpl extends BatteryStats {
(monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR);
addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mTmpRailStats.resetWifiTotalEnergyUsed();
+
+ if (uidEstimatedConsumptionMah != null) {
+ totalEstimatedConsumptionMah = Math.max(controllerMaMs / MILLISECONDS_IN_HOUR,
+ mWifiPowerCalculator.calcPowerFromControllerDataMah(
+ rxTimeMs, txTimeMs, idleTimeMs));
+ }
+ }
+
+ // Update the MeasuredEnergyStats information.
+ if (uidEstimatedConsumptionMah != null) {
+ mGlobalMeasuredEnergyStats.updateStandardBucket(
+ MeasuredEnergyStats.POWER_BUCKET_WIFI, consumedChargeUC);
+
+ // Now calculate the consumption for each uid, according to its proportional usage.
+ if (!mHasWifiReporting) {
+ final long globalTimeMs = mGlobalWifiRunningTimer
+ .getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000;
+ mGlobalWifiRunningTimer.setMark(elapsedRealtimeMs);
+ totalEstimatedConsumptionMah = mWifiPowerCalculator
+ .calcGlobalPowerWithoutControllerDataMah(globalTimeMs);
+ }
+ distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_WIFI,
+ consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedConsumptionMah);
}
}
}
@@ -11948,7 +12054,7 @@ public class BatteryStatsImpl extends BatteryStats {
* @param info The energy information from the bluetooth controller.
*/
public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info,
- long elapsedRealtimeMs, long uptimeMs) {
+ final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
if (DEBUG_ENERGY) {
Slog.d(TAG, "Updating bluetooth stats: " + info);
}
@@ -11980,6 +12086,11 @@ public class BatteryStatsImpl extends BatteryStats {
Slog.d(TAG, " Idle Time: " + idleTimeMs + " ms");
}
+ final ArrayMap<Uid, Double> uidEstimatedConsumptionMah =
+ (mGlobalMeasuredEnergyStats != null
+ && mBluetoothPowerCalculator != null && consumedChargeUC > 0) ?
+ new ArrayMap<>() : null;
+
long totalScanTimeMs = 0;
final int uidCount = mUidStats.size();
@@ -12038,6 +12149,12 @@ public class BatteryStatsImpl extends BatteryStats {
counter.getRxTimeCounter().addCountLocked(scanTimeRxSinceMarkMs);
counter.getTxTimeCounters()[0].addCountLocked(scanTimeTxSinceMarkMs);
+ if (uidEstimatedConsumptionMah != null) {
+ addDoubleToUidMap(uidEstimatedConsumptionMah, u,
+ mBluetoothPowerCalculator.calculatePowerMah(
+ scanTimeRxSinceMarkMs, scanTimeTxSinceMarkMs, 0));
+ }
+
leftOverRxTimeMs -= scanTimeRxSinceMarkMs;
leftOverTxTimeMs -= scanTimeTxSinceMarkMs;
}
@@ -12098,6 +12215,11 @@ public class BatteryStatsImpl extends BatteryStats {
Slog.d(TAG, "UID=" + uid + " rx_bytes=" + rxBytes + " rx_time=" + timeRxMs);
}
counter.getRxTimeCounter().addCountLocked(timeRxMs);
+
+ if (uidEstimatedConsumptionMah != null) {
+ addDoubleToUidMap(uidEstimatedConsumptionMah, u,
+ mBluetoothPowerCalculator.calculatePowerMah(timeRxMs, 0, 0));
+ }
}
if (totalTxBytes > 0 && txBytes > 0) {
@@ -12106,6 +12228,11 @@ public class BatteryStatsImpl extends BatteryStats {
Slog.d(TAG, "UID=" + uid + " tx_bytes=" + txBytes + " tx_time=" + timeTxMs);
}
counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
+
+ if (uidEstimatedConsumptionMah != null) {
+ addDoubleToUidMap(uidEstimatedConsumptionMah, u,
+ mBluetoothPowerCalculator.calculatePowerMah(0, timeTxMs, 0));
+ }
}
}
}
@@ -12117,12 +12244,26 @@ public class BatteryStatsImpl extends BatteryStats {
// POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
final double opVolt = mPowerProfile.getAveragePower(
PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
+ double controllerMaMs = 0;
if (opVolt != 0) {
+ controllerMaMs = (info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
+ / opVolt;
// We store the power drain as mAms.
- mBluetoothActivity.getPowerCounter().addCountLocked(
- (long) ((info.getControllerEnergyUsed() - mLastBluetoothActivityInfo.energy)
- / opVolt));
+ mBluetoothActivity.getPowerCounter().addCountLocked((long) controllerMaMs);
+ }
+
+ // Update the MeasuredEnergyStats information.
+ if (uidEstimatedConsumptionMah != null) {
+ mGlobalMeasuredEnergyStats.updateStandardBucket(
+ MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH, consumedChargeUC);
+
+ double totalEstimatedMah
+ = mBluetoothPowerCalculator.calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs);
+ totalEstimatedMah = Math.max(totalEstimatedMah, controllerMaMs / MILLISECONDS_IN_HOUR);
+ distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH,
+ consumedChargeUC, uidEstimatedConsumptionMah, totalEstimatedMah);
}
+
mLastBluetoothActivityInfo.set(info);
}
@@ -12311,37 +12452,17 @@ public class BatteryStatsImpl extends BatteryStats {
// If multidisplay becomes a reality, this is probably more reasonable than pooling.
// On the first pass, collect total time since mark so that we can normalize power.
- long totalFgTimeMs = 0L;
- final ArrayMap<Uid, Long> fgTimeMsArray = new ArrayMap<>();
+ final ArrayMap<Uid, Double> fgTimeUsArray = new ArrayMap<>();
final long elapsedRealtimeUs = elapsedRealtimeMs * 1000;
// TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
final int uidStatsSize = mUidStats.size();
for (int i = 0; i < uidStatsSize; i++) {
final Uid uid = mUidStats.valueAt(i);
- final long fgTimeMs = uid.markProcessForegroundTimeUs(elapsedRealtimeMs, true) / 1000;
- if (fgTimeMs == 0) continue;
- fgTimeMsArray.put(uid, fgTimeMs);
- totalFgTimeMs += fgTimeMs;
- }
- long totalDisplayChargeMC = chargeUC / 1000; // not final
-
- // Actually assign and distribute power usage to apps based on their fg time since mark.
- // TODO(b/175726326): Decide on 'energy' units and make sure algorithm won't overflow.
- final long fgTimeArraySize = fgTimeMsArray.size();
- for (int i = 0; i < fgTimeArraySize; i++) {
- final Uid uid = fgTimeMsArray.keyAt(i);
- final long fgTimeMs = fgTimeMsArray.valueAt(i);
-
- // Using long division: "appEnergy = totalEnergy * appFg/totalFg + 0.5" with rounding
- final long appDisplayChargeMC =
- (totalDisplayChargeMC * fgTimeMs + (totalFgTimeMs / 2))
- / totalFgTimeMs;
- uid.addChargeToStandardBucketLocked(appDisplayChargeMC * 1000, powerBucket);
-
- // To mitigate round-off errors, remove this app from numerator & denominator totals
- totalDisplayChargeMC -= appDisplayChargeMC;
- totalFgTimeMs -= fgTimeMs;
+ final long fgTimeUs = uid.markProcessForegroundTimeUs(elapsedRealtimeMs, true);
+ if (fgTimeUs == 0) continue;
+ fgTimeUsArray.put(uid, (double) fgTimeUs);
}
+ distributeEnergyToUidsLocked(powerBucket, chargeUC, fgTimeUsArray, 0);
}
/**
@@ -12389,6 +12510,54 @@ public class BatteryStatsImpl extends BatteryStats {
}
/**
+ * Attributes energy (for the given bucket) to each uid according to the following formula:
+ * blamedEnergy[uid] = totalEnergy * ratioNumerators[uid] / ratioDenominator;
+ * <p>Does nothing if ratioDenominator is 0.
+ *
+ * <p>Here, ratioDenominator = max(sumOfAllRatioNumerators, minRatioDenominator),
+ * so if given minRatioDenominator <= 0, then sumOfAllRatioNumerators will be used implicitly.
+ *
+ * <p>Note that ratioNumerators and minRatioDenominator must use the same units, but need not
+ * use the same units as totalConsumedChargeUC (which must be in microcoulombs).
+ *
+ * <p>A consequence of minRatioDenominator is that the sum over all uids might be less than
+ * totalConsumedChargeUC. This is intentional; the remainder is purposefully unnaccounted rather
+ * than incorrectly blamed on uids, and implies unknown (non-uid) sources of drain.
+ */
+ // TODO(b/182845832): Use some sort of "SparseDoubleArray" instead of ArrayMap<Uid, Double>.
+ private void distributeEnergyToUidsLocked(@StandardPowerBucket int bucket,
+ long totalConsumedChargeUC, ArrayMap<Uid, Double> ratioNumerators,
+ double minRatioDenominator) {
+
+ // If the sum of all app usage was greater than the total, use that instead:
+ double sumRatioNumerators = 0;
+ for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
+ sumRatioNumerators += ratioNumerators.valueAt(i);
+ }
+ final double ratioDenominator = Math.max(sumRatioNumerators, minRatioDenominator);
+ if (ratioDenominator <= 0) return;
+
+ for (int i = ratioNumerators.size() - 1; i >= 0; i--) {
+ final Uid uid = ratioNumerators.keyAt(i);
+ final double ratioNumerator = ratioNumerators.valueAt(i);
+ final long uidActualUC
+ = (long) (totalConsumedChargeUC * ratioNumerator / ratioDenominator + 0.5);
+ uid.addChargeToStandardBucketLocked(uidActualUC, bucket);
+ }
+ }
+
+ /** Adds the summand to the value stored in uidMap for the given uid. */
+ // TODO(b/182845832): Use some sort of "SparseDoubleArray" instead of ArrayMap<Uid, Double>.
+ private static void addDoubleToUidMap(ArrayMap<Uid, Double> uidMap, Uid uid, double summand) {
+ if (uidMap == null) return;
+ final Double oldVal = uidMap.get(uid);
+ if (oldVal != null) {
+ summand += oldVal;
+ }
+ uidMap.put(uid, summand);
+ }
+
+ /**
* Read and record Rail Energy data.
*/
public void updateRailStatsLocked() {
@@ -14222,15 +14391,20 @@ public class BatteryStatsImpl extends BatteryStats {
if (mGlobalMeasuredEnergyStats == null) {
mGlobalMeasuredEnergyStats =
new MeasuredEnergyStats(supportedStandardBuckets, numCustomBuckets);
- return;
} else {
supportedBucketMismatch = !mGlobalMeasuredEnergyStats.isSupportEqualTo(
supportedStandardBuckets, numCustomBuckets);
}
+ if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH]) {
+ mBluetoothPowerCalculator = new BluetoothPowerCalculator(mPowerProfile);
+ }
if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_CPU]) {
mCpuPowerCalculator = new CpuPowerCalculator(mPowerProfile);
}
+ if (supportedStandardBuckets[MeasuredEnergyStats.POWER_BUCKET_WIFI]) {
+ mWifiPowerCalculator = new WifiPowerCalculator(mPowerProfile);
+ }
}
if (supportedBucketMismatch) {
diff --git a/core/java/com/android/internal/os/BluetoothPowerCalculator.java b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
index 7d42de4486a4..db1403479f8a 100644
--- a/core/java/com/android/internal/os/BluetoothPowerCalculator.java
+++ b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
@@ -15,8 +15,11 @@
*/
package com.android.internal.os;
+import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
+
import android.os.BatteryConsumer;
import android.os.BatteryStats;
+import android.os.BatteryStats.ControllerActivityCounter;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
import android.os.Process;
@@ -65,17 +68,19 @@ public class BluetoothPowerCalculator extends PowerCalculator {
builder.getUidBatteryConsumerBuilders();
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
- calculateApp(app, total);
+ calculateApp(app, total, query);
if (app.getUid() == Process.BLUETOOTH_UID) {
app.excludeFromBatteryUsageStats();
systemBatteryConsumerBuilder.addUidBatteryConsumer(app);
}
}
- final BatteryStats.ControllerActivityCounter activityCounter =
+ final long measuredChargeUC = query.shouldForceUsePowerProfileModel() ?
+ POWER_DATA_UNAVAILABLE : batteryStats.getBluetoothMeasuredBatteryConsumptionUC();
+ final ControllerActivityCounter activityCounter =
batteryStats.getBluetoothControllerActivity();
final long systemDurationMs = calculateDuration(activityCounter);
- final double systemPowerMah = calculatePower(activityCounter);
+ final double systemPowerMah = calculatePowerMah(measuredChargeUC, activityCounter);
// Subtract what the apps used, but clamp to 0.
final long systemComponentDurationMs = Math.max(0, systemDurationMs - total.durationMs);
@@ -91,11 +96,16 @@ public class BluetoothPowerCalculator extends PowerCalculator {
systemComponentPowerMah);
}
- private void calculateApp(UidBatteryConsumer.Builder app, PowerAndDuration total) {
- final BatteryStats.ControllerActivityCounter activityCounter =
+ private void calculateApp(UidBatteryConsumer.Builder app, PowerAndDuration total,
+ BatteryUsageStatsQuery query) {
+
+ final long measuredChargeUC = query.shouldForceUsePowerProfileModel() ?
+ POWER_DATA_UNAVAILABLE :
+ app.getBatteryStatsUid().getBluetoothMeasuredBatteryConsumptionUC();
+ final ControllerActivityCounter activityCounter =
app.getBatteryStatsUid().getBluetoothControllerActivity();
final long durationMs = calculateDuration(activityCounter);
- final double powerMah = calculatePower(activityCounter);
+ final double powerMah = calculatePowerMah(measuredChargeUC, activityCounter);
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_BLUETOOTH, durationMs)
.setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerMah);
@@ -121,10 +131,11 @@ public class BluetoothPowerCalculator extends PowerCalculator {
}
BatterySipper bs = new BatterySipper(BatterySipper.DrainType.BLUETOOTH, null, 0);
- final BatteryStats.ControllerActivityCounter activityCounter =
+ final long measuredChargeUC = batteryStats.getBluetoothMeasuredBatteryConsumptionUC();
+ final ControllerActivityCounter activityCounter =
batteryStats.getBluetoothControllerActivity();
- final double systemPowerMah = calculatePower(activityCounter);
final long systemDurationMs = calculateDuration(activityCounter);
+ final double systemPowerMah = calculatePowerMah(measuredChargeUC, activityCounter);
// Subtract what the apps used, but clamp to 0.
final double powerMah = Math.max(0, systemPowerMah - total.powerMah);
@@ -152,10 +163,11 @@ public class BluetoothPowerCalculator extends PowerCalculator {
private void calculateApp(BatterySipper app, BatteryStats.Uid u, int statsType,
PowerAndDuration total) {
- final BatteryStats.ControllerActivityCounter activityCounter =
- u.getBluetoothControllerActivity();
+
+ final long measuredChargeUC = u.getBluetoothMeasuredBatteryConsumptionUC();
+ final ControllerActivityCounter activityCounter = u.getBluetoothControllerActivity();
final long durationMs = calculateDuration(activityCounter);
- final double powerMah = calculatePower(activityCounter);
+ final double powerMah = calculatePowerMah(measuredChargeUC, activityCounter);
app.bluetoothRunningTimeMs = durationMs;
app.bluetoothPowerMah = powerMah;
@@ -166,7 +178,7 @@ public class BluetoothPowerCalculator extends PowerCalculator {
total.powerMah += powerMah;
}
- private long calculateDuration(BatteryStats.ControllerActivityCounter counter) {
+ private long calculateDuration(ControllerActivityCounter counter) {
if (counter == null) {
return 0;
}
@@ -176,7 +188,11 @@ public class BluetoothPowerCalculator extends PowerCalculator {
+ counter.getTxTimeCounters()[0].getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
}
- private double calculatePower(BatteryStats.ControllerActivityCounter counter) {
+ /** Returns bluetooth power usage based on the best data available. */
+ private double calculatePowerMah(long measuredChargeUC, ControllerActivityCounter counter) {
+ if (measuredChargeUC != POWER_DATA_UNAVAILABLE) {
+ return uCtoMah(measuredChargeUC);
+ }
if (counter == null) {
return 0;
}
@@ -195,6 +211,11 @@ public class BluetoothPowerCalculator extends PowerCalculator {
counter.getRxTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
final long txTimeMs =
counter.getTxTimeCounters()[0].getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
+ return calculatePowerMah(rxTimeMs, txTimeMs, idleTimeMs);
+ }
+
+ /** Returns estimated bluetooth power usage based on usage times. */
+ public double calculatePowerMah(long rxTimeMs, long txTimeMs, long idleTimeMs) {
return ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))
/ (1000 * 60 * 60);
}
diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java
index 98f613fc1c40..b6bfde709cb8 100644
--- a/core/java/com/android/internal/os/WifiPowerCalculator.java
+++ b/core/java/com/android/internal/os/WifiPowerCalculator.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.os;
+import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
+
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
@@ -79,11 +81,6 @@ public class WifiPowerCalculator extends PowerCalculator {
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
- // batteryStats.hasWifiActivityReporting can change if we get energy data at a later point,
- // so always check this field.
- final boolean hasWifiPowerReporting =
- mHasWifiPowerController && batteryStats.hasWifiActivityReporting();
-
final SystemBatteryConsumer.Builder systemBatteryConsumerBuilder =
builder.getOrCreateSystemBatteryConsumerBuilder(
SystemBatteryConsumer.DRAIN_TYPE_WIFI);
@@ -97,7 +94,8 @@ public class WifiPowerCalculator extends PowerCalculator {
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
calculateApp(powerDurationAndTraffic, app.getBatteryStatsUid(), rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED,
- hasWifiPowerReporting);
+ batteryStats.hasWifiActivityReporting(),
+ query.shouldForceUsePowerProfileModel());
totalAppDurationMs += powerDurationAndTraffic.durationMs;
totalAppPowerMah += powerDurationAndTraffic.powerMah;
@@ -115,7 +113,9 @@ public class WifiPowerCalculator extends PowerCalculator {
calculateRemaining(powerDurationAndTraffic, batteryStats, rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED,
- hasWifiPowerReporting, totalAppDurationMs, totalAppPowerMah);
+ batteryStats.hasWifiActivityReporting(),
+ query.shouldForceUsePowerProfileModel(),
+ totalAppDurationMs, totalAppPowerMah);
systemBatteryConsumerBuilder
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI,
@@ -135,11 +135,6 @@ public class WifiPowerCalculator extends PowerCalculator {
public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
- // batteryStats.hasWifiActivityReporting can change if we get energy data at a later point,
- // so always check this field.
- final boolean hasWifiPowerReporting =
- mHasWifiPowerController && batteryStats.hasWifiActivityReporting();
-
final BatterySipper bs = new BatterySipper(BatterySipper.DrainType.WIFI, null, 0);
long totalAppDurationMs = 0;
@@ -149,7 +144,7 @@ public class WifiPowerCalculator extends PowerCalculator {
final BatterySipper app = sippers.get(i);
if (app.drainType == BatterySipper.DrainType.APP) {
calculateApp(powerDurationAndTraffic, app.uidObj, rawRealtimeUs, statsType,
- hasWifiPowerReporting);
+ batteryStats.hasWifiActivityReporting(), /* force use power model*/ false);
totalAppDurationMs += powerDurationAndTraffic.durationMs;
totalAppPowerMah += powerDurationAndTraffic.powerMah;
@@ -169,7 +164,8 @@ public class WifiPowerCalculator extends PowerCalculator {
}
calculateRemaining(powerDurationAndTraffic, batteryStats, rawRealtimeUs, statsType,
- hasWifiPowerReporting, totalAppDurationMs, totalAppPowerMah);
+ batteryStats.hasWifiActivityReporting(), /* force use power model*/ false,
+ totalAppDurationMs, totalAppPowerMah);
bs.wifiRunningTimeMs += powerDurationAndTraffic.durationMs;
bs.wifiPowerMah += powerDurationAndTraffic.powerMah;
@@ -180,8 +176,9 @@ public class WifiPowerCalculator extends PowerCalculator {
}
private void calculateApp(PowerDurationAndTraffic powerDurationAndTraffic, BatteryStats.Uid u,
- long rawRealtimeUs,
- int statsType, boolean hasWifiPowerReporting) {
+ long rawRealtimeUs, int statsType,
+ boolean hasWifiActivityReporting, boolean shouldForceUsePowerProfileModel) {
+
powerDurationAndTraffic.wifiRxPackets = u.getNetworkActivityPackets(
BatteryStats.NETWORK_WIFI_RX_DATA,
statsType);
@@ -195,7 +192,14 @@ public class WifiPowerCalculator extends PowerCalculator {
BatteryStats.NETWORK_WIFI_TX_DATA,
statsType);
- if (hasWifiPowerReporting) {
+ final long measuredChargeUC = u.getWifiMeasuredBatteryConsumptionUC();
+ final boolean isMeasuredPowerAvailable
+ = !shouldForceUsePowerProfileModel && measuredChargeUC != POWER_DATA_UNAVAILABLE;
+ if (isMeasuredPowerAvailable) {
+ powerDurationAndTraffic.powerMah = uCtoMah(measuredChargeUC);
+ }
+
+ if (hasWifiActivityReporting && mHasWifiPowerController) {
final BatteryStats.ControllerActivityCounter counter = u.getWifiControllerActivity();
if (counter != null) {
final long idleTime = counter.getIdleTimeCounter().getCountLocked(statsType);
@@ -203,9 +207,10 @@ public class WifiPowerCalculator extends PowerCalculator {
final long rxTime = counter.getRxTimeCounter().getCountLocked(statsType);
powerDurationAndTraffic.durationMs = idleTime + rxTime + txTime;
- powerDurationAndTraffic.powerMah = mIdlePowerEstimator.calculatePower(idleTime)
- + mTxPowerEstimator.calculatePower(txTime)
- + mRxPowerEstimator.calculatePower(rxTime);
+ if (!isMeasuredPowerAvailable) {
+ powerDurationAndTraffic.powerMah
+ = calcPowerFromControllerDataMah(rxTime, txTime, idleTime);
+ }
if (DEBUG && powerDurationAndTraffic.powerMah != 0) {
Log.d(TAG, "UID " + u.getUid() + ": idle=" + idleTime + "ms rx=" + rxTime
@@ -214,21 +219,20 @@ public class WifiPowerCalculator extends PowerCalculator {
}
}
} else {
- final double wifiPacketPower = (
- powerDurationAndTraffic.wifiRxPackets + powerDurationAndTraffic.wifiTxPackets)
- * mWifiPowerPerPacket;
final long wifiRunningTime = u.getWifiRunningTime(rawRealtimeUs, statsType) / 1000;
- final long wifiScanTimeMs = u.getWifiScanTime(rawRealtimeUs, statsType) / 1000;
- long batchScanTimeMs = 0;
- for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
- batchScanTimeMs += u.getWifiBatchedScanTime(bin, rawRealtimeUs, statsType) / 1000;
- }
-
powerDurationAndTraffic.durationMs = wifiRunningTime;
- powerDurationAndTraffic.powerMah = wifiPacketPower
- + mPowerOnPowerEstimator.calculatePower(wifiRunningTime)
- + mScanPowerEstimator.calculatePower(wifiScanTimeMs)
- + mBatchScanPowerEstimator.calculatePower(batchScanTimeMs);
+
+ if (!isMeasuredPowerAvailable) {
+ final long wifiScanTimeMs = u.getWifiScanTime(rawRealtimeUs, statsType) / 1000;
+ long batchTimeMs = 0;
+ for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
+ batchTimeMs += u.getWifiBatchedScanTime(bin, rawRealtimeUs, statsType) / 1000;
+ }
+ powerDurationAndTraffic.powerMah = calcPowerWithoutControllerDataMah(
+ powerDurationAndTraffic.wifiRxPackets,
+ powerDurationAndTraffic.wifiTxPackets,
+ wifiRunningTime, wifiScanTimeMs, batchTimeMs);
+ }
if (DEBUG && powerDurationAndTraffic.powerMah != 0) {
Log.d(TAG, "UID " + u.getUid() + ": power=" + formatCharge(
@@ -238,12 +242,20 @@ public class WifiPowerCalculator extends PowerCalculator {
}
private void calculateRemaining(PowerDurationAndTraffic powerDurationAndTraffic,
- BatteryStats stats, long rawRealtimeUs,
- int statsType, boolean hasWifiPowerReporting, long totalAppDurationMs,
- double totalAppPowerMah) {
+ BatteryStats stats, long rawRealtimeUs, int statsType,
+ boolean hasWifiActivityReporting, boolean shouldForceUsePowerProfileModel,
+ long totalAppDurationMs, double totalAppPowerMah) {
+
long totalDurationMs;
- double totalPowerMah;
- if (hasWifiPowerReporting) {
+ double totalPowerMah = 0;
+
+ final long measuredChargeUC = stats.getWifiMeasuredBatteryConsumptionUC();
+ final boolean isMeasuredPowerAvailable
+ = !shouldForceUsePowerProfileModel && measuredChargeUC != POWER_DATA_UNAVAILABLE;
+ if (isMeasuredPowerAvailable) {
+ totalPowerMah = uCtoMah(measuredChargeUC);
+ }
+ if (hasWifiActivityReporting && mHasWifiPowerController) {
final BatteryStats.ControllerActivityCounter counter =
stats.getWifiControllerActivity();
@@ -253,17 +265,19 @@ public class WifiPowerCalculator extends PowerCalculator {
totalDurationMs = idleTimeMs + rxTimeMs + txTimeMs;
- totalPowerMah =
- counter.getPowerCounter().getCountLocked(statsType) / (double) (1000 * 60 * 60);
- if (totalPowerMah == 0) {
- // Some controllers do not report power drain, so we can calculate it here.
- totalPowerMah = mIdlePowerEstimator.calculatePower(idleTimeMs)
- + mTxPowerEstimator.calculatePower(txTimeMs)
- + mRxPowerEstimator.calculatePower(rxTimeMs);
+ if (!isMeasuredPowerAvailable) {
+ totalPowerMah = counter.getPowerCounter().getCountLocked(statsType)
+ / (double) (1000 * 60 * 60);
+ if (totalPowerMah == 0) {
+ // Some controllers do not report power drain, so we can calculate it here.
+ totalPowerMah = calcPowerFromControllerDataMah(rxTimeMs, txTimeMs, idleTimeMs);
+ }
}
} else {
totalDurationMs = stats.getGlobalWifiRunningTime(rawRealtimeUs, statsType) / 1000;
- totalPowerMah = mPowerOnPowerEstimator.calculatePower(totalDurationMs);
+ if (!isMeasuredPowerAvailable) {
+ totalPowerMah = calcGlobalPowerWithoutControllerDataMah(totalDurationMs);
+ }
}
powerDurationAndTraffic.durationMs = Math.max(0, totalDurationMs - totalAppDurationMs);
@@ -274,6 +288,29 @@ public class WifiPowerCalculator extends PowerCalculator {
}
}
+ /** Returns (global or uid) estimated wifi power used using WifiControllerActivity data. */
+ public double calcPowerFromControllerDataMah(long rxTimeMs, long txTimeMs, long idleTimeMs) {
+ return mRxPowerEstimator.calculatePower(rxTimeMs)
+ + mTxPowerEstimator.calculatePower(txTimeMs)
+ + mIdlePowerEstimator.calculatePower(idleTimeMs);
+ }
+
+ /** Returns per-uid estimated wifi power used using non-WifiControllerActivity data. */
+ public double calcPowerWithoutControllerDataMah(long rxPackets, long txPackets,
+ long wifiRunningTimeMs, long wifiScanTimeMs, long wifiBatchScanTimeMs) {
+ return
+ (rxPackets + txPackets) * mWifiPowerPerPacket
+ + mPowerOnPowerEstimator.calculatePower(wifiRunningTimeMs)
+ + mScanPowerEstimator.calculatePower(wifiScanTimeMs)
+ + mBatchScanPowerEstimator.calculatePower(wifiBatchScanTimeMs);
+
+ }
+
+ /** Returns global estimated wifi power used using non-WifiControllerActivity data. */
+ public double calcGlobalPowerWithoutControllerDataMah(long globalWifiRunningTimeMs) {
+ return mPowerOnPowerEstimator.calculatePower(globalWifiRunningTimeMs);
+ }
+
/**
* Return estimated power per Wi-Fi packet in mAh/packet where 1 packet = 2 KB.
*/
diff --git a/core/java/com/android/internal/power/MeasuredEnergyStats.java b/core/java/com/android/internal/power/MeasuredEnergyStats.java
index e3d5464ca413..845b3e501c08 100644
--- a/core/java/com/android/internal/power/MeasuredEnergyStats.java
+++ b/core/java/com/android/internal/power/MeasuredEnergyStats.java
@@ -52,7 +52,9 @@ public class MeasuredEnergyStats {
public static final int POWER_BUCKET_SCREEN_DOZE = 1;
public static final int POWER_BUCKET_SCREEN_OTHER = 2;
public static final int POWER_BUCKET_CPU = 3;
- public static final int NUMBER_STANDARD_POWER_BUCKETS = 4; // Buckets above this are custom.
+ public static final int POWER_BUCKET_WIFI = 4;
+ public static final int POWER_BUCKET_BLUETOOTH = 5;
+ public static final int NUMBER_STANDARD_POWER_BUCKETS = 6; // Buckets above this are custom.
@IntDef(prefix = {"POWER_BUCKET_"}, value = {
POWER_BUCKET_UNKNOWN,
@@ -60,6 +62,8 @@ public class MeasuredEnergyStats {
POWER_BUCKET_SCREEN_DOZE,
POWER_BUCKET_SCREEN_OTHER,
POWER_BUCKET_CPU,
+ POWER_BUCKET_WIFI,
+ POWER_BUCKET_BLUETOOTH,
})
@Retention(RetentionPolicy.SOURCE)
public @interface StandardPowerBucket {
diff --git a/core/java/com/android/internal/view/inline/OWNERS b/core/java/com/android/internal/view/inline/OWNERS
new file mode 100644
index 000000000000..edfb2112198a
--- /dev/null
+++ b/core/java/com/android/internal/view/inline/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/autofill/OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
index 8aeb761ffc4d..80ab36ec84cf 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
@@ -33,11 +33,15 @@ import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
+import com.android.internal.power.MeasuredEnergyStats;
+
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.mockito.stubbing.Answer;
+import java.util.Arrays;
+
public class BatteryUsageStatsRule implements TestRule {
private final PowerProfile mPowerProfile;
private final MockClocks mMockClocks = new MockClocks();
@@ -98,6 +102,16 @@ public class BatteryUsageStatsRule implements TestRule {
return this;
}
+ /** Call only after setting the power profile information. */
+ public BatteryUsageStatsRule initMeasuredEnergyStatsLocked(int numCustom) {
+ final boolean[] supportedStandardBuckets =
+ new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS];
+ Arrays.fill(supportedStandardBuckets, true);
+ mBatteryStats.initMeasuredEnergyStatsLocked(supportedStandardBuckets, numCustom);
+ mBatteryStats.informThatAllExternalStatsAreFlushed();
+ return this;
+ }
+
public BatteryUsageStatsRule startWithScreenOn(boolean screenOn) {
mScreenOn = screenOn;
return this;
diff --git a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
index f6aa08bf0645..99cca0b26b1a 100644
--- a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.annotation.Nullable;
import android.os.BatteryConsumer;
+import android.os.BatteryUsageStatsQuery;
import android.os.Process;
import android.os.SystemBatteryConsumer;
@@ -60,7 +61,8 @@ public class BluetoothPowerCalculatorTest {
BluetoothPowerCalculator calculator =
new BluetoothPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(calculator);
+ mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
+ calculator);
assertBluetoothPowerAndDuration(
mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID),
@@ -91,7 +93,8 @@ public class BluetoothPowerCalculatorTest {
BluetoothPowerCalculator calculator =
new BluetoothPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(calculator);
+ mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
+ calculator);
assertBluetoothPowerAndDuration(
mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID),
diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
index a47c4d832083..26adbe9e7c59 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -46,6 +46,7 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
initTimersAndCounters();
setExternalStatsSyncLocked(new DummyExternalStatsSync());
+ informThatAllExternalStatsAreFlushed();
final boolean[] supportedStandardBuckets =
new boolean[MeasuredEnergyStats.NUMBER_STANDARD_POWER_BUCKETS];
diff --git a/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
index e1005457c289..2e23dc8dbba8 100644
--- a/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
@@ -17,11 +17,14 @@
package com.android.internal.os;
+import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
+
import static com.google.common.truth.Truth.assertThat;
import android.net.NetworkCapabilities;
import android.net.NetworkStats;
import android.os.BatteryConsumer;
+import android.os.BatteryUsageStatsQuery;
import android.os.Process;
import android.os.SystemBatteryConsumer;
import android.os.UidBatteryConsumer;
@@ -50,10 +53,11 @@ public class WifiPowerCalculatorTest {
.setAveragePower(PowerProfile.POWER_WIFI_ON, 360.0)
.setAveragePower(PowerProfile.POWER_WIFI_SCAN, 480.0)
.setAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN, 720.0)
- .setAveragePower(PowerProfile.POWER_WIFI_ACTIVE, 1080.0);
+ .setAveragePower(PowerProfile.POWER_WIFI_ACTIVE, 1080.0)
+ .initMeasuredEnergyStatsLocked(0);
- @Test
- public void testPowerControllerBasedModel() {
+ /** Sets up a batterystats object with pre-populated network values. */
+ private BatteryStatsImpl setupTestNetworkNumbers() {
BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
batteryStats.noteNetworkInterfaceForTransports("wifi",
@@ -64,13 +68,25 @@ public class WifiPowerCalculatorTest {
.insertEntry("wifi", Process.WIFI_UID, 0, 0, 1111, 111, 2222, 22, 111);
mStatsRule.setNetworkStats(networkStats);
- WifiActivityEnergyInfo energyInfo = new WifiActivityEnergyInfo(10000,
+ return batteryStats;
+ }
+
+ /** Sets up an WifiActivityEnergyInfo for ActivityController-model-based tests. */
+ private WifiActivityEnergyInfo setupPowerControllerBasedModelEnergyNumbersInfo() {
+ return new WifiActivityEnergyInfo(10000,
WifiActivityEnergyInfo.STACK_STATE_STATE_ACTIVE, 1000, 2000, 3000, 4000);
+ }
+
+ @Test
+ public void testPowerControllerBasedModel_nonMeasured() {
+ final BatteryStatsImpl batteryStats = setupTestNetworkNumbers();
+ final WifiActivityEnergyInfo energyInfo = setupPowerControllerBasedModelEnergyNumbersInfo();
- batteryStats.updateWifiState(energyInfo, 1000, 1000);
+ batteryStats.updateWifiState(energyInfo, POWER_DATA_UNAVAILABLE, 1000, 1000);
WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(calculator);
+ mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
+ calculator);
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
@@ -87,30 +103,54 @@ public class WifiPowerCalculatorTest {
}
@Test
- public void testTimerBasedModel() {
- BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+ public void testPowerControllerBasedModel_measured() {
+ final BatteryStatsImpl batteryStats = setupTestNetworkNumbers();
+ final WifiActivityEnergyInfo energyInfo = setupPowerControllerBasedModelEnergyNumbersInfo();
- batteryStats.noteNetworkInterfaceForTransports("wifi",
- new int[]{NetworkCapabilities.TRANSPORT_WIFI});
+ batteryStats.updateWifiState(energyInfo, 1_000_000, 1000, 1000);
- NetworkStats networkStats = new NetworkStats(10000, 1)
- .insertEntry("wifi", APP_UID, 0, 0, 1000, 100, 2000, 20, 100)
- .insertEntry("wifi", Process.WIFI_UID, 0, 0, 1111, 111, 2222, 22, 111);
- mStatsRule.setNetworkStats(networkStats);
+ WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
+ mStatsRule.apply(calculator);
+ UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
+ assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
+ .isEqualTo(1423);
+ /* Same ratio as in testPowerControllerBasedModel_nonMeasured but scaled by 1_000_000uC. */
+ assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isWithin(PRECISION).of(0.2214666 / (0.2214666 + 0.645200) * 1_000_000 / 3600000);
+
+ SystemBatteryConsumer systemConsumer =
+ mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI);
+ assertThat(systemConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
+ .isEqualTo(5577);
+ /* Same ratio as in testPowerControllerBasedModel_nonMeasured but scaled by 1_000_000uC. */
+ assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isWithin(PRECISION).of(0.645200 / (0.2214666 + 0.645200) * 1_000_000 / 3600000);
+ }
+
+ /** Sets up batterystats object with prepopulated network & timer data for Timer-model tests. */
+ private BatteryStatsImpl setupTimerBasedModelTestNumbers() {
+ final BatteryStatsImpl batteryStats = setupTestNetworkNumbers();
batteryStats.noteWifiScanStartedLocked(APP_UID, 1000, 1000);
batteryStats.noteWifiScanStoppedLocked(APP_UID, 2000, 2000);
batteryStats.noteWifiRunningLocked(new WorkSource(APP_UID), 3000, 3000);
batteryStats.noteWifiStoppedLocked(new WorkSource(APP_UID), 4000, 4000);
batteryStats.noteWifiRunningLocked(new WorkSource(Process.WIFI_UID), 1111, 2222);
batteryStats.noteWifiStoppedLocked(new WorkSource(Process.WIFI_UID), 3333, 4444);
+ return batteryStats;
+ }
+
+ @Test
+ public void testTimerBasedModel_nonMeasured() {
+ final BatteryStatsImpl batteryStats = setupTimerBasedModelTestNumbers();
// Don't pass WifiActivityEnergyInfo, making WifiPowerCalculator rely exclusively
// on the packet counts.
- batteryStats.updateWifiState(/* energyInfo */ null, 1000, 1000);
+ batteryStats.updateWifiState(/* energyInfo */ null, POWER_DATA_UNAVAILABLE, 1000, 1000);
WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(calculator);
+ mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
+ calculator);
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
@@ -125,4 +165,31 @@ public class WifiPowerCalculatorTest {
assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
.isWithin(PRECISION).of(0.8759216);
}
+
+ @Test
+ public void testTimerBasedModel_measured() {
+ final BatteryStatsImpl batteryStats = setupTimerBasedModelTestNumbers();
+
+ // Don't pass WifiActivityEnergyInfo, making WifiPowerCalculator rely exclusively
+ // on the packet counts.
+ batteryStats.updateWifiState(/* energyInfo */ null, 1_000_000, 1000, 1000);
+
+ WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
+ mStatsRule.apply(calculator);
+
+ UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
+ assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
+ .isEqualTo(1000);
+ /* Same ratio as in testTimerBasedModel_nonMeasured but scaled by 1_000_000uC. */
+ assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isWithin(PRECISION).of(0.8231573 / (0.8231573 + 0.8759216) * 1_000_000 / 3600000);
+
+ SystemBatteryConsumer systemConsumer =
+ mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI);
+ assertThat(systemConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
+ .isEqualTo(2222);
+ /* Same ratio as in testTimerBasedModel_nonMeasured but scaled by 1_000_000uC. */
+ assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isWithin(PRECISION).of(0.8759216 / (0.8231573 + 0.8759216) * 1_000_000 / 3600000);
+ }
}
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 971a53a8b2dc..e58f31fd15eb 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -126,7 +126,7 @@ bool Properties::load() {
SkAndroidFrameworkTraceUtil::setEnableTracing(
base::GetBoolProperty(PROPERTY_SKIA_ATRACE_ENABLED, false));
- runningInEmulator = base::GetBoolProperty(PROPERTY_QEMU_KERNEL, false);
+ runningInEmulator = base::GetBoolProperty(PROPERTY_IS_EMULATOR, false);
return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw);
}
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index dcb79babad24..42aa87b492e2 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -160,7 +160,7 @@ enum DebugLevel {
/**
* Property for whether this is running in the emulator.
*/
-#define PROPERTY_QEMU_KERNEL "ro.kernel.qemu"
+#define PROPERTY_IS_EMULATOR "ro.boot.qemu"
///////////////////////////////////////////////////////////////////////////////
// Misc
diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp
index 49c2b39f8904..309d71cfd062 100644
--- a/media/jni/soundpool/StreamManager.cpp
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -358,14 +358,14 @@ void StreamManager::addToActiveQueue_l(Stream *stream) {
void StreamManager::run(int32_t id)
{
ALOGV("%s(%d) entering", __func__, id);
- int64_t waitTimeNs = kWaitTimeBeforeCloseNs;
+ int64_t waitTimeNs = 0; // on thread start, mRestartStreams can be non-empty.
std::unique_lock lock(mStreamManagerLock);
while (!mQuit) {
- if (mRestartStreams.empty()) { // on thread start, mRestartStreams can be non-empty.
+ if (waitTimeNs > 0) {
mStreamManagerCondition.wait_for(
lock, std::chrono::duration<int64_t, std::nano>(waitTimeNs));
}
- ALOGV("%s(%d) awake", __func__, id);
+ ALOGV("%s(%d) awake lock waitTimeNs:%lld", __func__, id, (long long)waitTimeNs);
sanityCheckQueue_l();
diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt
index b9bcddba5d0a..cc95a7cc2413 100644
--- a/packages/Connectivity/framework/api/module-lib-current.txt
+++ b/packages/Connectivity/framework/api/module-lib-current.txt
@@ -29,6 +29,11 @@ package android.net {
field public static final int TRANSPORT_TEST = 7; // 0x7
}
+ public class ParseException extends java.lang.RuntimeException {
+ ctor public ParseException(@NonNull String);
+ ctor public ParseException(@NonNull String, @NonNull Throwable);
+ }
+
public final class TcpRepairWindow {
ctor public TcpRepairWindow(int, int, int, int, int, int);
field public final int maxWindow;
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
index 6d6a5547930c..7bfc9702ba6a 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
@@ -18,8 +18,8 @@ package android.net;
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST;
import static android.net.NetworkRequest.Type.LISTEN;
+import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST;
import static android.net.NetworkRequest.Type.REQUEST;
-import static android.net.NetworkRequest.Type.TRACK_BEST;
import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT;
import static android.net.QosCallback.QosCallbackRegistrationException;
@@ -3213,10 +3213,6 @@ public class ConnectivityManager {
}
}
- // TODO : remove this method. It is a stopgap measure to help sheperding a number
- // of dependent changes that would conflict throughout the automerger graph. Having this
- // temporarily helps with the process of going through with all these dependent changes across
- // the entire tree.
/**
* @hide
* Register a NetworkAgent with ConnectivityService.
@@ -3226,20 +3222,8 @@ public class ConnectivityManager {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_FACTORY})
public Network registerNetworkAgent(INetworkAgent na, NetworkInfo ni, LinkProperties lp,
- NetworkCapabilities nc, int score, NetworkAgentConfig config) {
- return registerNetworkAgent(na, ni, lp, nc, score, config, NetworkProvider.ID_NONE);
- }
-
- /**
- * @hide
- * Register a NetworkAgent with ConnectivityService.
- * @return Network corresponding to NetworkAgent.
- */
- @RequiresPermission(anyOf = {
- NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- android.Manifest.permission.NETWORK_FACTORY})
- public Network registerNetworkAgent(INetworkAgent na, NetworkInfo ni, LinkProperties lp,
- NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) {
+ NetworkCapabilities nc, @NonNull NetworkScore score, NetworkAgentConfig config,
+ int providerId) {
try {
return mService.registerNetworkAgent(na, ni, lp, nc, score, config, providerId);
} catch (RemoteException e) {
@@ -4265,7 +4249,7 @@ public class ConnectivityManager {
@NonNull NetworkCallback networkCallback, @NonNull Handler handler) {
final NetworkCapabilities nc = request.networkCapabilities;
final CallbackHandler cbHandler = new CallbackHandler(handler);
- sendRequestForNetwork(nc, networkCallback, 0, TRACK_BEST, TYPE_NONE, cbHandler);
+ sendRequestForNetwork(nc, networkCallback, 0, LISTEN_FOR_BEST, TYPE_NONE, cbHandler);
}
/**
@@ -5121,9 +5105,9 @@ public class ConnectivityManager {
}
// The first network ID of IPSec tunnel interface.
- private static final int TUN_INTF_NETID_START = 0xFC00;
+ private static final int TUN_INTF_NETID_START = 0xFC00; // 0xFC00 = 64512
// The network ID range of IPSec tunnel interface.
- private static final int TUN_INTF_NETID_RANGE = 0x0400;
+ private static final int TUN_INTF_NETID_RANGE = 0x0400; // 0x0400 = 1024
/**
* Get the network ID range reserved for IPSec tunnel interfaces.
diff --git a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl
index f9393e315b83..1bbf1a95fcca 100644
--- a/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl
+++ b/packages/Connectivity/framework/src/android/net/IConnectivityManager.aidl
@@ -30,6 +30,7 @@ import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest;
+import android.net.NetworkScore;
import android.net.NetworkState;
import android.net.NetworkStateSnapshot;
import android.net.OemNetworkPreferences;
@@ -138,7 +139,7 @@ interface IConnectivityManager
void declareNetworkRequestUnfulfillable(in NetworkRequest request);
Network registerNetworkAgent(in INetworkAgent na, in NetworkInfo ni, in LinkProperties lp,
- in NetworkCapabilities nc, int score, in NetworkAgentConfig config,
+ in NetworkCapabilities nc, in NetworkScore score, in NetworkAgentConfig config,
in int factorySerialNumber);
NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, int reqType,
diff --git a/packages/Connectivity/framework/src/android/net/Network.java b/packages/Connectivity/framework/src/android/net/Network.java
index 46141e0d0c1e..7245db3b17db 100644
--- a/packages/Connectivity/framework/src/android/net/Network.java
+++ b/packages/Connectivity/framework/src/android/net/Network.java
@@ -30,10 +30,10 @@ import android.system.OsConstants;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
-import com.android.okhttp.internalandroidapi.Dns;
-import com.android.okhttp.internalandroidapi.HttpURLConnectionFactory;
import libcore.io.IoUtils;
+import libcore.net.http.Dns;
+import libcore.net.http.HttpURLConnectionFactory;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -299,7 +299,7 @@ public class Network implements Parcelable {
// Set configuration on the HttpURLConnectionFactory that will be good for all
// connections created by this Network. Configuration that might vary is left
// until openConnection() and passed as arguments.
- HttpURLConnectionFactory urlConnectionFactory = new HttpURLConnectionFactory();
+ HttpURLConnectionFactory urlConnectionFactory = HttpURLConnectionFactory.createInstance();
urlConnectionFactory.setDns(dnsLookup); // Let traffic go via dnsLookup
// A private connection pool just for this Network.
urlConnectionFactory.setNewConnectionPool(httpMaxConnections,
diff --git a/packages/Connectivity/framework/src/android/net/NetworkAgent.java b/packages/Connectivity/framework/src/android/net/NetworkAgent.java
index 27aa15d1e1e4..b3ab0ee8bd3c 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkAgent.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkAgent.java
@@ -371,6 +371,14 @@ public abstract class NetworkAgent {
return ni;
}
+ // Temporary backward compatibility constructor
+ public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag,
+ @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score,
+ @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) {
+ this(context, looper, logTag, nc, lp,
+ new NetworkScore.Builder().setLegacyInt(score).build(), config, provider);
+ }
+
/**
* Create a new network agent.
* @param context a {@link Context} to get system services from.
@@ -382,10 +390,12 @@ public abstract class NetworkAgent {
* @param score the initial score of this network. Update with sendNetworkScore.
* @param config an immutable {@link NetworkAgentConfig} for this agent.
* @param provider the {@link NetworkProvider} managing this agent.
+ * @hide TODO : unhide when impl is complete
*/
public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag,
- @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score,
- @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) {
+ @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp,
+ @NonNull NetworkScore score, @NonNull NetworkAgentConfig config,
+ @Nullable NetworkProvider provider) {
this(looper, context, logTag, nc, lp, score, config,
provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(),
getLegacyNetworkInfo(config));
@@ -395,12 +405,12 @@ public abstract class NetworkAgent {
public final Context context;
public final NetworkCapabilities capabilities;
public final LinkProperties properties;
- public final int score;
+ public final NetworkScore score;
public final NetworkAgentConfig config;
public final NetworkInfo info;
InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities,
- @NonNull LinkProperties properties, int score, @NonNull NetworkAgentConfig config,
- @NonNull NetworkInfo info) {
+ @NonNull LinkProperties properties, @NonNull NetworkScore score,
+ @NonNull NetworkAgentConfig config, @NonNull NetworkInfo info) {
this.context = context;
this.capabilities = capabilities;
this.properties = properties;
@@ -412,8 +422,9 @@ public abstract class NetworkAgent {
private volatile InitialConfiguration mInitialConfiguration;
private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag,
- @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score,
- @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni) {
+ @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp,
+ @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, int providerId,
+ @NonNull NetworkInfo ni) {
mHandler = new NetworkAgentHandler(looper);
LOG_TAG = logTag;
mNetworkInfo = new NetworkInfo(ni);
@@ -875,13 +886,22 @@ public abstract class NetworkAgent {
/**
* Must be called by the agent to update the score of this network.
*
+ * @param score the new score.
+ * @hide TODO : unhide when impl is complete
+ */
+ public final void sendNetworkScore(@NonNull NetworkScore score) {
+ Objects.requireNonNull(score);
+ queueOrSendMessage(reg -> reg.sendScore(score));
+ }
+
+ /**
+ * Must be called by the agent to update the score of this network.
+ *
* @param score the new score, between 0 and 99.
+ * deprecated use sendNetworkScore(NetworkScore) TODO : remove in S.
*/
public final void sendNetworkScore(@IntRange(from = 0, to = 99) int score) {
- if (score < 0) {
- throw new IllegalArgumentException("Score must be >= 0");
- }
- queueOrSendMessage(reg -> reg.sendScore(score));
+ sendNetworkScore(new NetworkScore.Builder().setLegacyInt(score).build());
}
/**
diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
index 3fd95ee58df2..dbe3ecc4d775 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
@@ -140,7 +140,7 @@ public class NetworkRequest implements Parcelable {
REQUEST,
BACKGROUND_REQUEST,
TRACK_SYSTEM_DEFAULT,
- TRACK_BEST,
+ LISTEN_FOR_BEST,
};
/**
@@ -514,6 +514,15 @@ public class NetworkRequest implements Parcelable {
}
/**
+ * Returns true iff. this NetworkRequest is of type LISTEN_FOR_BEST.
+ *
+ * @hide
+ */
+ public boolean isListenForBest() {
+ return type == Type.LISTEN_FOR_BEST;
+ }
+
+ /**
* Returns true iff. the contained NetworkRequest is one that:
*
* - should be associated with at most one satisfying network
diff --git a/packages/Connectivity/framework/src/android/net/ParseException.java b/packages/Connectivity/framework/src/android/net/ParseException.java
index bcfdd7ef09cc..ca6d012dfe7c 100644
--- a/packages/Connectivity/framework/src/android/net/ParseException.java
+++ b/packages/Connectivity/framework/src/android/net/ParseException.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
/**
* Thrown when parsing failed.
@@ -25,12 +26,16 @@ import android.annotation.NonNull;
public class ParseException extends RuntimeException {
public String response;
- ParseException(@NonNull String response) {
+ /** @hide */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public ParseException(@NonNull String response) {
super(response);
this.response = response;
}
- ParseException(@NonNull String response, @NonNull Throwable cause) {
+ /** @hide */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public ParseException(@NonNull String response, @NonNull Throwable cause) {
super(response, cause);
this.response = response;
}
diff --git a/packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl b/packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl
index f0193db5c2e2..18d26a7e4baf 100644
--- a/packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl
+++ b/packages/Connectivity/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl
@@ -19,11 +19,12 @@ import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
+import android.net.NetworkScore;
import android.net.QosSession;
import android.telephony.data.EpsBearerQosSessionAttributes;
/**
- * Interface for NetworkAgents to send network network properties.
+ * Interface for NetworkAgents to send network properties.
* @hide
*/
oneway interface INetworkAgentRegistry {
@@ -31,7 +32,7 @@ oneway interface INetworkAgentRegistry {
void sendLinkProperties(in LinkProperties lp);
// TODO: consider replacing this by "markConnected()" and removing
void sendNetworkInfo(in NetworkInfo info);
- void sendScore(int score);
+ void sendScore(in NetworkScore score);
void sendExplicitlySelected(boolean explicitlySelected, boolean acceptPartial);
void sendSocketKeepaliveEvent(int slot, int reason);
void sendUnderlyingNetworks(in @nullable List<Network> networks);
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 9c0c80bff3df..bf4242f542da 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -23,7 +23,6 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.location.LocationManager;
import android.media.AudioManager;
-import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.TetheringManager;
import android.net.vcn.VcnTransportInfo;
@@ -37,6 +36,7 @@ import android.provider.Settings;
import android.telephony.AccessNetworkConstants;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
import androidx.annotation.NonNull;
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
@@ -439,8 +439,7 @@ public class Utils {
}
public static boolean isWifiOnly(Context context) {
- return !context.getSystemService(ConnectivityManager.class)
- .isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
+ return !context.getSystemService(TelephonyManager.class).isDataCapable();
}
/** Returns if the automatic storage management feature is turned on or not. **/
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
index 092cbf3c7c12..60bcf37304a5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
@@ -16,7 +16,6 @@
package com.android.settingslib.net;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
import static android.net.TrafficStats.MB_IN_BYTES;
@@ -59,7 +58,6 @@ public class DataUsageController {
PERIOD_BUILDER, Locale.getDefault());
private final Context mContext;
- private final ConnectivityManager mConnectivityManager;
private final INetworkStatsService mStatsService;
private final NetworkPolicyManager mPolicyManager;
private final NetworkStatsManager mNetworkStatsManager;
@@ -71,7 +69,6 @@ public class DataUsageController {
public DataUsageController(Context context) {
mContext = context;
- mConnectivityManager = ConnectivityManager.from(context);
mStatsService = INetworkStatsService.Stub.asInterface(
ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
mPolicyManager = NetworkPolicyManager.from(mContext);
@@ -236,7 +233,7 @@ public class DataUsageController {
public boolean isMobileDataSupported() {
// require both supported network and ready SIM
- return mConnectivityManager.isNetworkSupported(TYPE_MOBILE)
+ return getTelephonyManager().isDataCapable()
&& getTelephonyManager().getSimState() == SIM_STATE_READY;
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 6568bffddecc..268603fa8b0d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -2445,8 +2445,8 @@ class DatabaseHelper extends SQLiteOpenHelper {
R.bool.def_auto_time_zone); // Sync timezone to NITZ
loadSetting(stmt, Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
- ("1".equals(SystemProperties.get("ro.kernel.qemu")) ||
- res.getBoolean(R.bool.def_stay_on_while_plugged_in))
+ ("1".equals(SystemProperties.get("ro.boot.qemu"))
+ || res.getBoolean(R.bool.def_stay_on_while_plugged_in))
? 1 : 0);
loadIntegerSetting(stmt, Settings.Global.WIFI_SLEEP_POLICY,
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 688b33e0f685..f666490d13aa 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -55,6 +55,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.uidRulesToString;
+import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST;
import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequired;
import static android.os.Process.INVALID_UID;
import static android.os.Process.VPN_UID;
@@ -117,6 +118,7 @@ import android.net.NetworkMonitorManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkProvider;
import android.net.NetworkRequest;
+import android.net.NetworkScore;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
import android.net.NetworkStackClient;
@@ -1273,12 +1275,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
mDnsManager = new DnsManager(mContext, mDnsResolver);
registerPrivateDnsSettingsCallbacks();
+ // This NAI is a sentinel used to offer no service to apps that are on a multi-layer
+ // request that doesn't allow fallback to the default network. It should never be visible
+ // to apps. As such, it's not in the list of NAIs and doesn't need many of the normal
+ // arguments like the handler or the DnsResolver.
+ // TODO : remove this ; it is probably better handled with a sentinel request.
mNoServiceNetwork = new NetworkAgentInfo(null,
new Network(NO_SERVICE_NET_ID),
new NetworkInfo(TYPE_NONE, 0, "", ""),
- new LinkProperties(), new NetworkCapabilities(), 0, mContext,
- null, new NetworkAgentConfig(), this, null,
- null, 0, INVALID_UID, mQosCallbackTracker, mDeps);
+ new LinkProperties(), new NetworkCapabilities(),
+ new NetworkScore.Builder().setLegacyInt(0).build(), mContext, null,
+ new NetworkAgentConfig(), this, null, null, 0, INVALID_UID, mQosCallbackTracker,
+ mDeps);
}
private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
@@ -2949,7 +2957,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
break;
}
case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
- updateNetworkScore(nai, msg.arg1);
+ updateNetworkScore(nai, (NetworkScore) arg.second);
break;
}
case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
@@ -3656,6 +3664,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mNetworkRequestInfoLogs.log("REGISTER " + nri);
for (final NetworkRequest req : nri.mRequests) {
mNetworkRequests.put(req, nri);
+ // TODO: Consider update signal strength for other types.
if (req.isListen()) {
for (final NetworkAgentInfo network : mNetworkAgentInfos) {
if (req.networkCapabilities.hasSignalStrength()
@@ -3748,18 +3757,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
// listen requests won't keep up a network satisfying it. If this is not a multilayer
// request, return immediately. For multilayer requests, check to see if any of the
// multilayer requests may have a potential satisfier.
- if (!nri.isMultilayerRequest() && nri.mRequests.get(0).isListen()) {
+ if (!nri.isMultilayerRequest() && (nri.mRequests.get(0).isListen()
+ || nri.mRequests.get(0).isListenForBest())) {
return false;
}
for (final NetworkRequest req : nri.mRequests) {
// This multilayer listen request is satisfied therefore no further requests need to be
// evaluated deeming this network not a potential satisfier.
- if (req.isListen() && nri.getActiveRequest() == req) {
+ if ((req.isListen() || req.isListenForBest()) && nri.getActiveRequest() == req) {
return false;
}
// As non-multilayer listen requests have already returned, the below would only happen
// for a multilayer request therefore continue to the next request if available.
- if (req.isListen()) {
+ if (req.isListen() || req.isListenForBest()) {
continue;
}
// If this Network is already the highest scoring Network for a request, or if
@@ -3799,8 +3809,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
? mNetworkRequests.get(request) : getNriForAppRequest(request);
if (nri != null) {
- if (Process.SYSTEM_UID != callingUid && Process.NETWORK_STACK_UID != callingUid
- && nri.mUid != callingUid) {
+ if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) {
log(String.format("UID %d attempted to %s for unowned request %s",
callingUid, requestedOperation, nri));
return null;
@@ -5543,8 +5552,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
// request if the app changes network state. http://b/29964605
enforceMeteredApnPolicy(networkCapabilities);
break;
- case TRACK_BEST:
- throw new UnsupportedOperationException("Not implemented yet");
+ case LISTEN_FOR_BEST:
+ enforceAccessPermission();
+ networkCapabilities = new NetworkCapabilities(networkCapabilities);
+ break;
default:
throw new IllegalArgumentException("Unsupported request type " + reqType);
}
@@ -5552,11 +5563,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
ensureSufficientPermissionsForRequest(networkCapabilities,
Binder.getCallingPid(), callingUid, callingPackageName);
- // Set the UID range for this request to the single UID of the requester, or to an empty
- // set of UIDs if the caller has the appropriate permission and UIDs have not been set.
+ // Enforce FOREGROUND if the caller does not have permission to use background network.
+ if (reqType == LISTEN_FOR_BEST) {
+ restrictBackgroundRequestForCaller(networkCapabilities);
+ }
+
+ // Set the UID range for this request to the single UID of the requester, unless the
+ // requester has the permission to specify other UIDs.
// This will overwrite any allowed UIDs in the requested capabilities. Though there
// are no visible methods to set the UIDs, an app could use reflection to try and get
// networks for other apps so it's essential that the UIDs are overwritten.
+ // Also set the requester UID and package name in the request.
restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities,
callingUid, callingPackageName);
@@ -6083,20 +6100,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
return nai == getDefaultNetwork();
}
- // TODO : remove this method. It's a stopgap measure to help sheperding a number of dependent
- // changes that would conflict throughout the automerger graph. Having this method temporarily
- // helps with the process of going through with all these dependent changes across the entire
- // tree.
- /**
- * Register a new agent. {@see #registerNetworkAgent} below.
- */
- public Network registerNetworkAgent(INetworkAgent na, NetworkInfo networkInfo,
- LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
- int currentScore, NetworkAgentConfig networkAgentConfig) {
- return registerNetworkAgent(na, networkInfo, linkProperties, networkCapabilities,
- currentScore, networkAgentConfig, NetworkProvider.ID_NONE);
- }
-
/**
* Register a new agent with ConnectivityService to handle a network.
*
@@ -6107,7 +6110,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
* later : see {@link #updateLinkProperties}.
* @param networkCapabilities the initial capabilites of this network. They can be updated
* later : see {@link #updateCapabilities}.
- * @param currentScore the initial score of the network. See
+ * @param initialScore the initial score of the network. See
* {@link NetworkAgentInfo#getCurrentScore}.
* @param networkAgentConfig metadata about the network. This is never updated.
* @param providerId the ID of the provider owning this NetworkAgent.
@@ -6115,10 +6118,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/
public Network registerNetworkAgent(INetworkAgent na, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
- int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) {
+ @NonNull NetworkScore initialScore, NetworkAgentConfig networkAgentConfig,
+ int providerId) {
Objects.requireNonNull(networkInfo, "networkInfo must not be null");
Objects.requireNonNull(linkProperties, "linkProperties must not be null");
Objects.requireNonNull(networkCapabilities, "networkCapabilities must not be null");
+ Objects.requireNonNull(initialScore, "initialScore must not be null");
Objects.requireNonNull(networkAgentConfig, "networkAgentConfig must not be null");
if (networkCapabilities.hasTransport(TRANSPORT_TEST)) {
enforceAnyPermissionOf(Manifest.permission.MANAGE_TEST_NETWORKS);
@@ -6130,7 +6135,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
final long token = Binder.clearCallingIdentity();
try {
return registerNetworkAgentInternal(na, networkInfo, linkProperties,
- networkCapabilities, currentScore, networkAgentConfig, providerId, uid);
+ networkCapabilities, initialScore, networkAgentConfig, providerId, uid);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -6138,7 +6143,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
private Network registerNetworkAgentInternal(INetworkAgent na, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
- int currentScore, NetworkAgentConfig networkAgentConfig, int providerId, int uid) {
+ NetworkScore currentScore, NetworkAgentConfig networkAgentConfig, int providerId,
+ int uid) {
if (networkCapabilities.hasTransport(TRANSPORT_TEST)) {
// Strictly, sanitizing here is unnecessary as the capabilities will be sanitized in
// the call to mixInCapabilities below anyway, but sanitizing here means the NAI never
@@ -7862,7 +7868,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
- private void updateNetworkScore(@NonNull final NetworkAgentInfo nai, final int score) {
+ private void updateNetworkScore(@NonNull final NetworkAgentInfo nai, final NetworkScore score) {
if (VDBG || DDBG) log("updateNetworkScore for " + nai.toShortString() + " to " + score);
nai.setScore(score);
rematchAllNetworksAndRequests();
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index e2086b01ec13..e74c936af02d 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -589,9 +589,9 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
Slog.w(TAG, "exception reading modem stats: " + e.getCause());
}
- final MeasuredEnergySnapshot.MeasuredEnergyDeltaData measuredEnergyDelta;
+ final MeasuredEnergySnapshot.MeasuredEnergyDeltaData measuredEnergyDeltas;
if (mMeasuredEnergySnapshot == null || futureECRs == null) {
- measuredEnergyDelta = null;
+ measuredEnergyDeltas = null;
} else {
final int voltageMv;
synchronized (mStats) {
@@ -610,7 +610,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
ecrs = null;
}
- measuredEnergyDelta = mMeasuredEnergySnapshot.updateAndGetDelta(ecrs, voltageMv);
+ measuredEnergyDeltas = mMeasuredEnergySnapshot.updateAndGetDelta(ecrs, voltageMv);
}
final long elapsedRealtime = SystemClock.elapsedRealtime();
@@ -633,10 +633,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
}
final long[] cpuClusterChargeUC;
- if (measuredEnergyDelta == null) {
+ if (measuredEnergyDeltas == null) {
cpuClusterChargeUC = null;
} else {
- cpuClusterChargeUC = measuredEnergyDelta.cpuClusterChargeUC;
+ cpuClusterChargeUC = measuredEnergyDeltas.cpuClusterChargeUC;
}
mStats.updateCpuTimeLocked(onBattery, onBatteryScreenOff, cpuClusterChargeUC);
}
@@ -650,9 +650,9 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
mStats.updateRpmStatsLocked(elapsedRealtimeUs);
}
- // Inform mStats about each applicable measured energy.
- if (measuredEnergyDelta != null) {
- final long displayChargeUC = measuredEnergyDelta.displayChargeUC;
+ // Inform mStats about each applicable measured energy (unless addressed elsewhere).
+ if (measuredEnergyDeltas != null) {
+ final long displayChargeUC = measuredEnergyDeltas.displayChargeUC;
if (displayChargeUC != MeasuredEnergySnapshot.UNAVAILABLE) {
// If updating, pass in what BatteryExternalStatsWorker thinks screenState is.
mStats.updateDisplayMeasuredEnergyStatsLocked(displayChargeUC, screenState,
@@ -660,19 +660,23 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
}
}
// Inform mStats about each applicable custom energy bucket.
- if (measuredEnergyDelta != null
- && measuredEnergyDelta.otherTotalChargeUC != null) {
+ if (measuredEnergyDeltas != null
+ && measuredEnergyDeltas.otherTotalChargeUC != null) {
// Iterate over the custom (EnergyConsumerType.OTHER) ordinals.
- for (int ord = 0; ord < measuredEnergyDelta.otherTotalChargeUC.length; ord++) {
- long totalEnergy = measuredEnergyDelta.otherTotalChargeUC[ord];
- SparseLongArray uidEnergies = measuredEnergyDelta.otherUidChargesUC[ord];
+ for (int ord = 0; ord < measuredEnergyDeltas.otherTotalChargeUC.length; ord++) {
+ long totalEnergy = measuredEnergyDeltas.otherTotalChargeUC[ord];
+ SparseLongArray uidEnergies = measuredEnergyDeltas.otherUidChargesUC[ord];
mStats.updateCustomMeasuredEnergyStatsLocked(ord, totalEnergy, uidEnergies);
}
}
if (bluetoothInfo != null) {
if (bluetoothInfo.isValid()) {
- mStats.updateBluetoothStateLocked(bluetoothInfo, elapsedRealtime, uptime);
+ final long btChargeUC = measuredEnergyDeltas != null
+ ? measuredEnergyDeltas.bluetoothChargeUC
+ : MeasuredEnergySnapshot.UNAVAILABLE;
+ mStats.updateBluetoothStateLocked(bluetoothInfo,
+ btChargeUC, elapsedRealtime, uptime);
} else {
Slog.w(TAG, "bluetooth info is invalid: " + bluetoothInfo);
}
@@ -684,10 +688,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
if (wifiInfo != null) {
if (wifiInfo.isValid()) {
- // TODO: wifiEnergyDelta = measuredEnergyDelta.consumerTypeEnergyUJ
- // .get(EnergyConsumerType.WIFI, MeasuredEnergySnapshot.UNAVAILABLE)
- mStats.updateWifiState(extractDeltaLocked(wifiInfo)
- /*, TODO: wifiEnergyDelta */, elapsedRealtime, uptime);
+ final long wifiChargeUC = measuredEnergyDeltas != null ?
+ measuredEnergyDeltas.wifiChargeUC : MeasuredEnergySnapshot.UNAVAILABLE;
+ mStats.updateWifiState(
+ extractDeltaLocked(wifiInfo), wifiChargeUC, elapsedRealtime, uptime);
} else {
Slog.w(TAG, "wifi info is invalid: " + wifiInfo);
}
@@ -820,13 +824,19 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
for (int idx = 0; idx < size; idx++) {
final EnergyConsumer consumer = idToConsumer.valueAt(idx);
switch (consumer.type) {
+ case EnergyConsumerType.BLUETOOTH:
+ buckets[MeasuredEnergyStats.POWER_BUCKET_BLUETOOTH] = true;
+ break;
+ case EnergyConsumerType.CPU_CLUSTER:
+ buckets[MeasuredEnergyStats.POWER_BUCKET_CPU] = true;
+ break;
case EnergyConsumerType.DISPLAY:
buckets[MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON] = true;
buckets[MeasuredEnergyStats.POWER_BUCKET_SCREEN_DOZE] = true;
buckets[MeasuredEnergyStats.POWER_BUCKET_SCREEN_OTHER] = true;
break;
- case EnergyConsumerType.CPU_CLUSTER:
- buckets[MeasuredEnergyStats.POWER_BUCKET_CPU] = true;
+ case EnergyConsumerType.WIFI:
+ buckets[MeasuredEnergyStats.POWER_BUCKET_WIFI] = true;
break;
}
}
@@ -864,13 +874,18 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
}
final IntArray energyConsumerIds = new IntArray();
+ if ((flags & UPDATE_BT) != 0) {
+ addEnergyConsumerIdLocked(energyConsumerIds, EnergyConsumerType.BLUETOOTH);
+ }
if ((flags & UPDATE_CPU) != 0) {
addEnergyConsumerIdLocked(energyConsumerIds, EnergyConsumerType.CPU_CLUSTER);
}
if ((flags & UPDATE_DISPLAY) != 0) {
addEnergyConsumerIdLocked(energyConsumerIds, EnergyConsumerType.DISPLAY);
}
- // TODO: Wifi, Bluetooth, etc., go here
+ if ((flags & UPDATE_WIFI) != 0) {
+ addEnergyConsumerIdLocked(energyConsumerIds, EnergyConsumerType.WIFI);
+ }
if (energyConsumerIds.size() == 0) {
return null;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 6b9fc0718879..c3f97adbd9c3 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
+import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
import android.annotation.NonNull;
import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -1927,7 +1928,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
- mStats.updateWifiState(info, elapsedRealtime, uptime);
+ mStats.updateWifiState(info, POWER_DATA_UNAVAILABLE, elapsedRealtime, uptime);
});
}
}
@@ -1945,7 +1946,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub
final long uptime = SystemClock.uptimeMillis();
mHandler.post(() -> {
synchronized (mStats) {
- mStats.updateBluetoothStateLocked(info, elapsedRealtime, uptime);
+ mStats.updateBluetoothStateLocked(
+ info, POWER_DATA_UNAVAILABLE, elapsedRealtime, uptime);
}
});
}
diff --git a/services/core/java/com/android/server/am/MeasuredEnergySnapshot.java b/services/core/java/com/android/server/am/MeasuredEnergySnapshot.java
index 9b2ca136bdfb..4c9ab63a100b 100644
--- a/services/core/java/com/android/server/am/MeasuredEnergySnapshot.java
+++ b/services/core/java/com/android/server/am/MeasuredEnergySnapshot.java
@@ -41,7 +41,7 @@ public class MeasuredEnergySnapshot {
private static final int MILLIVOLTS_PER_VOLT = 1000;
- public static final long UNAVAILABLE = -1L;
+ public static final long UNAVAILABLE = android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
/** Map of {@link EnergyConsumer#id} to its corresponding {@link EnergyConsumer}. */
private final SparseArray<EnergyConsumer> mEnergyConsumers;
@@ -109,12 +109,18 @@ public class MeasuredEnergySnapshot {
/** Class for returning the relevant data calculated from the measured energy delta */
static class MeasuredEnergyDeltaData {
- /** The chargeUC for {@link EnergyConsumerType#DISPLAY}. */
- public long displayChargeUC = UNAVAILABLE;
+ /** The chargeUC for {@link EnergyConsumerType#BLUETOOTH}. */
+ public long bluetoothChargeUC = UNAVAILABLE;
/** The chargeUC for {@link EnergyConsumerType#CPU_CLUSTER}s. */
public long[] cpuClusterChargeUC = null;
+ /** The chargeUC for {@link EnergyConsumerType#DISPLAY}. */
+ public long displayChargeUC = UNAVAILABLE;
+
+ /** The chargeUC for {@link EnergyConsumerType#WIFI}. */
+ public long wifiChargeUC = UNAVAILABLE;
+
/** Map of {@link EnergyConsumerType#OTHER} ordinals to their total chargeUC. */
public @Nullable long[] otherTotalChargeUC = null;
@@ -196,8 +202,8 @@ public class MeasuredEnergySnapshot {
final long deltaChargeUC = calculateChargeConsumedUC(deltaUJ, avgVoltageMV);
switch (type) {
- case EnergyConsumerType.DISPLAY:
- output.displayChargeUC = deltaChargeUC;
+ case EnergyConsumerType.BLUETOOTH:
+ output.bluetoothChargeUC = deltaChargeUC;
break;
case EnergyConsumerType.CPU_CLUSTER:
@@ -207,6 +213,14 @@ public class MeasuredEnergySnapshot {
output.cpuClusterChargeUC[ordinal] = deltaChargeUC;
break;
+ case EnergyConsumerType.DISPLAY:
+ output.displayChargeUC = deltaChargeUC;
+ break;
+
+ case EnergyConsumerType.WIFI:
+ output.wifiChargeUC = deltaChargeUC;
+ break;
+
case EnergyConsumerType.OTHER:
if (output.otherTotalChargeUC == null) {
output.otherTotalChargeUC = new long[getNumOtherOrdinals()];
@@ -215,6 +229,7 @@ public class MeasuredEnergySnapshot {
output.otherTotalChargeUC[ordinal] = deltaChargeUC;
output.otherUidChargesUC[ordinal] = otherUidCharges;
break;
+
default:
Slog.w(TAG, "Ignoring consumer " + consumer.name + " of unknown type " + type);
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 5bf15dc70ff9..71565301e3ed 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -80,6 +80,7 @@ import com.android.server.wm.WindowManagerInternal;
import java.io.IOException;
import java.io.RandomAccessFile;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -95,21 +96,20 @@ class HostClipboardMonitor implements Runnable {
private static final String PIPE_NAME = "pipe:clipboard";
private static final String PIPE_DEVICE = "/dev/qemu_pipe";
+ private static byte[] createOpenHandshake() {
+ // String.getBytes doesn't include the null terminator,
+ // but the QEMU pipe device requires the pipe service name
+ // to be null-terminated.
+
+ final byte[] bits = Arrays.copyOf(PIPE_NAME.getBytes(), PIPE_NAME.length() + 1);
+ bits[PIPE_NAME.length()] = 0;
+ return bits;
+ }
+
private void openPipe() {
try {
- // String.getBytes doesn't include the null terminator,
- // but the QEMU pipe device requires the pipe service name
- // to be null-terminated.
- byte[] b = new byte[PIPE_NAME.length() + 1];
- b[PIPE_NAME.length()] = 0;
- System.arraycopy(
- PIPE_NAME.getBytes(),
- 0,
- b,
- 0,
- PIPE_NAME.length());
mPipe = new RandomAccessFile(PIPE_DEVICE, "rw");
- mPipe.write(b);
+ mPipe.write(createOpenHandshake());
} catch (IOException e) {
try {
if (mPipe != null) mPipe.close();
@@ -173,7 +173,7 @@ public class ClipboardService extends SystemService {
private static final String TAG = "ClipboardService";
private static final boolean IS_EMULATOR =
- SystemProperties.getBoolean("ro.kernel.qemu", false);
+ SystemProperties.getBoolean("ro.boot.qemu", false);
// DeviceConfig properties
private static final String PROPERTY_SHOW_ACCESS_NOTIFICATIONS = "show_access_notifications";
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 803cc9d31c35..e44dcf5975f1 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -35,6 +35,7 @@ import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkMonitorManager;
import android.net.NetworkRequest;
+import android.net.NetworkScore;
import android.net.NetworkStateSnapshot;
import android.net.QosCallbackException;
import android.net.QosFilter;
@@ -302,8 +303,8 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
// validated).
private boolean mInactive;
- // This represents the quality of the network with no clear scale.
- private int mScore;
+ // This represents the quality of the network.
+ private NetworkScore mScore;
// The list of NetworkRequests being satisfied by this Network.
private final SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
@@ -338,7 +339,8 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
private final QosCallbackTracker mQosCallbackTracker;
public NetworkAgentInfo(INetworkAgent na, Network net, NetworkInfo info,
- @NonNull LinkProperties lp, @NonNull NetworkCapabilities nc, int score, Context context,
+ @NonNull LinkProperties lp, @NonNull NetworkCapabilities nc,
+ @NonNull NetworkScore score, Context context,
Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd,
IDnsResolver dnsResolver, int factorySerialNumber, int creatorUid,
QosCallbackTracker qosCallbackTracker, ConnectivityService.Dependencies deps) {
@@ -603,9 +605,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
}
@Override
- public void sendScore(int score) {
- mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_SCORE_CHANGED, score, 0,
- new Pair<>(NetworkAgentInfo.this, null)).sendToTarget();
+ public void sendScore(@NonNull final NetworkScore score) {
+ mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_SCORE_CHANGED,
+ new Pair<>(NetworkAgentInfo.this, score)).sendToTarget();
}
@Override
@@ -717,6 +719,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
break;
case LISTEN:
+ case LISTEN_FOR_BEST:
case TRACK_DEFAULT:
case TRACK_SYSTEM_DEFAULT:
break;
@@ -857,7 +860,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE;
}
- int score = mScore;
+ int score = mScore.getLegacyInt();
if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) {
score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY;
}
@@ -886,7 +889,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
return getCurrentScore(true);
}
- public void setScore(final int score) {
+ public void setScore(final NetworkScore score) {
mScore = score;
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d5a9e3c0d4f8..e58836659189 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -10635,17 +10635,17 @@ public class NotificationManagerService extends SystemService {
return true;
}
}
- String toastMessage = "Indirect activity start from " + packageName;
String logcatMessage =
"Indirect notification activity start (trampoline) from " + packageName;
-
+ // Call to toast() method is posted to mHandler below to offload PM lookup from the
+ // activity start path
if (CompatChanges.isChangeEnabled(NOTIFICATION_TRAMPOLINE_BLOCK, uid)) {
- toast(toastMessage + " blocked.");
+ mHandler.post(() -> toast(packageName, uid, /* blocked */ true));
Slog.e(TAG, logcatMessage + " blocked");
return false;
} else {
if (mPackagesShown.add(packageName)) {
- toast(toastMessage + ". This will be blocked in S.");
+ mHandler.post(() -> toast(packageName, uid, /* blocked */ false));
}
Slog.w(TAG, logcatMessage + ", this should be avoided for performance reasons");
return true;
@@ -10661,10 +10661,19 @@ public class NotificationManagerService extends SystemService {
&& !CompatChanges.isChangeEnabled(NOTIFICATION_TRAMPOLINE_BLOCK, uid);
}
- private void toast(String message) {
- mUiHandler.post(() ->
- Toast.makeText(getUiContext(), message + "\nSee g.co/dev/trampolines.",
- Toast.LENGTH_LONG).show());
+ private void toast(String packageName, int uid, boolean blocked) {
+ final CharSequence label;
+ try {
+ label = mPackageManagerClient.getApplicationLabel(
+ mPackageManager.getApplicationInfo(packageName, 0,
+ UserHandle.getUserId(uid)));
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unexpected exception obtaining app label from PackageManager", e);
+ return;
+ }
+ mUiHandler.post(() -> Toast.makeText(getUiContext(),
+ label + " launch " + (blocked ? "blocked" : "will be blocked")
+ + "\ng.co/dev/trampolines", Toast.LENGTH_LONG).show());
}
}
}
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index a73f6c6d8c2d..6cb4a63a5636 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -123,16 +123,9 @@ static void android_server_SystemServer_initZygoteChildHeapProfiling(JNIEnv* /*
}
static void android_server_SystemServer_fdtrackAbort(JNIEnv*, jobject) {
- raise(BIONIC_SIGNAL_FDTRACK);
-
- // Wait for a bit to allow fdtrack to dump backtraces to logcat.
- std::this_thread::sleep_for(5s);
-
- // Abort on a different thread to avoid ART dumping runtime stacks.
- std::thread([]() {
- LOG_ALWAYS_FATAL("b/140703823: aborting due to fd leak: check logs for fd "
- "backtraces");
- }).join();
+ sigval val;
+ val.sival_int = 1;
+ sigqueue(getpid(), BIONIC_SIGNAL_FDTRACK, val);
}
static jlong android_server_SystemServer_startIncrementalService(JNIEnv* env, jclass klass,
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 4e23609bd774..592952354b8f 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1327,7 +1327,7 @@ public final class SystemServer implements Dumpable {
false);
boolean enableLeftyService = SystemProperties.getBoolean("config.enable_lefty", false);
- boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1");
+ boolean isEmulator = SystemProperties.get("ro.boot.qemu").equals("1");
boolean isWatch = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_WATCH);
diff --git a/services/tests/servicestests/src/com/android/server/am/BatteryExternalStatsWorkerTest.java b/services/tests/servicestests/src/com/android/server/am/BatteryExternalStatsWorkerTest.java
index 8d54ead75761..73a2febf72aa 100644
--- a/services/tests/servicestests/src/com/android/server/am/BatteryExternalStatsWorkerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/BatteryExternalStatsWorkerTest.java
@@ -17,8 +17,10 @@
package com.android.server.am;
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL;
+import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_BT;
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU;
import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_DISPLAY;
+import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -39,6 +41,7 @@ import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
import com.android.internal.os.BatteryStatsImpl;
+import com.android.internal.os.PowerProfile;
import org.junit.Before;
import org.junit.Test;
@@ -61,7 +64,7 @@ public class BatteryExternalStatsWorkerTest {
public void setUp() {
final Context context = InstrumentationRegistry.getContext();
- mBatteryStatsImpl = new TestBatteryStatsImpl();
+ mBatteryStatsImpl = new TestBatteryStatsImpl(context);
mPowerStatsInternal = new TestPowerStatsInternal();
mBatteryExternalStatsWorker = new BatteryExternalStatsWorker(new TestInjector(context),
mBatteryStatsImpl);
@@ -72,13 +75,24 @@ public class BatteryExternalStatsWorkerTest {
final int numCpuClusters = 4;
final int numOther = 3;
- final IntArray tempAllIds = new IntArray();
// Add some energy consumers used by BatteryExternalStatsWorker.
+ final IntArray tempAllIds = new IntArray();
+
final int displayId = mPowerStatsInternal.addEnergyConsumer(EnergyConsumerType.DISPLAY, 0,
"display");
tempAllIds.add(displayId);
mPowerStatsInternal.incrementEnergyConsumption(displayId, 12345);
+ final int wifiId = mPowerStatsInternal.addEnergyConsumer(EnergyConsumerType.WIFI, 0,
+ "wifi");
+ tempAllIds.add(wifiId);
+ mPowerStatsInternal.incrementEnergyConsumption(wifiId, 23456);
+
+ final int btId = mPowerStatsInternal.addEnergyConsumer(EnergyConsumerType.BLUETOOTH, 0,
+ "bt");
+ tempAllIds.add(btId);
+ mPowerStatsInternal.incrementEnergyConsumption(btId, 34567);
+
final int[] cpuClusterIds = new int[numCpuClusters];
for (int i = 0; i < numCpuClusters; i++) {
cpuClusterIds[i] = mPowerStatsInternal.addEnergyConsumer(
@@ -109,6 +123,18 @@ public class BatteryExternalStatsWorkerTest {
assertEquals(1, displayResults.length);
assertEquals(displayId, displayResults[0].id);
+ final EnergyConsumerResult[] wifiResults =
+ mBatteryExternalStatsWorker.getMeasuredEnergyLocked(UPDATE_WIFI).getNow(null);
+ // Results should only have the wifi energy consumer
+ assertEquals(1, wifiResults.length);
+ assertEquals(wifiId, wifiResults[0].id);
+
+ final EnergyConsumerResult[] bluetoothResults =
+ mBatteryExternalStatsWorker.getMeasuredEnergyLocked(UPDATE_BT).getNow(null);
+ // Results should only have the bluetooth energy consumer
+ assertEquals(1, bluetoothResults.length);
+ assertEquals(btId, bluetoothResults[0].id);
+
final EnergyConsumerResult[] cpuResults =
mBatteryExternalStatsWorker.getMeasuredEnergyLocked(UPDATE_CPU).getNow(null);
// Results should only have the cpu cluster energy consumers
@@ -148,6 +174,9 @@ public class BatteryExternalStatsWorkerTest {
}
public class TestBatteryStatsImpl extends BatteryStatsImpl {
+ public TestBatteryStatsImpl(Context context) {
+ mPowerProfile = new PowerProfile(context, true /* forTest */);
+ }
}
public class TestPowerStatsInternal extends PowerStatsInternal {
diff --git a/telecomm/java/android/telecom/CallDiagnosticService.java b/telecomm/java/android/telecom/CallDiagnosticService.java
index 5fb6b3381360..f5357b19c4de 100644
--- a/telecomm/java/android/telecom/CallDiagnosticService.java
+++ b/telecomm/java/android/telecom/CallDiagnosticService.java
@@ -27,8 +27,6 @@ import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.RemoteException;
-import android.telephony.Annotation;
-import android.telephony.ims.ImsReasonInfo;
import android.util.ArrayMap;
import com.android.internal.telecom.ICallDiagnosticService;
@@ -59,7 +57,7 @@ import java.util.concurrent.Executor;
* </pre>
* <p>
* <h2>Threading Model</h2>
- * By default, all incoming IPC from Telecom in this service and in the {@link DiagnosticCall}
+ * By default, all incoming IPC from Telecom in this service and in the {@link CallDiagnostics}
* instances will take place on the main thread. You can override {@link #getExecutor()} in your
* implementation to provide your own {@link Executor}.
* @hide
@@ -116,26 +114,28 @@ public abstract class CallDiagnosticService extends Service {
}
/**
- * Listens to events raised by a {@link DiagnosticCall}.
+ * Listens to events raised by a {@link CallDiagnostics}.
*/
- private android.telecom.DiagnosticCall.Listener mDiagnosticCallListener =
- new android.telecom.DiagnosticCall.Listener() {
+ private CallDiagnostics.Listener mDiagnosticCallListener =
+ new CallDiagnostics.Listener() {
@Override
- public void onSendDeviceToDeviceMessage(DiagnosticCall diagnosticCall,
- @DiagnosticCall.MessageType int message, int value) {
- handleSendDeviceToDeviceMessage(diagnosticCall, message, value);
+ public void onSendDeviceToDeviceMessage(CallDiagnostics callDiagnostics,
+ @CallDiagnostics.MessageType int message, int value) {
+ handleSendDeviceToDeviceMessage(callDiagnostics, message, value);
}
@Override
- public void onDisplayDiagnosticMessage(DiagnosticCall diagnosticCall, int messageId,
+ public void onDisplayDiagnosticMessage(CallDiagnostics callDiagnostics,
+ int messageId,
CharSequence message) {
- handleDisplayDiagnosticMessage(diagnosticCall, messageId, message);
+ handleDisplayDiagnosticMessage(callDiagnostics, messageId, message);
}
@Override
- public void onClearDiagnosticMessage(DiagnosticCall diagnosticCall, int messageId) {
- handleClearDiagnosticMessage(diagnosticCall, messageId);
+ public void onClearDiagnosticMessage(CallDiagnostics callDiagnostics,
+ int messageId) {
+ handleClearDiagnosticMessage(callDiagnostics, messageId);
}
};
@@ -149,7 +149,7 @@ public abstract class CallDiagnosticService extends Service {
* Map which tracks the Telecom calls received from the Telecom stack.
*/
private final Map<String, Call.Details> mCallByTelecomCallId = new ArrayMap<>();
- private final Map<String, DiagnosticCall> mDiagnosticCallByTelecomCallId = new ArrayMap<>();
+ private final Map<String, CallDiagnostics> mDiagnosticCallByTelecomCallId = new ArrayMap<>();
private final Object mLock = new Object();
private ICallDiagnosticServiceAdapter mAdapter;
@@ -177,7 +177,7 @@ public abstract class CallDiagnosticService extends Service {
* executor you want to use for incoming IPC.
*
* @return the {@link Executor} to use for incoming IPC from Telecom to
- * {@link CallDiagnosticService} and {@link DiagnosticCall}.
+ * {@link CallDiagnosticService} and {@link CallDiagnostics}.
*/
@SuppressLint("OnNameExpected")
@NonNull public Executor getExecutor() {
@@ -188,30 +188,30 @@ public abstract class CallDiagnosticService extends Service {
* Telecom calls this method on the {@link CallDiagnosticService} with details about a new call
* which was added to Telecom.
* <p>
- * The {@link CallDiagnosticService} returns an implementation of {@link DiagnosticCall} to be
+ * The {@link CallDiagnosticService} returns an implementation of {@link CallDiagnostics} to be
* used for the lifespan of this call.
* <p>
* Calls to this method will use the {@link CallDiagnosticService}'s {@link Executor}; see
* {@link CallDiagnosticService#getExecutor()} for more information.
*
* @param call The details of the new call.
- * @return An instance of {@link DiagnosticCall} which the {@link CallDiagnosticService}
+ * @return An instance of {@link CallDiagnostics} which the {@link CallDiagnosticService}
* provides to be used for the lifespan of the call.
- * @throws IllegalArgumentException if a {@code null} {@link DiagnosticCall} is returned.
+ * @throws IllegalArgumentException if a {@code null} {@link CallDiagnostics} is returned.
*/
- public abstract @NonNull DiagnosticCall onInitializeDiagnosticCall(@NonNull
+ public abstract @NonNull CallDiagnostics onInitializeCallDiagnostics(@NonNull
android.telecom.Call.Details call);
/**
- * Telecom calls this method when a previous created {@link DiagnosticCall} is no longer needed.
- * This happens when Telecom is no longer tracking the call in question.
+ * Telecom calls this method when a previous created {@link CallDiagnostics} is no longer
+ * needed. This happens when Telecom is no longer tracking the call in question.
* <p>
* Calls to this method will use the {@link CallDiagnosticService}'s {@link Executor}; see
* {@link CallDiagnosticService#getExecutor()} for more information.
*
* @param call The diagnostic call which is no longer tracked by Telecom.
*/
- public abstract void onRemoveDiagnosticCall(@NonNull DiagnosticCall call);
+ public abstract void onRemoveCallDiagnostics(@NonNull CallDiagnostics call);
/**
* Telecom calls this method when the audio routing or available audio route information
@@ -260,35 +260,35 @@ public abstract class CallDiagnosticService extends Service {
}
getExecutor().execute(() -> {
- DiagnosticCall diagnosticCall = onInitializeDiagnosticCall(newCallDetails);
- if (diagnosticCall == null) {
+ CallDiagnostics callDiagnostics = onInitializeCallDiagnostics(newCallDetails);
+ if (callDiagnostics == null) {
throw new IllegalArgumentException(
"A valid DiagnosticCall instance was not provided.");
}
synchronized (mLock) {
- diagnosticCall.setListener(mDiagnosticCallListener);
- diagnosticCall.setCallId(telecomCallId);
- mDiagnosticCallByTelecomCallId.put(telecomCallId, diagnosticCall);
+ callDiagnostics.setListener(mDiagnosticCallListener);
+ callDiagnostics.setCallId(telecomCallId);
+ mDiagnosticCallByTelecomCallId.put(telecomCallId, callDiagnostics);
}
});
}
/**
* Handles an update to {@link Call.Details} notified by Telecom.
- * Caches the call details and notifies the {@link DiagnosticCall} of the change via
- * {@link DiagnosticCall#onCallDetailsChanged(Call.Details)}.
+ * Caches the call details and notifies the {@link CallDiagnostics} of the change via
+ * {@link CallDiagnostics#onCallDetailsChanged(Call.Details)}.
* @param parcelableCall the new parceled call details from Telecom.
*/
private void handleCallUpdated(@NonNull ParcelableCall parcelableCall) {
String telecomCallId = parcelableCall.getId();
Log.i(this, "handleCallUpdated: callId=%s - updated", telecomCallId);
Call.Details newCallDetails = Call.Details.createFromParcelableCall(parcelableCall);
- DiagnosticCall diagnosticCall;
+ CallDiagnostics callDiagnostics;
synchronized (mLock) {
- diagnosticCall = mDiagnosticCallByTelecomCallId.get(telecomCallId);
+ callDiagnostics = mDiagnosticCallByTelecomCallId.get(telecomCallId);
mCallByTelecomCallId.put(telecomCallId, newCallDetails);
}
- getExecutor().execute(() -> diagnosticCall.handleCallUpdated(newCallDetails));
+ getExecutor().execute(() -> callDiagnostics.handleCallUpdated(newCallDetails));
}
/**
@@ -302,37 +302,37 @@ public abstract class CallDiagnosticService extends Service {
mCallByTelecomCallId.remove(telecomCallId);
}
- DiagnosticCall diagnosticCall;
+ CallDiagnostics callDiagnostics;
synchronized (mLock) {
if (mDiagnosticCallByTelecomCallId.containsKey(telecomCallId)) {
- diagnosticCall = mDiagnosticCallByTelecomCallId.remove(telecomCallId);
+ callDiagnostics = mDiagnosticCallByTelecomCallId.remove(telecomCallId);
} else {
- diagnosticCall = null;
+ callDiagnostics = null;
}
}
// Inform the service of the removed call.
- if (diagnosticCall != null) {
- getExecutor().execute(() -> onRemoveDiagnosticCall(diagnosticCall));
+ if (callDiagnostics != null) {
+ getExecutor().execute(() -> onRemoveCallDiagnostics(callDiagnostics));
}
}
/**
* Handles an incoming device to device message received from Telecom. Notifies the
- * {@link DiagnosticCall} via {@link DiagnosticCall#onReceiveDeviceToDeviceMessage(int, int)}.
+ * {@link CallDiagnostics} via {@link CallDiagnostics#onReceiveDeviceToDeviceMessage(int, int)}.
* @param callId
* @param message
* @param value
*/
private void handleReceivedD2DMessage(@NonNull String callId, int message, int value) {
Log.i(this, "handleReceivedD2DMessage: callId=%s, msg=%d/%d", callId, message, value);
- DiagnosticCall diagnosticCall;
+ CallDiagnostics callDiagnostics;
synchronized (mLock) {
- diagnosticCall = mDiagnosticCallByTelecomCallId.get(callId);
+ callDiagnostics = mDiagnosticCallByTelecomCallId.get(callId);
}
- if (diagnosticCall != null) {
+ if (callDiagnostics != null) {
getExecutor().execute(
- () -> diagnosticCall.onReceiveDeviceToDeviceMessage(message, value));
+ () -> callDiagnostics.onReceiveDeviceToDeviceMessage(message, value));
}
}
@@ -345,12 +345,12 @@ public abstract class CallDiagnosticService extends Service {
private void handleCallDisconnected(@NonNull String callId,
@NonNull DisconnectCause disconnectCause) {
Log.i(this, "handleCallDisconnected: call=%s; cause=%s", callId, disconnectCause);
- DiagnosticCall diagnosticCall = mDiagnosticCallByTelecomCallId.get(callId);
+ CallDiagnostics callDiagnostics = mDiagnosticCallByTelecomCallId.get(callId);
CharSequence message;
if (disconnectCause.getImsReasonInfo() != null) {
- message = diagnosticCall.onCallDisconnected(disconnectCause.getImsReasonInfo());
+ message = callDiagnostics.onCallDisconnected(disconnectCause.getImsReasonInfo());
} else {
- message = diagnosticCall.onCallDisconnected(
+ message = callDiagnostics.onCallDisconnected(
disconnectCause.getTelephonyDisconnectCause(),
disconnectCause.getTelephonyPreciseDisconnectCause());
}
@@ -375,15 +375,15 @@ public abstract class CallDiagnosticService extends Service {
}
/**
- * Handles a request from a {@link DiagnosticCall} to send a device to device message (received
- * via {@link DiagnosticCall#sendDeviceToDeviceMessage(int, int)}.
- * @param diagnosticCall
+ * Handles a request from a {@link CallDiagnostics} to send a device to device message (received
+ * via {@link CallDiagnostics#sendDeviceToDeviceMessage(int, int)}.
+ * @param callDiagnostics
* @param message
* @param value
*/
- private void handleSendDeviceToDeviceMessage(@NonNull DiagnosticCall diagnosticCall,
+ private void handleSendDeviceToDeviceMessage(@NonNull CallDiagnostics callDiagnostics,
int message, int value) {
- String callId = diagnosticCall.getCallId();
+ String callId = callDiagnostics.getCallId();
try {
mAdapter.sendDeviceToDeviceMessage(callId, message, value);
Log.i(this, "handleSendDeviceToDeviceMessage: call=%s; msg=%d/%d", callId, message,
@@ -395,15 +395,15 @@ public abstract class CallDiagnosticService extends Service {
}
/**
- * Handles a request from a {@link DiagnosticCall} to display an in-call diagnostic message.
- * Originates from {@link DiagnosticCall#displayDiagnosticMessage(int, CharSequence)}.
- * @param diagnosticCall
+ * Handles a request from a {@link CallDiagnostics} to display an in-call diagnostic message.
+ * Originates from {@link CallDiagnostics#displayDiagnosticMessage(int, CharSequence)}.
+ * @param callDiagnostics
* @param messageId
* @param message
*/
- private void handleDisplayDiagnosticMessage(DiagnosticCall diagnosticCall, int messageId,
+ private void handleDisplayDiagnosticMessage(CallDiagnostics callDiagnostics, int messageId,
CharSequence message) {
- String callId = diagnosticCall.getCallId();
+ String callId = callDiagnostics.getCallId();
try {
mAdapter.displayDiagnosticMessage(callId, messageId, message);
Log.i(this, "handleDisplayDiagnosticMessage: call=%s; msg=%d/%s", callId, messageId,
@@ -415,14 +415,14 @@ public abstract class CallDiagnosticService extends Service {
}
/**
- * Handles a request from a {@link DiagnosticCall} to clear a previously shown diagnostic
+ * Handles a request from a {@link CallDiagnostics} to clear a previously shown diagnostic
* message.
- * Originates from {@link DiagnosticCall#clearDiagnosticMessage(int)}.
- * @param diagnosticCall
+ * Originates from {@link CallDiagnostics#clearDiagnosticMessage(int)}.
+ * @param callDiagnostics
* @param messageId
*/
- private void handleClearDiagnosticMessage(DiagnosticCall diagnosticCall, int messageId) {
- String callId = diagnosticCall.getCallId();
+ private void handleClearDiagnosticMessage(CallDiagnostics callDiagnostics, int messageId) {
+ String callId = callDiagnostics.getCallId();
try {
mAdapter.clearDiagnosticMessage(callId, messageId);
Log.i(this, "handleClearDiagnosticMessage: call=%s; msg=%d", callId, messageId);
diff --git a/telecomm/java/android/telecom/CallDiagnostics.java b/telecomm/java/android/telecom/CallDiagnostics.java
new file mode 100644
index 000000000000..3356431f17b1
--- /dev/null
+++ b/telecomm/java/android/telecom/CallDiagnostics.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telecom;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.telephony.Annotation;
+import android.telephony.CallQuality;
+import android.telephony.ims.ImsReasonInfo;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
+
+/**
+ * {@link CallDiagnostics} provides a way for a {@link CallDiagnosticService} to receive diagnostic
+ * information about a mobile call on the device. A {@link CallDiagnostics} instance is similar to
+ * a {@link Call}, however it does not expose call control capabilities and exposes extra diagnostic
+ * and messaging capabilities not present on a {@link Call}. The {@link CallDiagnosticService}
+ * creates a {@link CallDiagnostics} for each {@link Call} on the device. This means that for each
+ * in progress call on the device, the {@link CallDiagnosticService} will create an instance of
+ * {@link CallDiagnostics}.
+ * <p>
+ * The {@link CallDiagnosticService} can generate mid-call diagnostic messages using the
+ * {@link #displayDiagnosticMessage(int, CharSequence)} API which provides the user with valuable
+ * information about conditions impacting their call and corrective actions. For example, if the
+ * {@link CallDiagnosticService} determines that conditions on the call are degrading, it can inform
+ * the user that the call may soon drop and that they can try using a different calling method
+ * (e.g. VOIP or WIFI).
+ * <h2>Threading Model</h2>
+ * All incoming IPC from Telecom in this class will use the same {@link Executor} as the
+ * {@link CallDiagnosticService}. See {@link CallDiagnosticService#setExecutor(Executor)} for more
+ * information.
+ * @hide
+ */
+@SystemApi
+public abstract class CallDiagnostics {
+
+ /**
+ * @hide
+ */
+ public interface Listener {
+ /**
+ * Used to inform the {@link CallDiagnosticService} of a request to send a D2d message
+ * @param callDiagnostics the call the message is from.
+ * @param message the message type
+ * @param value the message value
+ */
+ void onSendDeviceToDeviceMessage(CallDiagnostics callDiagnostics, int message, int value);
+
+ /**
+ * Used to inform the {@link CallDiagnosticService} of a request to display a diagnostic
+ * message.
+ * @param callDiagnostics the call the message pertains to.
+ * @param messageId an identifier for the message.
+ * @param message the message to display.
+ */
+ void onDisplayDiagnosticMessage(CallDiagnostics callDiagnostics, int messageId,
+ CharSequence message);
+
+ /**
+ * Used to inform the {@link CallDiagnosticService} that a previously shown message is no
+ * longer pertinent.
+ * @param callDiagnostics the call the message pertains to.
+ * @param messageId the ID of the previously posted message.
+ */
+ void onClearDiagnosticMessage(CallDiagnostics callDiagnostics, int messageId);
+ }
+
+ /**
+ * Device to device message sent via {@link #sendDeviceToDeviceMessage(int, int)} (received via
+ * {@link #onReceiveDeviceToDeviceMessage(int, int)}) which communicates the radio access type
+ * used for the current call. The call network type communicated here is an intentional
+ * simplification of the {@link android.telephony.TelephonyManager#getNetworkType(int)} which
+ * removes some of the resolution inherent in those values; the
+ * {@link android.telephony.TelephonyManager#NETWORK_TYPE_LTE_CA} value, for example is
+ * collapsed into the {@link android.telephony.TelephonyManager#NETWORK_TYPE_LTE} value for
+ * efficiency of transport. For a discussion on the necessity of this simplification, see
+ * {@link #sendDeviceToDeviceMessage(int, int)}.
+ * <p>
+ * Valid values are below:
+ * <UL>
+ * <LI>{@link android.telephony.TelephonyManager#NETWORK_TYPE_LTE}</LI>
+ * <LI>{@link android.telephony.TelephonyManager#NETWORK_TYPE_IWLAN}</LI>
+ * <LI>{@link android.telephony.TelephonyManager#NETWORK_TYPE_NR}</LI>
+ * </UL>
+ */
+ public static final int MESSAGE_CALL_NETWORK_TYPE = 1;
+
+ /**
+ * Device to device message sent via {@link #sendDeviceToDeviceMessage(int, int)} (received via
+ * {@link #onReceiveDeviceToDeviceMessage(int, int)}) which communicates the call audio codec
+ * used for the current call.
+ * <p>
+ * The audio codec communicated here is an intentional simplification of the
+ * {@link Connection#EXTRA_AUDIO_CODEC} for a call and focuses on communicating the most common
+ * variants of these audio codecs. Other variants of these codecs are reported as the next
+ * closest variant. For example, the {@link Connection#AUDIO_CODEC_EVS_FB} full band codec
+ * is reported via device to device communication as {@link Connection#AUDIO_CODEC_EVS_WB}.
+ * For a discussion on the necessity of this simplification, see
+ * {@link #sendDeviceToDeviceMessage(int, int)}.
+ * <p>
+ * Valid values:
+ * <UL>
+ * <LI>{@link Connection#AUDIO_CODEC_EVS_WB}</LI>
+ * <LI>{@link Connection#AUDIO_CODEC_AMR_WB}</LI>
+ * <LI>{@link Connection#AUDIO_CODEC_AMR}</LI>
+ * </UL>
+ */
+ public static final int MESSAGE_CALL_AUDIO_CODEC = 2;
+
+ /**
+ * Device to device message sent via {@link #sendDeviceToDeviceMessage(int, int)} (received via
+ * {@link #onReceiveDeviceToDeviceMessage(int, int)}) which communicates the battery state of
+ * the device. Will typically mirror battery state reported via intents such as
+ * {@link android.content.Intent#ACTION_BATTERY_LOW}.
+ * <p>
+ * Valid values:
+ * <UL>
+ * <LI>{@link #BATTERY_STATE_LOW}</LI>
+ * <LI>{@link #BATTERY_STATE_GOOD}</LI>
+ * <LI>{@link #BATTERY_STATE_CHARGING}</LI>
+ * </UL>
+ */
+ public static final int MESSAGE_DEVICE_BATTERY_STATE = 3;
+
+ /**
+ * Device to device message sent via {@link #sendDeviceToDeviceMessage(int, int)} (received via
+ * {@link #onReceiveDeviceToDeviceMessage(int, int)}) which communicates the overall network
+ * coverage as it pertains to the current call. A {@link CallDiagnosticService} should signal
+ * poor coverage if the network coverage reaches a level where there is a high probability of
+ * the call dropping as a result.
+ * <p>
+ * Valid values:
+ * <UL>
+ * <LI>{@link #COVERAGE_POOR}</LI>
+ * <LI>{@link #COVERAGE_GOOD}</LI>
+ * </UL>
+ */
+ public static final int MESSAGE_DEVICE_NETWORK_COVERAGE = 4;
+
+ /**@hide*/
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "MESSAGE_", value = {
+ MESSAGE_CALL_NETWORK_TYPE,
+ MESSAGE_CALL_AUDIO_CODEC,
+ MESSAGE_DEVICE_BATTERY_STATE,
+ MESSAGE_DEVICE_NETWORK_COVERAGE
+ })
+ public @interface MessageType {}
+
+ /**
+ * Used with {@link #MESSAGE_DEVICE_BATTERY_STATE} to indicate that the battery is low.
+ */
+ public static final int BATTERY_STATE_LOW = 1;
+
+ /**
+ * Used with {@link #MESSAGE_DEVICE_BATTERY_STATE} to indicate that the battery is not low.
+ */
+ public static final int BATTERY_STATE_GOOD = 2;
+
+ /**
+ * Used with {@link #MESSAGE_DEVICE_BATTERY_STATE} to indicate that the battery is charging.
+ */
+ public static final int BATTERY_STATE_CHARGING = 3;
+
+ /**
+ * Used with {@link #MESSAGE_DEVICE_NETWORK_COVERAGE} to indicate that the coverage is poor.
+ */
+ public static final int COVERAGE_POOR = 1;
+
+ /**
+ * Used with {@link #MESSAGE_DEVICE_NETWORK_COVERAGE} to indicate that the coverage is good.
+ */
+ public static final int COVERAGE_GOOD = 2;
+
+ private Listener mListener;
+ private String mCallId;
+
+ /**
+ * @hide
+ */
+ public void setListener(@NonNull Listener listener) {
+ mListener = listener;
+ }
+
+ /**
+ * Sets the call ID for this {@link CallDiagnostics}.
+ * @param callId
+ * @hide
+ */
+ public void setCallId(@NonNull String callId) {
+ mCallId = callId;
+ }
+
+ /**
+ * @return the Telecom call ID for this {@link CallDiagnostics}.
+ * @hide
+ */
+ public @NonNull String getCallId() {
+ return mCallId;
+ }
+
+ /**
+ * Telecom calls this method when the details of a call changes.
+ * <p>
+ * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
+ * see {@link CallDiagnosticService#getExecutor()} for more information.
+ */
+ public abstract void onCallDetailsChanged(@NonNull android.telecom.Call.Details details);
+
+ /**
+ * The {@link CallDiagnosticService} implements this method to handle messages received via
+ * device to device communication.
+ * <p>
+ * See {@link #sendDeviceToDeviceMessage(int, int)} for background on device to device
+ * communication.
+ * <p>
+ * The underlying device to device communication protocol assumes that where there the two
+ * devices communicating are using a different version of the protocol, messages the recipient
+ * are not aware of are silently discarded. This means an older client talking to a new client
+ * will not receive newer messages and values sent by the new client.
+ * <p>
+ * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
+ * see {@link CallDiagnosticService#getExecutor()} for more information.
+ */
+ public abstract void onReceiveDeviceToDeviceMessage(
+ @MessageType int message,
+ int value);
+
+ /**
+ * Sends a device to device message to the device on the other end of this call.
+ * <p>
+ * Device to device communication is an Android platform feature which supports low bandwidth
+ * communication between Android devices while they are in a call. The device to device
+ * communication leverages DTMF tones or RTP header extensions to pass messages. The
+ * messages are unacknowledged and sent in a best-effort manner. The protocols assume that the
+ * nature of the message are informational only and are used only to convey basic state
+ * information between devices.
+ * <p>
+ * Device to device messages are intentional simplifications of more rich indicators in the
+ * platform due to the extreme bandwidth constraints inherent with underlying device to device
+ * communication transports used by the telephony framework. Device to device communication is
+ * either accomplished by adding RFC8285 compliant RTP header extensions to the audio packets
+ * for a call, or using the DTMF digits A-D as a communication pathway. RTP header extension
+ * packets ride alongside a the audio for a call, and are thus limited to roughly a byte for
+ * a message. Signalling requirements for DTMF digits place even more significant limitations
+ * on the amount of information which can be communicated during a call, offering only a few
+ * bits of potential information per message. The messages and values are constrained in order
+ * to meet the limited bandwidth inherent with DTMF signalling.
+ * <p>
+ * Allowed message types are:
+ * <ul>
+ * <li>{@link #MESSAGE_CALL_NETWORK_TYPE}</LI>
+ * <li>{@link #MESSAGE_CALL_AUDIO_CODEC}</LI>
+ * <li>{@link #MESSAGE_DEVICE_BATTERY_STATE}</LI>
+ * <li>{@link #MESSAGE_DEVICE_NETWORK_COVERAGE}</LI>
+ * </ul>
+ * @param message The message type to send.
+ * @param value The message value corresponding to the type.
+ */
+ public final void sendDeviceToDeviceMessage(int message, int value) {
+ if (mListener != null) {
+ mListener.onSendDeviceToDeviceMessage(this, message, value);
+ }
+ }
+
+ /**
+ * Telecom calls this method when a GSM or CDMA call disconnects.
+ * The CallDiagnosticService can return a human readable disconnect message which will be passed
+ * to the Dialer app as the {@link DisconnectCause#getDescription()}. A dialer app typically
+ * shows this message at the termination of the call. If {@code null} is returned, the
+ * disconnect message generated by the telephony stack will be shown instead.
+ * <p>
+ * @param disconnectCause the disconnect cause for the call.
+ * @param preciseDisconnectCause the precise disconnect cause for the call.
+ * @return the disconnect message to use in place of the default Telephony message, or
+ * {@code null} if the default message will not be overridden.
+ * <p>
+ * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
+ * see {@link CallDiagnosticService#getExecutor()} for more information.
+ */
+ // TODO: Wire in Telephony support for this.
+ public abstract @Nullable CharSequence onCallDisconnected(
+ @Annotation.DisconnectCauses int disconnectCause,
+ @Annotation.PreciseDisconnectCauses int preciseDisconnectCause);
+
+ /**
+ * Telecom calls this method when an IMS call disconnects and Telephony has already
+ * provided the disconnect reason info and disconnect message for the call. The
+ * {@link CallDiagnosticService} can intercept the raw IMS disconnect reason at this point and
+ * combine it with other call diagnostic information it is aware of to override the disconnect
+ * call message if desired.
+ *
+ * @param disconnectReason The {@link ImsReasonInfo} associated with the call disconnection.
+ * @return A user-readable call disconnect message to use in place of the platform-generated
+ * disconnect message, or {@code null} if the disconnect message should not be overridden.
+ * <p>
+ * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
+ * see {@link CallDiagnosticService#getExecutor()} for more information.
+ */
+ // TODO: Wire in Telephony support for this.
+ public abstract @Nullable CharSequence onCallDisconnected(
+ @NonNull ImsReasonInfo disconnectReason);
+
+ /**
+ * Telecom calls this method when a {@link CallQuality} report is received from the telephony
+ * stack for a call.
+ * @param callQuality The call quality report for this call.
+ * <p>
+ * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
+ * see {@link CallDiagnosticService#getExecutor()} for more information.
+ */
+ public abstract void onCallQualityReceived(@NonNull CallQuality callQuality);
+
+ /**
+ * Signals the active default dialer app to display a call diagnostic message. This can be
+ * used to report problems encountered during the span of a call.
+ * <p>
+ * The {@link CallDiagnosticService} provides a unique client-specific identifier used to
+ * identify the specific diagnostic message type.
+ * <p>
+ * The {@link CallDiagnosticService} should call {@link #clearDiagnosticMessage(int)} when the
+ * diagnostic condition has cleared.
+ * @param messageId the unique message identifier.
+ * @param message a human-readable, localized message to be shown to the user indicating a
+ * call issue which has occurred, along with potential mitigating actions.
+ */
+ public final void displayDiagnosticMessage(int messageId, @NonNull
+ CharSequence message) {
+ if (mListener != null) {
+ mListener.onDisplayDiagnosticMessage(this, messageId, message);
+ }
+ }
+
+ /**
+ * Signals to the active default dialer that the diagnostic message previously signalled using
+ * {@link #displayDiagnosticMessage(int, CharSequence)} with the specified messageId is no
+ * longer applicable (e.g. service has improved, for example.
+ * @param messageId the message identifier for a message previously shown via
+ * {@link #displayDiagnosticMessage(int, CharSequence)}.
+ */
+ public final void clearDiagnosticMessage(int messageId) {
+ if (mListener != null) {
+ mListener.onClearDiagnosticMessage(this, messageId);
+ }
+ }
+
+ /**
+ * Called by the {@link CallDiagnosticService} to update the call details for this
+ * {@link CallDiagnostics} based on an update received from Telecom.
+ * @param newDetails the new call details.
+ * @hide
+ */
+ public void handleCallUpdated(@NonNull Call.Details newDetails) {
+ onCallDetailsChanged(newDetails);
+ }
+}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 335857af8883..6dab6df22cf9 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -947,7 +947,7 @@ public abstract class Connection extends Conferenceable {
* {@link CallDiagnosticService} implementation which is active.
* <p>
* Likewise, if a {@link CallDiagnosticService} sends a message using
- * {@link DiagnosticCall#sendDeviceToDeviceMessage(int, int)}, it will be routed to telephony
+ * {@link CallDiagnostics#sendDeviceToDeviceMessage(int, int)}, it will be routed to telephony
* via {@link Connection#onCallEvent(String, Bundle)}. The telephony stack will relay the
* message to the other device.
* @hide
@@ -960,7 +960,7 @@ public abstract class Connection extends Conferenceable {
* Sent along with {@link #EVENT_DEVICE_TO_DEVICE_MESSAGE} to indicate the device to device
* message type.
*
- * See {@link DiagnosticCall} for more information.
+ * See {@link CallDiagnostics} for more information.
* @hide
*/
@SystemApi
@@ -971,7 +971,7 @@ public abstract class Connection extends Conferenceable {
* Sent along with {@link #EVENT_DEVICE_TO_DEVICE_MESSAGE} to indicate the device to device
* message value.
* <p>
- * See {@link DiagnosticCall} for more information.
+ * See {@link CallDiagnostics} for more information.
* @hide
*/
@SystemApi
diff --git a/telecomm/java/android/telecom/DiagnosticCall.java b/telecomm/java/android/telecom/DiagnosticCall.java
index af46b7759fb5..a6b7258052a4 100644
--- a/telecomm/java/android/telecom/DiagnosticCall.java
+++ b/telecomm/java/android/telecom/DiagnosticCall.java
@@ -16,338 +16,12 @@
package android.telecom;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.telephony.Annotation;
-import android.telephony.CallQuality;
-import android.telephony.ims.ImsReasonInfo;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.concurrent.Executor;
/**
- * A {@link DiagnosticCall} provides a way for a {@link CallDiagnosticService} to receive diagnostic
- * information about a mobile call on the device. A {@link DiagnosticCall} is similar to a
- * {@link Call}, however it does not expose call control capabilities and exposes extra diagnostic
- * and messaging capabilities not present on a {@link Call}. The {@link CallDiagnosticService}
- * creates a {@link DiagnosticCall} for each {@link Call} on the device. This means that for each
- * in progress call on the device, the {@link CallDiagnosticService} will create an instance of
- * {@link DiagnosticCall}.
- * <p>
- * The {@link CallDiagnosticService} can generate mid-call diagnostic messages using the
- * {@link #displayDiagnosticMessage(int, CharSequence)} API which provides the user with valuable
- * information about conditions impacting their call and corrective actions. For example, if the
- * {@link CallDiagnosticService} determines that conditions on the call are degrading, it can inform
- * the user that the call may soon drop and that they can try using a different calling method
- * (e.g. VOIP or WIFI).
- * <h2>Threading Model</h2>
- * All incoming IPC from Telecom in this class will use the same {@link Executor} as the
- * {@link CallDiagnosticService}. See {@link CallDiagnosticService#setExecutor(Executor)} for more
- * information.
+ * @deprecated use {@link CallDiagnostics} instead.
* @hide
*/
@SystemApi
-public abstract class DiagnosticCall {
-
- /**
- * @hide
- */
- public interface Listener {
- void onSendDeviceToDeviceMessage(DiagnosticCall diagnosticCall, int message, int value);
- void onDisplayDiagnosticMessage(DiagnosticCall diagnosticCall, int messageId,
- CharSequence message);
- void onClearDiagnosticMessage(DiagnosticCall diagnosticCall, int messageId);
- }
-
- /**
- * Device to device message sent via {@link #sendDeviceToDeviceMessage(int, int)} (received via
- * {@link #onReceiveDeviceToDeviceMessage(int, int)}) which communicates the radio access type
- * used for the current call. The call network type communicated here is an intentional
- * simplification of the {@link android.telephony.TelephonyManager#getNetworkType(int)} which
- * removes some of the resolution inherent in those values; the
- * {@link android.telephony.TelephonyManager#NETWORK_TYPE_LTE_CA} value, for example is
- * collapsed into the {@link android.telephony.TelephonyManager#NETWORK_TYPE_LTE} value for
- * efficiency of transport. For a discussion on the necessity of this simplification, see
- * {@link #sendDeviceToDeviceMessage(int, int)}.
- * <p>
- * Valid values are below:
- * <UL>
- * <LI>{@link android.telephony.TelephonyManager#NETWORK_TYPE_LTE}</LI>
- * <LI>{@link android.telephony.TelephonyManager#NETWORK_TYPE_IWLAN}</LI>
- * <LI>{@link android.telephony.TelephonyManager#NETWORK_TYPE_NR}</LI>
- * </UL>
- */
- public static final int MESSAGE_CALL_NETWORK_TYPE = 1;
-
- /**
- * Device to device message sent via {@link #sendDeviceToDeviceMessage(int, int)} (received via
- * {@link #onReceiveDeviceToDeviceMessage(int, int)}) which communicates the call audio codec
- * used for the current call.
- * <p>
- * The audio codec communicated here is an intentional simplification of the
- * {@link Connection#EXTRA_AUDIO_CODEC} for a call and focuses on communicating the most common
- * variants of these audio codecs. Other variants of these codecs are reported as the next
- * closest variant. For example, the {@link Connection#AUDIO_CODEC_EVS_FB} full band codec
- * is reported via device to device communication as {@link Connection#AUDIO_CODEC_EVS_WB}.
- * For a discussion on the necessity of this simplification, see
- * {@link #sendDeviceToDeviceMessage(int, int)}.
- * <p>
- * Valid values:
- * <UL>
- * <LI>{@link Connection#AUDIO_CODEC_EVS_WB}</LI>
- * <LI>{@link Connection#AUDIO_CODEC_AMR_WB}</LI>
- * <LI>{@link Connection#AUDIO_CODEC_AMR}</LI>
- * </UL>
- */
- public static final int MESSAGE_CALL_AUDIO_CODEC = 2;
-
- /**
- * Device to device message sent via {@link #sendDeviceToDeviceMessage(int, int)} (received via
- * {@link #onReceiveDeviceToDeviceMessage(int, int)}) which communicates the battery state of
- * the device. Will typically mirror battery state reported via intents such as
- * {@link android.content.Intent#ACTION_BATTERY_LOW}.
- * <p>
- * Valid values:
- * <UL>
- * <LI>{@link #BATTERY_STATE_LOW}</LI>
- * <LI>{@link #BATTERY_STATE_GOOD}</LI>
- * <LI>{@link #BATTERY_STATE_CHARGING}</LI>
- * </UL>
- */
- public static final int MESSAGE_DEVICE_BATTERY_STATE = 3;
-
- /**
- * Device to device message sent via {@link #sendDeviceToDeviceMessage(int, int)} (received via
- * {@link #onReceiveDeviceToDeviceMessage(int, int)}) which communicates the overall network
- * coverage as it pertains to the current call. A {@link CallDiagnosticService} should signal
- * poor coverage if the network coverage reaches a level where there is a high probability of
- * the call dropping as a result.
- * <p>
- * Valid values:
- * <UL>
- * <LI>{@link #COVERAGE_POOR}</LI>
- * <LI>{@link #COVERAGE_GOOD}</LI>
- * </UL>
- */
- public static final int MESSAGE_DEVICE_NETWORK_COVERAGE = 4;
-
- /**@hide*/
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = "MESSAGE_", value = {
- MESSAGE_CALL_NETWORK_TYPE,
- MESSAGE_CALL_AUDIO_CODEC,
- MESSAGE_DEVICE_BATTERY_STATE,
- MESSAGE_DEVICE_NETWORK_COVERAGE
- })
- public @interface MessageType {}
-
- /**
- * Used with {@link #MESSAGE_DEVICE_BATTERY_STATE} to indicate that the battery is low.
- */
- public static final int BATTERY_STATE_LOW = 1;
-
- /**
- * Used with {@link #MESSAGE_DEVICE_BATTERY_STATE} to indicate that the battery is not low.
- */
- public static final int BATTERY_STATE_GOOD = 2;
-
- /**
- * Used with {@link #MESSAGE_DEVICE_BATTERY_STATE} to indicate that the battery is charging.
- */
- public static final int BATTERY_STATE_CHARGING = 3;
-
- /**
- * Used with {@link #MESSAGE_DEVICE_NETWORK_COVERAGE} to indicate that the coverage is poor.
- */
- public static final int COVERAGE_POOR = 1;
-
- /**
- * Used with {@link #MESSAGE_DEVICE_NETWORK_COVERAGE} to indicate that the coverage is good.
- */
- public static final int COVERAGE_GOOD = 2;
-
- private Listener mListener;
- private String mCallId;
-
- /**
- * @hide
- */
- public void setListener(@NonNull Listener listener) {
- mListener = listener;
- }
-
- /**
- * Sets the call ID for this {@link DiagnosticCall}.
- * @param callId
- * @hide
- */
- public void setCallId(@NonNull String callId) {
- mCallId = callId;
- }
-
- /**
- * @return the Telecom call ID for this {@link DiagnosticCall}.
- * @hide
- */
- public @NonNull String getCallId() {
- return mCallId;
- }
-
- /**
- * Telecom calls this method when the details of a call changes.
- * <p>
- * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
- * see {@link CallDiagnosticService#getExecutor()} for more information.
- */
- public abstract void onCallDetailsChanged(@NonNull android.telecom.Call.Details details);
-
- /**
- * The {@link CallDiagnosticService} implements this method to handle messages received via
- * device to device communication.
- * <p>
- * See {@link #sendDeviceToDeviceMessage(int, int)} for background on device to device
- * communication.
- * <p>
- * The underlying device to device communication protocol assumes that where there the two
- * devices communicating are using a different version of the protocol, messages the recipient
- * are not aware of are silently discarded. This means an older client talking to a new client
- * will not receive newer messages and values sent by the new client.
- * <p>
- * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
- * see {@link CallDiagnosticService#getExecutor()} for more information.
- */
- public abstract void onReceiveDeviceToDeviceMessage(
- @MessageType int message,
- int value);
-
- /**
- * Sends a device to device message to the device on the other end of this call.
- * <p>
- * Device to device communication is an Android platform feature which supports low bandwidth
- * communication between Android devices while they are in a call. The device to device
- * communication leverages DTMF tones or RTP header extensions to pass messages. The
- * messages are unacknowledged and sent in a best-effort manner. The protocols assume that the
- * nature of the message are informational only and are used only to convey basic state
- * information between devices.
- * <p>
- * Device to device messages are intentional simplifications of more rich indicators in the
- * platform due to the extreme bandwidth constraints inherent with underlying device to device
- * communication transports used by the telephony framework. Device to device communication is
- * either accomplished by adding RFC8285 compliant RTP header extensions to the audio packets
- * for a call, or using the DTMF digits A-D as a communication pathway. RTP header extension
- * packets ride alongside a the audio for a call, and are thus limited to roughly a byte for
- * a message. Signalling requirements for DTMF digits place even more significant limitations
- * on the amount of information which can be communicated during a call, offering only a few
- * bits of potential information per message. The messages and values are constrained in order
- * to meet the limited bandwidth inherent with DTMF signalling.
- * <p>
- * Allowed message types are:
- * <ul>
- * <li>{@link #MESSAGE_CALL_NETWORK_TYPE}</LI>
- * <li>{@link #MESSAGE_CALL_AUDIO_CODEC}</LI>
- * <li>{@link #MESSAGE_DEVICE_BATTERY_STATE}</LI>
- * <li>{@link #MESSAGE_DEVICE_NETWORK_COVERAGE}</LI>
- * </ul>
- * @param message The message type to send.
- * @param value The message value corresponding to the type.
- */
- public final void sendDeviceToDeviceMessage(int message, int value) {
- if (mListener != null) {
- mListener.onSendDeviceToDeviceMessage(this, message, value);
- }
- }
-
- /**
- * Telecom calls this method when a GSM or CDMA call disconnects.
- * The CallDiagnosticService can return a human readable disconnect message which will be passed
- * to the Dialer app as the {@link DisconnectCause#getDescription()}. A dialer app typically
- * shows this message at the termination of the call. If {@code null} is returned, the
- * disconnect message generated by the telephony stack will be shown instead.
- * <p>
- * @param disconnectCause the disconnect cause for the call.
- * @param preciseDisconnectCause the precise disconnect cause for the call.
- * @return the disconnect message to use in place of the default Telephony message, or
- * {@code null} if the default message will not be overridden.
- * <p>
- * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
- * see {@link CallDiagnosticService#getExecutor()} for more information.
- */
- // TODO: Wire in Telephony support for this.
- public abstract @Nullable CharSequence onCallDisconnected(
- @Annotation.DisconnectCauses int disconnectCause,
- @Annotation.PreciseDisconnectCauses int preciseDisconnectCause);
-
- /**
- * Telecom calls this method when an IMS call disconnects and Telephony has already
- * provided the disconnect reason info and disconnect message for the call. The
- * {@link CallDiagnosticService} can intercept the raw IMS disconnect reason at this point and
- * combine it with other call diagnostic information it is aware of to override the disconnect
- * call message if desired.
- *
- * @param disconnectReason The {@link ImsReasonInfo} associated with the call disconnection.
- * @return A user-readable call disconnect message to use in place of the platform-generated
- * disconnect message, or {@code null} if the disconnect message should not be overridden.
- * <p>
- * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
- * see {@link CallDiagnosticService#getExecutor()} for more information.
- */
- // TODO: Wire in Telephony support for this.
- public abstract @Nullable CharSequence onCallDisconnected(
- @NonNull ImsReasonInfo disconnectReason);
-
- /**
- * Telecom calls this method when a {@link CallQuality} report is received from the telephony
- * stack for a call.
- * @param callQuality The call quality report for this call.
- * <p>
- * Calls to this method will use the same {@link Executor} as the {@link CallDiagnosticService};
- * see {@link CallDiagnosticService#getExecutor()} for more information.
- */
- public abstract void onCallQualityReceived(@NonNull CallQuality callQuality);
-
- /**
- * Signals the active default dialer app to display a call diagnostic message. This can be
- * used to report problems encountered during the span of a call.
- * <p>
- * The {@link CallDiagnosticService} provides a unique client-specific identifier used to
- * identify the specific diagnostic message type.
- * <p>
- * The {@link CallDiagnosticService} should call {@link #clearDiagnosticMessage(int)} when the
- * diagnostic condition has cleared.
- * @param messageId the unique message identifier.
- * @param message a human-readable, localized message to be shown to the user indicating a
- * call issue which has occurred, along with potential mitigating actions.
- */
- public final void displayDiagnosticMessage(int messageId, @NonNull
- CharSequence message) {
- if (mListener != null) {
- mListener.onDisplayDiagnosticMessage(this, messageId, message);
- }
- }
-
- /**
- * Signals to the active default dialer that the diagnostic message previously signalled using
- * {@link #displayDiagnosticMessage(int, CharSequence)} with the specified messageId is no
- * longer applicable (e.g. service has improved, for example.
- * @param messageId the message identifier for a message previously shown via
- * {@link #displayDiagnosticMessage(int, CharSequence)}.
- */
- public final void clearDiagnosticMessage(int messageId) {
- if (mListener != null) {
- mListener.onClearDiagnosticMessage(this, messageId);
- }
- }
-
- /**
- * Called by the {@link CallDiagnosticService} to update the call details for this
- * {@link DiagnosticCall} based on an update received from Telecom.
- * @param newDetails the new call details.
- * @hide
- */
- public void handleCallUpdated(@NonNull Call.Details newDetails) {
- onCallDetailsChanged(newDetails);
- }
+public abstract class DiagnosticCall extends CallDiagnostics {
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index faa5deed0f1c..962200b82a81 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -15454,7 +15454,9 @@ public class TelephonyManager {
public static final int PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED = 1;
/**
- * The unattended reboot was not prepared due to generic error.
+ * The unattended reboot was not prepared due to a non-recoverable error. After this error,
+ * the client that manages the unattended reboot should not try to invoke the API again
+ * until the next power cycle.
* @hide
*/
@SystemApi
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
index 3c12aaa0f1c8..c92d40cdd555 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
@@ -16,7 +16,6 @@
package com.android.server.wm.flicker.close
-import android.view.WindowManagerPolicyConstants
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
@@ -50,12 +49,7 @@ class CloseAppBackButtonTest(testSpec: FlickerTestParameter) : CloseAppTransitio
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests(
- repetitions = 5,
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
- )
- )
+ .getConfigNonRotationTests(repetitions = 5)
}
}
} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
index 8359ccf12d2d..1f880f61d65e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
@@ -16,7 +16,6 @@
package com.android.server.wm.flicker.close
-import android.view.WindowManagerPolicyConstants
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
@@ -50,12 +49,7 @@ class CloseAppHomeButtonTest(testSpec: FlickerTestParameter) : CloseAppTransitio
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests(
- repetitions = 5,
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
- )
- )
+ .getConfigNonRotationTests(repetitions = 5)
}
}
} \ No newline at end of file
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index fadd1eac14ef..58d8ee512dc2 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -202,6 +202,7 @@ import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkPolicyManager;
import android.net.NetworkRequest;
+import android.net.NetworkScore;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
import android.net.NetworkStackClient;
@@ -1078,6 +1079,10 @@ public class ConnectivityServiceTest {
public void triggerUnfulfillable(NetworkRequest r) {
super.releaseRequestAsUnfulfillableByAnyFactory(r);
}
+
+ public void assertNoRequestChanged() {
+ assertNull(mRequestHistory.poll(0, r -> true));
+ }
}
private Set<UidRange> uidRangesForUids(int... uids) {
@@ -9160,7 +9165,8 @@ public class ConnectivityServiceTest {
ConnectivityManager.getNetworkTypeName(TYPE_MOBILE),
TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE));
return new NetworkAgentInfo(null, new Network(NET_ID), info, new LinkProperties(),
- nc, 0, mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0,
+ nc, new NetworkScore.Builder().setLegacyInt(0).build(),
+ mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0,
INVALID_UID, mQosCallbackTracker, new ConnectivityService.Dependencies());
}
@@ -11119,11 +11125,99 @@ public class ConnectivityServiceTest {
mCm.unregisterNetworkCallback(cellCb);
}
+ // Cannot be part of MockNetworkFactory since it requires method of the test.
+ private void expectNoRequestChanged(@NonNull MockNetworkFactory factory) {
+ waitForIdle();
+ factory.assertNoRequestChanged();
+ }
+
@Test
- public void testRegisterBestMatchingNetworkCallback() throws Exception {
- final NetworkRequest request = new NetworkRequest.Builder().build();
- assertThrows(UnsupportedOperationException.class,
- () -> mCm.registerBestMatchingNetworkCallback(request, new NetworkCallback(),
- mCsHandlerThread.getThreadHandler()));
+ public void testRegisterBestMatchingNetworkCallback_noIssueToFactory() throws Exception {
+ // Prepare mock mms factory.
+ final HandlerThread handlerThread = new HandlerThread("MockCellularFactory");
+ handlerThread.start();
+ NetworkCapabilities filter = new NetworkCapabilities()
+ .addTransportType(TRANSPORT_CELLULAR)
+ .addCapability(NET_CAPABILITY_MMS);
+ final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
+ mServiceContext, "testFactory", filter, mCsHandlerThread);
+ testFactory.setScoreFilter(40);
+
+ try {
+ // Register the factory and expect it will see default request, because all requests
+ // are sent to all factories.
+ testFactory.register();
+ testFactory.expectRequestAdd();
+ testFactory.assertRequestCountEquals(1);
+ // The factory won't try to start the network since the default request doesn't
+ // match the filter (no INTERNET capability).
+ assertFalse(testFactory.getMyStartRequested());
+
+ // Register callback for listening best matching network. Verify that the request won't
+ // be sent to factory.
+ final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
+ mCm.registerBestMatchingNetworkCallback(
+ new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
+ bestMatchingCb, mCsHandlerThread.getThreadHandler());
+ bestMatchingCb.assertNoCallback();
+ expectNoRequestChanged(testFactory);
+ testFactory.assertRequestCountEquals(1);
+ assertFalse(testFactory.getMyStartRequested());
+
+ // Fire a normal mms request, verify the factory will only see the request.
+ final TestNetworkCallback mmsNetworkCallback = new TestNetworkCallback();
+ final NetworkRequest mmsRequest = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_MMS).build();
+ mCm.requestNetwork(mmsRequest, mmsNetworkCallback);
+ testFactory.expectRequestAdd();
+ testFactory.assertRequestCountEquals(2);
+ assertTrue(testFactory.getMyStartRequested());
+
+ // Unregister best matching callback, verify factory see no change.
+ mCm.unregisterNetworkCallback(bestMatchingCb);
+ expectNoRequestChanged(testFactory);
+ testFactory.assertRequestCountEquals(2);
+ assertTrue(testFactory.getMyStartRequested());
+ } finally {
+ testFactory.terminate();
+ }
+ }
+
+ @Test
+ public void testRegisterBestMatchingNetworkCallback_trackBestNetwork() throws Exception {
+ final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
+ mCm.registerBestMatchingNetworkCallback(
+ new NetworkRequest.Builder().addCapability(NET_CAPABILITY_TRUSTED).build(),
+ bestMatchingCb, mCsHandlerThread.getThreadHandler());
+
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+ bestMatchingCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(true);
+ bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+
+ // Change something on cellular to trigger capabilities changed, since the callback
+ // only cares about the best network, verify it received nothing from cellular.
+ mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
+ bestMatchingCb.assertNoCallback();
+
+ // Make cellular the best network again, verify the callback now tracks cellular.
+ mWiFiNetworkAgent.adjustScore(-50);
+ bestMatchingCb.expectAvailableCallbacksValidated(mCellNetworkAgent);
+
+ // Make cellular temporary non-trusted, which will not satisfying the request.
+ // Verify the callback switch from/to the other network accordingly.
+ mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
+ bestMatchingCb.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
+ mCellNetworkAgent.addCapability(NET_CAPABILITY_TRUSTED);
+ bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mCellNetworkAgent);
+
+ // Verify the callback doesn't care about wifi disconnect.
+ mWiFiNetworkAgent.disconnect();
+ bestMatchingCb.assertNoCallback();
+ mCellNetworkAgent.disconnect();
+ bestMatchingCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
}
}
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index 1c0ba4f8d8f5..ea2b362c537a 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -40,6 +40,7 @@ import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkProvider;
+import android.net.NetworkScore;
import android.os.Binder;
import android.text.format.DateUtils;
@@ -355,8 +356,9 @@ public class LingerMonitorTest {
caps.addCapability(0);
caps.addTransportType(transport);
NetworkAgentInfo nai = new NetworkAgentInfo(null, new Network(netId), info,
- new LinkProperties(), caps, 50, mCtx, null, new NetworkAgentConfig() /* config */,
- mConnService, mNetd, mDnsResolver, NetworkProvider.ID_NONE, Binder.getCallingUid(),
+ new LinkProperties(), caps, new NetworkScore.Builder().setLegacyInt(50).build(),
+ mCtx, null, new NetworkAgentConfig() /* config */, mConnService, mNetd,
+ mDnsResolver, NetworkProvider.ID_NONE, Binder.getCallingUid(),
mQosCallbackTracker, new ConnectivityService.Dependencies());
nai.everValidated = true;
return nai;
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index b8f7fbca3983..11fcea60d98d 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -1026,7 +1026,11 @@ public class VpnTest {
.thenReturn(new Network[] { new Network(101) });
when(mConnectivityManager.registerNetworkAgent(any(), any(), any(), any(),
- anyInt(), any(), anyInt())).thenReturn(new Network(102));
+ any(), any(), anyInt())).thenAnswer(invocation -> {
+ // The runner has registered an agent and is now ready.
+ legacyRunnerReady.open();
+ return new Network(102);
+ });
final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), profile);
final TestDeps deps = (TestDeps) vpn.mDeps;
try {
@@ -1048,7 +1052,7 @@ public class VpnTest {
ArgumentCaptor<NetworkCapabilities> ncCaptor =
ArgumentCaptor.forClass(NetworkCapabilities.class);
verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(),
- lpCaptor.capture(), ncCaptor.capture(), anyInt(), any(), anyInt());
+ lpCaptor.capture(), ncCaptor.capture(), any(), any(), anyInt());
// In this test the expected address is always v4 so /32.
// Note that the interface needs to be specified because RouteInfo objects stored in
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index 0e5f5e43f282..ca6448ca9b8c 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -188,7 +188,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
any(),
lpCaptor.capture(),
ncCaptor.capture(),
- anyInt(),
+ any(),
any(),
anyInt());
verify(mIpSecSvc)