Merge changes Id1439137,Iad79331e
* changes:
8/n: Schedule invalidation request
7/n: Add HalClientMonitor
diff --git a/apex/appsearch/framework/api/current.txt b/apex/appsearch/framework/api/current.txt
index 9fa4b8e..f9ff9dd 100644
--- a/apex/appsearch/framework/api/current.txt
+++ b/apex/appsearch/framework/api/current.txt
@@ -80,7 +80,8 @@
method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig.Builder setTokenizerType(int);
}
- public final class AppSearchSession {
+ public final class AppSearchSession implements java.io.Closeable {
+ method public void close();
method public void getByUri(@NonNull android.app.appsearch.GetByUriRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,android.app.appsearch.GenericDocument>);
method public void getSchema(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.util.Set<android.app.appsearch.AppSearchSchema>>>);
method public void putDocuments(@NonNull android.app.appsearch.PutDocumentsRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,java.lang.Void>);
diff --git a/apex/appsearch/framework/api/system-current.txt b/apex/appsearch/framework/api/system-current.txt
index 73a4a19..56b7ffd 100644
--- a/apex/appsearch/framework/api/system-current.txt
+++ b/apex/appsearch/framework/api/system-current.txt
@@ -9,7 +9,8 @@
method public static void initialize();
}
- public class GlobalSearchSession {
+ public class GlobalSearchSession implements java.io.Closeable {
+ method public void close();
method @NonNull public android.app.appsearch.SearchResults query(@NonNull String, @NonNull android.app.appsearch.SearchSpec, @NonNull java.util.concurrent.Executor);
}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
index d4872e8..0427577 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
@@ -28,6 +28,7 @@
import com.android.internal.util.Preconditions;
+import java.io.Closeable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -42,7 +43,7 @@
*
* This class is thread safe.
*/
-public final class AppSearchSession {
+public final class AppSearchSession implements Closeable {
private static final String TAG = "AppSearchSession";
private final String mDatabaseName;
@UserIdInt
@@ -490,11 +491,10 @@
}
/**
- * Closes the SearchSessionImpl to persists all update/delete requests to the disk.
- *
- * @hide
+ * Closes the {@link AppSearchSession} to persist all schema and document updates, additions,
+ * and deletes to disk.
*/
- // TODO(b/175637134) when unhide it, implement Closeable and remove this method.
+ @Override
public void close() {
if (mIsMutated && !mIsClosed) {
try {
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
index 95f7d79..9e34616 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
@@ -23,6 +23,9 @@
import android.annotation.UserIdInt;
import android.os.RemoteException;
+import com.android.internal.util.Preconditions;
+
+import java.io.Closeable;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -34,11 +37,12 @@
* @hide
*/
@SystemApi
-public class GlobalSearchSession {
+public class GlobalSearchSession implements Closeable {
private final IAppSearchManager mService;
@UserIdInt
private final int mUserId;
+ private boolean mIsClosed = false;
static void createGlobalSearchSession(
@NonNull IAppSearchManager service,
@@ -129,7 +133,14 @@
Objects.requireNonNull(queryExpression);
Objects.requireNonNull(searchSpec);
Objects.requireNonNull(executor);
+ Preconditions.checkState(!mIsClosed, "GlobalSearchSession has already been closed");
return new SearchResults(mService, /*databaseName=*/null, queryExpression,
searchSpec, mUserId, executor);
}
+
+ /** Closes the {@link GlobalSearchSession}. */
+ @Override
+ public void close() {
+ mIsClosed = true;
+ }
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index a9ca730..26b5abe 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -260,11 +260,9 @@
try {
final int bindFlags;
if (job.shouldTreatAsExpeditedJob()) {
- // Add BIND_FOREGROUND_SERVICE to make it BFGS. Without it, it'll be
- // PROCESS_STATE_IMPORTANT_FOREGROUND. Unclear which is better here.
// TODO(171305774): The job should run on the little cores. We'll probably need
// another binding flag for that.
- bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
+ bindFlags = Context.BIND_AUTO_CREATE;
} else {
bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
| Context.BIND_NOT_PERCEPTIBLE;
diff --git a/apex/media/framework/api/current.txt b/apex/media/framework/api/current.txt
index ce3bcbe..103bb47 100644
--- a/apex/media/framework/api/current.txt
+++ b/apex/media/framework/api/current.txt
@@ -6,9 +6,11 @@
method public int describeContents();
method @NonNull public java.util.List<java.lang.String> getSupportedHdrTypes();
method @NonNull public java.util.List<java.lang.String> getSupportedVideoMimeTypes();
- method public boolean isHdrTypeSupported(@NonNull String);
+ method @NonNull public java.util.List<java.lang.String> getUnsupportedHdrTypes();
+ method @NonNull public java.util.List<java.lang.String> getUnsupportedVideoMimeTypes();
+ method public boolean isHdrTypeSupported(@NonNull String) throws android.media.ApplicationMediaCapabilities.FormatNotFoundException;
method public boolean isSlowMotionSupported();
- method public boolean isVideoMimeTypeSupported(@NonNull String);
+ method public boolean isVideoMimeTypeSupported(@NonNull String) throws android.media.ApplicationMediaCapabilities.FormatNotFoundException;
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.media.ApplicationMediaCapabilities> CREATOR;
}
@@ -17,10 +19,16 @@
ctor public ApplicationMediaCapabilities.Builder();
method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedHdrType(@NonNull String);
method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedVideoMimeType(@NonNull String);
+ method @NonNull public android.media.ApplicationMediaCapabilities.Builder addUnsupportedHdrType(@NonNull String);
+ method @NonNull public android.media.ApplicationMediaCapabilities.Builder addUnsupportedVideoMimeType(@NonNull String);
method @NonNull public android.media.ApplicationMediaCapabilities build();
method @NonNull public android.media.ApplicationMediaCapabilities.Builder setSlowMotionSupported(boolean);
}
+ public static class ApplicationMediaCapabilities.FormatNotFoundException extends android.util.AndroidException {
+ ctor public ApplicationMediaCapabilities.FormatNotFoundException(@NonNull String);
+ }
+
public class MediaController2 implements java.lang.AutoCloseable {
method public void cancelSessionCommand(@NonNull Object);
method public void close();
diff --git a/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java b/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java
index 36f6b94..25ccec2 100644
--- a/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java
+++ b/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java
@@ -22,6 +22,7 @@
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.AndroidException;
import android.util.Log;
import org.xmlpull.v1.XmlPullParser;
@@ -68,35 +69,73 @@
public final class ApplicationMediaCapabilities implements Parcelable {
private static final String TAG = "ApplicationMediaCapabilities";
+ /**
+ * This exception is thrown when a given format is not specified in the media capabilities.
+ */
+ public static class FormatNotFoundException extends AndroidException {
+ public FormatNotFoundException(@NonNull String format) {
+ super(format);
+ }
+ }
+
/** List of supported video codec mime types. */
// TODO: init it with avc and mpeg4 as application is assuming to support them.
private Set<String> mSupportedVideoMimeTypes = new HashSet<>();
+ /** List of unsupported video codec mime types. */
+ private Set<String> mUnsupportedVideoMimeTypes = new HashSet<>();
+
/** List of supported hdr types. */
private Set<String> mSupportedHdrTypes = new HashSet<>();
+ /** List of unsupported hdr types. */
+ private Set<String> mUnsupportedHdrTypes = new HashSet<>();
+
private boolean mIsSlowMotionSupported = false;
private ApplicationMediaCapabilities(Builder b) {
mSupportedVideoMimeTypes.addAll(b.getSupportedVideoMimeTypes());
+ mUnsupportedVideoMimeTypes.addAll(b.getUnsupportedVideoMimeTypes());
mSupportedHdrTypes.addAll(b.getSupportedHdrTypes());
+ mUnsupportedHdrTypes.addAll(b.getUnsupportedHdrTypes());
mIsSlowMotionSupported = b.mIsSlowMotionSupported;
}
/**
- * Query if an video codec is supported by the application.
+ * Query if a video codec format is supported by the application.
+ * @param videoMime The mime type of the video codec format. Must be the one used in
+ * {@link MediaFormat#KEY_MIME}.
+ * @return true if application supports the video codec format, false otherwise.
+ * @throws FormatNotFoundException if the application did not specify the codec either in the
+ * supported or unsupported formats.
*/
public boolean isVideoMimeTypeSupported(
- @NonNull String videoMime) {
- return mSupportedVideoMimeTypes.contains(videoMime);
+ @NonNull String videoMime) throws FormatNotFoundException {
+ if (mUnsupportedVideoMimeTypes.contains(videoMime)) {
+ return false;
+ } else if (mSupportedVideoMimeTypes.contains(videoMime)) {
+ return true;
+ } else {
+ throw new FormatNotFoundException(videoMime);
+ }
}
/**
- * Query if a hdr type is supported by the application.
+ * Query if a HDR type is supported by the application.
+ * @param hdrType The type of the HDR format.
+ * @return true if application supports the HDR format, false otherwise.
+ * @throws FormatNotFoundException if the application did not specify the format either in the
+ * supported or unsupported formats.
*/
public boolean isHdrTypeSupported(
- @NonNull @MediaFeature.MediaHdrType String hdrType) {
- return mSupportedHdrTypes.contains(hdrType);
+ @NonNull @MediaFeature.MediaHdrType String hdrType) throws FormatNotFoundException {
+ if (mUnsupportedHdrTypes.contains(hdrType)) {
+ return false;
+ } else if (mSupportedHdrTypes.contains(hdrType)) {
+ return true;
+ } else {
+ throw new FormatNotFoundException(hdrType);
+ }
}
@Override
@@ -111,11 +150,21 @@
for (String cap : mSupportedVideoMimeTypes) {
dest.writeString(cap);
}
+ // Write out the unsupported video mime types.
+ dest.writeInt(mUnsupportedVideoMimeTypes.size());
+ for (String cap : mUnsupportedVideoMimeTypes) {
+ dest.writeString(cap);
+ }
// Write out the supported hdr types.
dest.writeInt(mSupportedHdrTypes.size());
for (String cap : mSupportedHdrTypes) {
dest.writeString(cap);
}
+ // Write out the unsupported hdr types.
+ dest.writeInt(mUnsupportedHdrTypes.size());
+ for (String cap : mUnsupportedHdrTypes) {
+ dest.writeString(cap);
+ }
// Write out the supported slow motion.
dest.writeBoolean(mIsSlowMotionSupported);
}
@@ -124,7 +173,9 @@
public String toString() {
String caps = new String(
"Supported Video MimeTypes: " + mSupportedVideoMimeTypes.toString());
+ caps += "Unsupported Video MimeTypes: " + mUnsupportedVideoMimeTypes.toString();
caps += "Supported HDR types: " + mSupportedHdrTypes.toString();
+ caps += "Unsupported HDR types: " + mUnsupportedHdrTypes.toString();
caps += "Supported slow motion: " + mIsSlowMotionSupported;
return caps;
}
@@ -159,9 +210,8 @@
};
/*
- * Returns a list that contains all the video codec mime types supported by the application.
- * The list will be empty if no codecs are supported by the application.
- * @return List of supported video codec mime types.
+ * Query the video codec mime types supported by the application.
+ * @return List of supported video codec mime types. The list will be empty if there are none.
*/
@NonNull
public List<String> getSupportedVideoMimeTypes() {
@@ -169,9 +219,17 @@
}
/*
- * Returns a list that contains all hdr types supported by the application.
- * The list will be empty if no hdr types are supported by the application.
- * @return List of supported hdr types.
+ * Query the video codec mime types that are not supported by the application.
+ * @return List of unsupported video codec mime types. The list will be empty if there are none.
+ */
+ @NonNull
+ public List<String> getUnsupportedVideoMimeTypes() {
+ return new ArrayList<>(mSupportedVideoMimeTypes);
+ }
+
+ /*
+ * Query all hdr types that are supported by the application.
+ * @return List of supported hdr types. The list will be empty if there are none.
*/
@NonNull
public List<String> getSupportedHdrTypes() {
@@ -179,6 +237,15 @@
}
/*
+ * Query all hdr types that are not supported by the application.
+ * @return List of unsupported hdr types. The list will be empty if there are none.
+ */
+ @NonNull
+ public List<String> getUnsupportedHdrTypes() {
+ return new ArrayList<>(mUnsupportedHdrTypes);
+ }
+
+ /*
* Whether handling of slow-motion video is supported
*/
public boolean isSlowMotionSupported() {
@@ -213,6 +280,12 @@
/** List of supported hdr types. */
private Set<String> mSupportedHdrTypes = new HashSet<>();
+ /** List of unsupported video codec mime types. */
+ private Set<String> mUnsupportedVideoMimeTypes = new HashSet<>();
+
+ /** List of unsupported hdr types. */
+ private Set<String> mUnsupportedHdrTypes = new HashSet<>();
+
private boolean mIsSlowMotionSupported = false;
/* Map to save the format read from the xml. */
@@ -299,26 +372,50 @@
case "HEVC":
if (isSupported) {
mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
+ } else {
+ mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
+ }
+ break;
+ case "VP9":
+ if (isSupported) {
+ mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_VP9);
+ } else {
+ mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_VP9);
+ }
+ break;
+ case "AV1":
+ if (isSupported) {
+ mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_AV1);
+ } else {
+ mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_AV1);
}
break;
case "HDR10":
if (isSupported) {
mSupportedHdrTypes.add(MediaFeature.HdrType.HDR10);
+ } else {
+ mUnsupportedHdrTypes.add(MediaFeature.HdrType.HDR10);
}
break;
case "HDR10Plus":
if (isSupported) {
mSupportedHdrTypes.add(MediaFeature.HdrType.HDR10_PLUS);
+ } else {
+ mUnsupportedHdrTypes.add(MediaFeature.HdrType.HDR10_PLUS);
}
break;
case "Dolby-Vision":
if (isSupported) {
mSupportedHdrTypes.add(MediaFeature.HdrType.DOLBY_VISION);
+ } else {
+ mUnsupportedHdrTypes.add(MediaFeature.HdrType.DOLBY_VISION);
}
break;
case "HLG":
if (isSupported) {
mSupportedHdrTypes.add(MediaFeature.HdrType.HLG);
+ } else {
+ mUnsupportedHdrTypes.add(MediaFeature.HdrType.HLG);
}
break;
case "SlowMotion":
@@ -348,8 +445,11 @@
@NonNull
public ApplicationMediaCapabilities build() {
Log.d(TAG,
- "Building ApplicationMediaCapabilities with: " + mSupportedHdrTypes.toString()
- + " " + mSupportedVideoMimeTypes.toString() + " "
+ "Building ApplicationMediaCapabilities with: (Supported HDR: "
+ + mSupportedHdrTypes.toString() + " Unsupported HDR: "
+ + mUnsupportedHdrTypes.toString() + ") (Supported Codec: "
+ + " " + mSupportedVideoMimeTypes.toString() + " Unsupported Codec:"
+ + mUnsupportedVideoMimeTypes.toString() + ") "
+ mIsSlowMotionSupported);
// If hdr is supported, application must also support hevc.
@@ -365,8 +465,7 @@
*
* @param codecMime Supported codec mime types. Must be one of the mime type defined
* in {@link MediaFormat}.
- * @throws UnsupportedOperationException if the codec mime type is not supported.
- * @throws IllegalArgumentException if mime type is not valid.
+ * @throws IllegalArgumentException if mime type is not valid.
*/
@NonNull
public Builder addSupportedVideoMimeType(
@@ -379,16 +478,49 @@
return new ArrayList<>(mSupportedVideoMimeTypes);
}
+ private boolean isValidVideoCodecMimeType(@NonNull String codecMime) {
+ if (!codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)
+ && !codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)
+ && !codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AV1)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Adds an unsupported video codec mime type.
+ *
+ * @param codecMime Unsupported codec mime type. Must be one of the mime type defined
+ * in {@link MediaFormat}.
+ * @throws IllegalArgumentException if mime type is not valid.
+ */
+ @NonNull
+ public Builder addUnsupportedVideoMimeType(
+ @NonNull String codecMime) {
+ if (!isValidVideoCodecMimeType(codecMime)) {
+ throw new IllegalArgumentException("Invalid codec mime type: " + codecMime);
+ }
+ mUnsupportedVideoMimeTypes.add(codecMime);
+ return this;
+ }
+
+ private List<String> getUnsupportedVideoMimeTypes() {
+ return new ArrayList<>(mUnsupportedVideoMimeTypes);
+ }
+
/**
* Adds a supported hdr type.
*
- * @param hdrType Supported hdr types. Must be one of the String defined in
+ * @param hdrType Supported hdr type. Must be one of the String defined in
* {@link MediaFeature.HdrType}.
* @throws IllegalArgumentException if hdrType is not valid.
*/
@NonNull
public Builder addSupportedHdrType(
@NonNull @MediaFeature.MediaHdrType String hdrType) {
+ if (!isValidVideoCodecHdrType(hdrType)) {
+ throw new IllegalArgumentException("Invalid hdr type: " + hdrType);
+ }
mSupportedHdrTypes.add(hdrType);
return this;
}
@@ -397,6 +529,37 @@
return new ArrayList<>(mSupportedHdrTypes);
}
+ private boolean isValidVideoCodecHdrType(@NonNull String hdrType) {
+ if (!hdrType.equals(MediaFeature.HdrType.DOLBY_VISION)
+ && !hdrType.equals(MediaFeature.HdrType.HDR10)
+ && !hdrType.equals(MediaFeature.HdrType.HDR10_PLUS)
+ && !hdrType.equals(MediaFeature.HdrType.HLG)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Adds an unsupported hdr type.
+ *
+ * @param hdrType Unsupported hdr type. Must be one of the String defined in
+ * {@link MediaFeature.HdrType}.
+ * @throws IllegalArgumentException if hdrType is not valid.
+ */
+ @NonNull
+ public Builder addUnsupportedHdrType(
+ @NonNull @MediaFeature.MediaHdrType String hdrType) {
+ if (!isValidVideoCodecHdrType(hdrType)) {
+ throw new IllegalArgumentException("Invalid hdr type: " + hdrType);
+ }
+ mUnsupportedHdrTypes.add(hdrType);
+ return this;
+ }
+
+ private List<String> getUnsupportedHdrTypes() {
+ return new ArrayList<>(mUnsupportedHdrTypes);
+ }
+
/**
* Sets whether slow-motion video is supported.
* If an application indicates support for slow-motion, it is application's responsibility
diff --git a/apex/media/framework/java/android/media/MediaTranscodeManager.java b/apex/media/framework/java/android/media/MediaTranscodeManager.java
index 3d706e4..5d212b8 100644
--- a/apex/media/framework/java/android/media/MediaTranscodeManager.java
+++ b/apex/media/framework/java/android/media/MediaTranscodeManager.java
@@ -980,8 +980,15 @@
throw new UnsupportedOperationException(
"Source video format hint must be set!");
}
- boolean supportHevc = mClientCaps.isVideoMimeTypeSupported(
- MediaFormat.MIMETYPE_VIDEO_HEVC);
+
+ boolean supportHevc = false;
+ try {
+ supportHevc = mClientCaps.isVideoMimeTypeSupported(
+ MediaFormat.MIMETYPE_VIDEO_HEVC);
+ } catch (ApplicationMediaCapabilities.FormatNotFoundException ex) {
+ // Set to false if application did not specify.
+ supportHevc = false;
+ }
if (!supportHevc && MediaFormat.MIMETYPE_VIDEO_HEVC.equals(
mSrcVideoFormatHint.getString(MediaFormat.KEY_MIME))) {
return true;
diff --git a/config/hiddenapi-temp-blocklist.txt b/config/hiddenapi-max-target-r-loprio.txt
similarity index 100%
rename from config/hiddenapi-temp-blocklist.txt
rename to config/hiddenapi-max-target-r-loprio.txt
diff --git a/core/api/current.txt b/core/api/current.txt
index ba3f636..1eeb927 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -393,6 +393,7 @@
field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d
field public static final int canControlMagnification = 16844039; // 0x1010507
+ field public static final int canPauseRecording = 16844314; // 0x101061a
field public static final int canPerformGestures = 16844045; // 0x101050d
field public static final int canRecord = 16844060; // 0x101051c
field @Deprecated public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
@@ -1054,11 +1055,11 @@
field public static final int parentActivityName = 16843687; // 0x10103a7
field @Deprecated public static final int password = 16843100; // 0x101015c
field public static final int path = 16842794; // 0x101002a
- field public static final int pathAdvancedPattern = 16844318; // 0x101061e
+ field public static final int pathAdvancedPattern = 16844319; // 0x101061f
field public static final int pathData = 16843781; // 0x1010405
field public static final int pathPattern = 16842796; // 0x101002c
field public static final int pathPrefix = 16842795; // 0x101002b
- field public static final int pathSuffix = 16844316; // 0x101061c
+ field public static final int pathSuffix = 16844317; // 0x101061d
field public static final int patternPathData = 16843978; // 0x10104ca
field public static final int permission = 16842758; // 0x1010006
field public static final int permissionFlags = 16843719; // 0x10103c7
@@ -1151,7 +1152,7 @@
field public static final int reqNavigation = 16843306; // 0x101022a
field public static final int reqTouchScreen = 16843303; // 0x1010227
field public static final int requestLegacyExternalStorage = 16844291; // 0x1010603
- field public static final int requireDeviceScreenOn = 16844315; // 0x101061b
+ field public static final int requireDeviceScreenOn = 16844316; // 0x101061c
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
@@ -1292,10 +1293,10 @@
field public static final int spotShadowAlpha = 16843967; // 0x10104bf
field public static final int src = 16843033; // 0x1010119
field public static final int ssp = 16843747; // 0x10103e3
- field public static final int sspAdvancedPattern = 16844319; // 0x101061f
+ field public static final int sspAdvancedPattern = 16844320; // 0x1010620
field public static final int sspPattern = 16843749; // 0x10103e5
field public static final int sspPrefix = 16843748; // 0x10103e4
- field public static final int sspSuffix = 16844317; // 0x101061d
+ field public static final int sspSuffix = 16844318; // 0x101061e
field public static final int stackFromBottom = 16843005; // 0x10100fd
field public static final int stackViewStyle = 16843838; // 0x101043e
field public static final int starStyle = 16842882; // 0x1010082
@@ -6759,7 +6760,7 @@
method public android.content.Intent getCropAndSetWallpaperIntent(android.net.Uri);
method public int getDesiredMinimumHeight();
method public int getDesiredMinimumWidth();
- method public android.graphics.drawable.Drawable getDrawable();
+ method @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public android.graphics.drawable.Drawable getDrawable();
method @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
method @Nullable public android.app.WallpaperColors getWallpaperColors(int);
@@ -10349,6 +10350,7 @@
field public static final String BIOMETRIC_SERVICE = "biometric";
field public static final String BLOB_STORE_SERVICE = "blob_store";
field public static final String BLUETOOTH_SERVICE = "bluetooth";
+ field public static final String BUGREPORT_SERVICE = "bugreport";
field public static final String CAMERA_SERVICE = "camera";
field public static final String CAPTIONING_SERVICE = "captioning";
field public static final String CARRIER_CONFIG_SERVICE = "carrier_config";
@@ -15542,7 +15544,6 @@
ctor public Point(int, int);
ctor public Point(@NonNull android.graphics.Point);
method public int describeContents();
- method public final void dump(@NonNull java.io.PrintWriter);
method public final boolean equals(int, int);
method public final void negate();
method public final void offset(int, int);
@@ -24751,6 +24752,7 @@
}
public final class TvInputInfo implements android.os.Parcelable {
+ method public boolean canPauseRecording();
method public boolean canRecord();
method @Deprecated public android.content.Intent createSettingsIntent();
method public android.content.Intent createSetupIntent();
@@ -24784,6 +24786,7 @@
public static final class TvInputInfo.Builder {
ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName);
method public android.media.tv.TvInputInfo build();
+ method @NonNull public android.media.tv.TvInputInfo.Builder setCanPauseRecording(boolean);
method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean);
method public android.media.tv.TvInputInfo.Builder setExtras(android.os.Bundle);
method public android.media.tv.TvInputInfo.Builder setTunerCount(int);
@@ -24875,7 +24878,9 @@
method public void notifyRecordingStopped(android.net.Uri);
method public void notifyTuned(android.net.Uri);
method public void onAppPrivateCommand(@NonNull String, android.os.Bundle);
+ method public void onPauseRecording(@NonNull android.os.Bundle);
method public abstract void onRelease();
+ method public void onResumeRecording(@NonNull android.os.Bundle);
method public abstract void onStartRecording(@Nullable android.net.Uri);
method public void onStartRecording(@Nullable android.net.Uri, @NonNull android.os.Bundle);
method public abstract void onStopRecording();
@@ -24925,7 +24930,11 @@
public class TvRecordingClient {
ctor public TvRecordingClient(android.content.Context, String, @NonNull android.media.tv.TvRecordingClient.RecordingCallback, android.os.Handler);
+ method public void pauseRecording();
+ method public void pauseRecording(@NonNull android.os.Bundle);
method public void release();
+ method public void resumeRecording();
+ method public void resumeRecording(@NonNull android.os.Bundle);
method public void sendAppPrivateCommand(@NonNull String, android.os.Bundle);
method public void startRecording(@Nullable android.net.Uri);
method public void startRecording(@Nullable android.net.Uri, @NonNull android.os.Bundle);
@@ -30073,6 +30082,24 @@
method public boolean unlinkToDeath(@NonNull android.os.IBinder.DeathRecipient, int);
}
+ public final class BugreportManager {
+ method public void cancelBugreport();
+ method public void startConnectivityBugreport(@NonNull android.os.ParcelFileDescriptor, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
+ }
+
+ public abstract static class BugreportManager.BugreportCallback {
+ ctor public BugreportManager.BugreportCallback();
+ method public void onEarlyReportFinished();
+ method public void onError(int);
+ method public void onFinished();
+ method public void onProgress(@FloatRange(from=0.0f, to=100.0f) float);
+ field public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS = 5; // 0x5
+ field public static final int BUGREPORT_ERROR_INVALID_INPUT = 1; // 0x1
+ field public static final int BUGREPORT_ERROR_RUNTIME = 2; // 0x2
+ field public static final int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT = 4; // 0x4
+ field public static final int BUGREPORT_ERROR_USER_DENIED_CONSENT = 3; // 0x3
+ }
+
public class Build {
ctor public Build();
method @NonNull public static java.util.List<android.os.Build.Partition> getFingerprintedPartitions();
@@ -34462,6 +34489,7 @@
field public static final String ACTION_LOCATION_SOURCE_SETTINGS = "android.settings.LOCATION_SOURCE_SETTINGS";
field public static final String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
field public static final String ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION = "android.settings.MANAGE_ALL_FILES_ACCESS_PERMISSION";
+ field public static final String ACTION_MANAGE_ALL_SUBSCRIPTIONS_SETTINGS = "android.settings.MANAGE_ALL_SUBSCRIPTIONS_SETTINGS";
field public static final String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
field public static final String ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION = "android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION";
field public static final String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
@@ -39755,6 +39783,7 @@
field public static final int BAND_25 = 25; // 0x19
field public static final int BAND_257 = 257; // 0x101
field public static final int BAND_258 = 258; // 0x102
+ field public static final int BAND_26 = 26; // 0x1a
field public static final int BAND_260 = 260; // 0x104
field public static final int BAND_261 = 261; // 0x105
field public static final int BAND_28 = 28; // 0x1c
@@ -39766,10 +39795,12 @@
field public static final int BAND_39 = 39; // 0x27
field public static final int BAND_40 = 40; // 0x28
field public static final int BAND_41 = 41; // 0x29
+ field public static final int BAND_46 = 46; // 0x2e
field public static final int BAND_48 = 48; // 0x30
field public static final int BAND_5 = 5; // 0x5
field public static final int BAND_50 = 50; // 0x32
field public static final int BAND_51 = 51; // 0x33
+ field public static final int BAND_53 = 53; // 0x35
field public static final int BAND_65 = 65; // 0x41
field public static final int BAND_66 = 66; // 0x42
field public static final int BAND_7 = 7; // 0x7
@@ -39795,6 +39826,7 @@
field public static final int BAND_93 = 93; // 0x5d
field public static final int BAND_94 = 94; // 0x5e
field public static final int BAND_95 = 95; // 0x5f
+ field public static final int BAND_96 = 96; // 0x60
}
public static final class AccessNetworkConstants.UtranBand {
@@ -40173,6 +40205,11 @@
field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
}
+ public static final class CarrierConfigManager.ImsServiceEntitlement {
+ field public static final String KEY_AES_URL_STRING = "imsserviceentitlement.aes_url_string";
+ field public static final String KEY_PREFIX = "imsserviceentitlement.";
+ }
+
public static final class CarrierConfigManager.Iwlan {
field public static final int AUTHENTICATION_METHOD_CERT = 1; // 0x1
field public static final int AUTHENTICATION_METHOD_EAP_ONLY = 0; // 0x0
@@ -41110,12 +41147,13 @@
public class PhoneNumberUtils {
ctor public PhoneNumberUtils();
method public static void addTtsSpan(android.text.Spannable, int, int);
+ method public static boolean areSamePhoneNumber(@NonNull String, @NonNull String, @NonNull String);
method @Deprecated public static String calledPartyBCDFragmentToString(byte[], int, int);
method public static String calledPartyBCDFragmentToString(byte[], int, int, int);
method @Deprecated public static String calledPartyBCDToString(byte[], int, int);
method public static String calledPartyBCDToString(byte[], int, int, int);
- method public static boolean compare(String, String);
- method public static boolean compare(android.content.Context, String, String);
+ method @Deprecated public static boolean compare(String, String);
+ method @Deprecated public static boolean compare(android.content.Context, String, String);
method public static String convertKeypadLettersToDigits(String);
method public static android.text.style.TtsSpan createTtsSpan(String);
method public static CharSequence createTtsSpannable(CharSequence);
@@ -41300,17 +41338,27 @@
public final class PhysicalChannelConfig implements android.os.Parcelable {
method public int describeContents();
- method public int getCellBandwidthDownlink();
- method public int getChannelNumber();
+ method @IntRange(from=1, to=261) public int getBand();
+ method @IntRange(from=1) public int getCellBandwidthDownlinkKhz();
+ method @IntRange(from=1) public int getCellBandwidthUplinkKhz();
+ method @Deprecated public int getChannelNumber();
method public int getConnectionStatus();
+ method @IntRange(from=0) public int getDownlinkChannelNumber();
+ method @IntRange(from=0) public int getDownlinkFrequencyKhz();
method public int getNetworkType();
method @IntRange(from=0, to=1007) public int getPhysicalCellId();
+ method @IntRange(from=0) public int getUplinkChannelNumber();
+ method @IntRange(from=0) public int getUplinkFrequencyKhz();
method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int BAND_UNKNOWN = 0; // 0x0
+ field public static final int CELL_BANDWIDTH_UNKNOWN = 0; // 0x0
field public static final int CHANNEL_NUMBER_UNKNOWN = -1; // 0xffffffff
field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1
field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2
field public static final int CONNECTION_UNKNOWN = -1; // 0xffffffff
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhysicalChannelConfig> CREATOR;
+ field public static final int FREQUENCY_UNKNOWN = -1; // 0xffffffff
+ field public static final int PHYSICAL_CELL_ID_MAXIMUM_VALUE = 1007; // 0x3ef
field public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; // 0xffffffff
}
@@ -41393,6 +41441,32 @@
field public static final int INVALID = 2147483647; // 0x7fffffff
}
+ public final class SignalThresholdInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getRadioAccessNetworkType();
+ method public int getSignalMeasurementType();
+ method @NonNull public int[] getThresholds();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SignalThresholdInfo> CREATOR;
+ field public static final int SIGNAL_MEASUREMENT_TYPE_RSCP = 2; // 0x2
+ field public static final int SIGNAL_MEASUREMENT_TYPE_RSRP = 3; // 0x3
+ field public static final int SIGNAL_MEASUREMENT_TYPE_RSRQ = 4; // 0x4
+ field public static final int SIGNAL_MEASUREMENT_TYPE_RSSI = 1; // 0x1
+ field public static final int SIGNAL_MEASUREMENT_TYPE_RSSNR = 5; // 0x5
+ field public static final int SIGNAL_MEASUREMENT_TYPE_SSRSRP = 6; // 0x6
+ field public static final int SIGNAL_MEASUREMENT_TYPE_SSRSRQ = 7; // 0x7
+ field public static final int SIGNAL_MEASUREMENT_TYPE_SSSINR = 8; // 0x8
+ field public static final int SIGNAL_MEASUREMENT_TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ public static final class SignalThresholdInfo.Builder {
+ ctor public SignalThresholdInfo.Builder();
+ method @NonNull public android.telephony.SignalThresholdInfo build();
+ method @NonNull public android.telephony.SignalThresholdInfo.Builder setRadioAccessNetworkType(int);
+ method @NonNull public android.telephony.SignalThresholdInfo.Builder setSignalMeasurementType(int);
+ method @NonNull public android.telephony.SignalThresholdInfo.Builder setThresholds(@NonNull int[]);
+ }
+
public final class SmsManager {
method public String createAppSpecificSmsToken(android.app.PendingIntent);
method @Nullable public String createAppSpecificSmsTokenWithPackageInfo(@Nullable String, @NonNull android.app.PendingIntent);
@@ -41850,8 +41924,8 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void switchMultiSimConfig(int);
method public void unregisterPhoneStateListener(@NonNull android.telephony.PhoneStateListener);
method public void updateAvailableNetworks(@NonNull java.util.List<android.telephony.AvailableNetworkInfo>, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
- method public void uploadCallComposerPicture(@NonNull java.nio.file.Path, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.os.ParcelUuid,android.telephony.TelephonyManager.CallComposerException>);
- method public void uploadCallComposerPicture(@NonNull java.io.InputStream, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.os.ParcelUuid,android.telephony.TelephonyManager.CallComposerException>);
+ method public void uploadCallComposerPicture(@NonNull java.nio.file.Path, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.os.ParcelUuid,android.telephony.TelephonyManager.CallComposerException>);
+ method public void uploadCallComposerPicture(@NonNull java.io.InputStream, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.os.ParcelUuid,android.telephony.TelephonyManager.CallComposerException>);
field public static final String ACTION_CARRIER_MESSAGING_CLIENT_SERVICE = "android.telephony.action.CARRIER_MESSAGING_CLIENT_SERVICE";
field public static final String ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE = "android.telephony.action.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE";
field public static final String ACTION_CARRIER_SIGNAL_PCO_VALUE = "android.telephony.action.CARRIER_SIGNAL_PCO_VALUE";
@@ -41877,6 +41951,7 @@
field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80
field public static final int CALL_COMPOSER_STATUS_OFF = 0; // 0x0
field public static final int CALL_COMPOSER_STATUS_ON = 1; // 0x1
+ field public static final int CALL_COMPOSER_STATUS_ON_NO_PICTURES = 2; // 0x2
field public static final int CALL_STATE_IDLE = 0; // 0x0
field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
field public static final int CALL_STATE_RINGING = 1; // 0x1
@@ -42002,6 +42077,7 @@
field public static final int ERROR_FILE_TOO_LARGE = 2; // 0x2
field public static final int ERROR_INPUT_CLOSED = 4; // 0x4
field public static final int ERROR_IO_EXCEPTION = 5; // 0x5
+ field public static final int ERROR_NETWORK_UNAVAILABLE = 6; // 0x6
field public static final int ERROR_REMOTE_END_CLOSED = 1; // 0x1
field public static final int ERROR_UNKNOWN = 0; // 0x0
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 21a6ba1..eab4d64 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -893,6 +893,8 @@
field public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI";
field public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL";
field public static final String EXTRA_PROVISIONING_ORGANIZATION_NAME = "android.app.extra.PROVISIONING_ORGANIZATION_NAME";
+ field public static final String EXTRA_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE = "android.app.extra.PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE";
+ field public static final String EXTRA_PROVISIONING_SKIP_OWNERSHIP_DISCLAIMER = "android.app.extra.PROVISIONING_SKIP_OWNERSHIP_DISCLAIMER";
field public static final String EXTRA_PROVISIONING_SUPPORTED_MODES = "android.app.extra.PROVISIONING_SUPPORTED_MODES";
field public static final String EXTRA_PROVISIONING_SUPPORT_URL = "android.app.extra.PROVISIONING_SUPPORT_URL";
field public static final String EXTRA_PROVISIONING_TRIGGER = "android.app.extra.PROVISIONING_TRIGGER";
@@ -1922,7 +1924,6 @@
field public static final String BATTERY_STATS_SERVICE = "batterystats";
field public static final int BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS = 1048576; // 0x100000
field public static final int BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND = 262144; // 0x40000
- field public static final String BUGREPORT_SERVICE = "bugreport";
field public static final String CONTENT_SUGGESTIONS_SERVICE = "content_suggestions";
field public static final String CONTEXTHUB_SERVICE = "contexthub";
field public static final String ETHERNET_SERVICE = "ethernet";
@@ -3983,6 +3984,25 @@
method public void onLocationBatch(java.util.List<android.location.Location>);
}
+ public final class CorrelationVector implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public int getFrequencyOffsetMetersPerSecond();
+ method @NonNull public int[] getMagnitude();
+ method @FloatRange(from=0.0f) public double getSamplingStartMeters();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getSamplingWidthMeters();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.CorrelationVector> CREATOR;
+ }
+
+ public static final class CorrelationVector.Builder {
+ ctor public CorrelationVector.Builder();
+ method @NonNull public android.location.CorrelationVector build();
+ method @NonNull public android.location.CorrelationVector.Builder setFrequencyOffsetMetersPerSecond(@IntRange(from=0) int);
+ method @NonNull public android.location.CorrelationVector.Builder setMagnitude(@NonNull int[]);
+ method @NonNull public android.location.CorrelationVector.Builder setSamplingStartMeters(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.CorrelationVector.Builder setSamplingWidthMeters(@FloatRange(from=0.0f, fromInclusive=false) double);
+ }
+
public final class GnssCapabilities implements android.os.Parcelable {
method public boolean hasGeofencing();
method public boolean hasLowPowerMode();
@@ -3991,6 +4011,7 @@
method public boolean hasMeasurementCorrectionsLosSats();
method @Deprecated public boolean hasMeasurementCorrectionsReflectingPane();
method public boolean hasMeasurementCorrectionsReflectingPlane();
+ method public boolean hasMeasurementCorrelationVectors();
method @Deprecated public boolean hasNavMessages();
method @Deprecated public boolean hasSatelliteBlacklist();
method public boolean hasSatelliteBlocklist();
@@ -4004,12 +4025,15 @@
method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsExcessPathLength(boolean);
method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsLosSats(boolean);
method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsReflectingPlane(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrelationVectors(boolean);
method @NonNull public android.location.GnssCapabilities.Builder setHasSatelliteBlocklist(boolean);
method @NonNull public android.location.GnssCapabilities.Builder setHasSatellitePvt(boolean);
}
public final class GnssMeasurement implements android.os.Parcelable {
+ method @Nullable public java.util.Collection<android.location.CorrelationVector> getCorrelationVectors();
method @Nullable public android.location.SatellitePvt getSatellitePvt();
+ method public boolean hasCorrelationVectors();
method public boolean hasSatellitePvt();
}
@@ -4043,6 +4067,14 @@
method @NonNull public android.location.GnssMeasurementCorrections.Builder setVerticalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
}
+ public final class GnssMeasurementRequest implements android.os.Parcelable {
+ method public boolean isCorrelationVectorOutputsEnabled();
+ }
+
+ public static final class GnssMeasurementRequest.Builder {
+ method @NonNull public android.location.GnssMeasurementRequest.Builder setCorrelationVectorOutputsEnabled(boolean);
+ }
+
public final class GnssReflectingPlane implements android.os.Parcelable {
method public int describeContents();
method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
@@ -5319,9 +5351,9 @@
method public int disconnectFrontendToCiCam(int);
method public int getAvSyncHwId(@NonNull android.media.tv.tuner.filter.Filter);
method public long getAvSyncTime(int);
+ method @Nullable public java.util.List<android.media.tv.tuner.frontend.FrontendInfo> getAvailableFrontendInfos();
method @Nullable public android.media.tv.tuner.DemuxCapabilities getDemuxCapabilities();
method @Nullable public android.media.tv.tuner.frontend.FrontendInfo getFrontendInfo();
- method @Nullable public java.util.List<android.media.tv.tuner.frontend.FrontendInfo> getFrontendInfoList();
method @Nullable public android.media.tv.tuner.frontend.FrontendStatus getFrontendStatus(@NonNull int[]);
method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER) public android.media.tv.tuner.Descrambler openDescrambler();
method @Nullable public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener);
@@ -7821,24 +7853,10 @@
}
public final class BugreportManager {
- method @RequiresPermission(android.Manifest.permission.DUMP) public void cancelBugreport();
method @RequiresPermission(android.Manifest.permission.DUMP) public void requestBugreport(@NonNull android.os.BugreportParams, @Nullable CharSequence, @Nullable CharSequence);
method @RequiresPermission(android.Manifest.permission.DUMP) public void startBugreport(@NonNull android.os.ParcelFileDescriptor, @Nullable android.os.ParcelFileDescriptor, @NonNull android.os.BugreportParams, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
}
- public abstract static class BugreportManager.BugreportCallback {
- ctor public BugreportManager.BugreportCallback();
- method public void onEarlyReportFinished();
- method public void onError(int);
- method public void onFinished();
- method public void onProgress(@FloatRange(from=0.0f, to=100.0f) float);
- field public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS = 5; // 0x5
- field public static final int BUGREPORT_ERROR_INVALID_INPUT = 1; // 0x1
- field public static final int BUGREPORT_ERROR_RUNTIME = 2; // 0x2
- field public static final int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT = 4; // 0x4
- field public static final int BUGREPORT_ERROR_USER_DENIED_CONSENT = 3; // 0x3
- }
-
public final class BugreportParams {
ctor public BugreportParams(int);
method public int getMode();
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 62c660c..775ded7 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -385,18 +385,35 @@
method @NonNull public static String operationToString(int);
method @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public void setNextOperationSafety(int, boolean);
field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED";
+ field public static final int OPERATION_CLEAR_APPLICATION_USER_DATA = 23; // 0x17
field public static final int OPERATION_CREATE_AND_MANAGE_USER = 5; // 0x5
+ field public static final int OPERATION_INSTALL_CA_CERT = 24; // 0x18
+ field public static final int OPERATION_INSTALL_KEY_PAIR = 25; // 0x19
+ field public static final int OPERATION_INSTALL_SYSTEM_UPDATE = 26; // 0x1a
field public static final int OPERATION_LOCK_NOW = 1; // 0x1
field public static final int OPERATION_LOGOUT_USER = 9; // 0x9
field public static final int OPERATION_REBOOT = 7; // 0x7
+ field public static final int OPERATION_REMOVE_ACTIVE_ADMIN = 27; // 0x1b
+ field public static final int OPERATION_REMOVE_KEY_PAIR = 28; // 0x1c
field public static final int OPERATION_REMOVE_USER = 6; // 0x6
+ field public static final int OPERATION_REQUEST_BUGREPORT = 29; // 0x1d
+ field public static final int OPERATION_SET_ALWAYS_ON_VPN_PACKAGE = 30; // 0x1e
field public static final int OPERATION_SET_APPLICATION_HIDDEN = 15; // 0xf
field public static final int OPERATION_SET_APPLICATION_RESTRICTIONS = 16; // 0x10
+ field public static final int OPERATION_SET_CAMERA_DISABLED = 31; // 0x1f
+ field public static final int OPERATION_SET_FACTORY_RESET_PROTECTION_POLICY = 32; // 0x20
+ field public static final int OPERATION_SET_GLOBAL_PRIVATE_DNS = 33; // 0x21
field public static final int OPERATION_SET_KEEP_UNINSTALLED_PACKAGES = 17; // 0x11
field public static final int OPERATION_SET_KEYGUARD_DISABLED = 12; // 0xc
field public static final int OPERATION_SET_LOCK_TASK_FEATURES = 18; // 0x12
field public static final int OPERATION_SET_LOCK_TASK_PACKAGES = 19; // 0x13
+ field public static final int OPERATION_SET_LOGOUT_ENABLED = 34; // 0x22
+ field public static final int OPERATION_SET_MASTER_VOLUME_MUTED = 35; // 0x23
+ field public static final int OPERATION_SET_OVERRIDE_APNS_ENABLED = 36; // 0x24
field public static final int OPERATION_SET_PACKAGES_SUSPENDED = 20; // 0x14
+ field public static final int OPERATION_SET_PERMISSION_GRANT_STATE = 37; // 0x25
+ field public static final int OPERATION_SET_PERMISSION_POLICY = 38; // 0x26
+ field public static final int OPERATION_SET_RESTRICTIONS_PROVIDER = 39; // 0x27
field public static final int OPERATION_SET_STATUS_BAR_DISABLED = 13; // 0xd
field public static final int OPERATION_SET_SYSTEM_SETTING = 11; // 0xb
field public static final int OPERATION_SET_SYSTEM_UPDATE_POLICY = 14; // 0xe
@@ -406,6 +423,7 @@
field public static final int OPERATION_START_USER_IN_BACKGROUND = 3; // 0x3
field public static final int OPERATION_STOP_USER = 4; // 0x4
field public static final int OPERATION_SWITCH_USER = 2; // 0x2
+ field public static final int OPERATION_UNINSTALL_CA_CERT = 40; // 0x28
field public static final int OPERATION_WIPE_DATA = 8; // 0x8
}
@@ -449,13 +467,10 @@
package android.app.role {
- public class RoleControllerManager {
- method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isApplicationVisibleForRole(@NonNull String, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isRoleVisible(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
- }
-
public final class RoleManager {
method @Nullable public String getSmsRoleHolder(int);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isApplicationVisibleForRole(@NonNull String, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isRoleVisible(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
}
}
@@ -730,6 +745,18 @@
}
+package android.hardware {
+
+ public final class SensorPrivacyManager {
+ method public boolean isIndividualSensorPrivacyEnabled(int);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setIndividualSensorPrivacy(int, boolean);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setIndividualSensorPrivacyForProfileGroup(int, boolean);
+ field public static final int INDIVIDUAL_SENSOR_CAMERA = 2; // 0x2
+ field public static final int INDIVIDUAL_SENSOR_MICROPHONE = 1; // 0x1
+ }
+
+}
+
package android.hardware.biometrics {
public class BiometricManager {
@@ -929,6 +956,7 @@
method @Deprecated public void resetCarrierPhase();
method @Deprecated public void resetCarrierPhaseUncertainty();
method public void resetCodeType();
+ method public void resetCorrelationVectors();
method public void resetFullInterSignalBiasNanos();
method public void resetFullInterSignalBiasUncertaintyNanos();
method public void resetSatelliteInterSignalBiasNanos();
@@ -948,6 +976,7 @@
method public void setCn0DbHz(double);
method public void setCodeType(@NonNull String);
method public void setConstellationType(int);
+ method public void setCorrelationVectors(@Nullable java.util.Collection<android.location.CorrelationVector>);
method public void setFullInterSignalBiasNanos(double);
method public void setFullInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
method public void setMultipathIndicator(int);
diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt
index 3bd88a4..216d340 100644
--- a/core/api/test-lint-baseline.txt
+++ b/core/api/test-lint-baseline.txt
@@ -468,6 +468,8 @@
GetterSetterNames: android.location.GnssMeasurement#setCarrierFrequencyHz(float):
GetterSetterNames: android.location.GnssMeasurement#setCodeType(String):
+
+GetterSetterNames: android.location.GnssMeasurement#setCorrelationVectors(java.util.Collection<android.location.CorrelationVector>):
GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasNanos(double):
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index b1890b0..f7f42a6 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -98,11 +98,15 @@
public abstract void killForegroundAppsForUser(@UserIdInt int userId);
/**
- * Sets how long a {@link PendingIntent} can be temporarily whitelist to by bypass restrictions
- * such as Power Save mode.
+ * Sets how long a {@link PendingIntent} can be temporarily whitelist to by bypass restrictions
+ * such as Power Save mode.
+ * @param target
+ * @param whitelistToken
+ * @param duration temp allowlist duration in milliseconds.
+ * @param type temp allowlist type defined at {@link BroadcastOptions.TempAllowListType}
*/
public abstract void setPendingIntentWhitelistDuration(IIntentSender target,
- IBinder whitelistToken, long duration);
+ IBinder whitelistToken, long duration, int type);
/**
* Returns the flags set for a {@link PendingIntent}.
@@ -318,8 +322,17 @@
public abstract boolean isBooted();
public abstract void finishBooting();
+ /**
+ * Temp allowlist a UID for PendingIntent.
+ * @param callerPid the PID that sent the PendingIntent.
+ * @param callerUid the UID that sent the PendingIntent.
+ * @param targetUid the UID that is been temp allowlisted.
+ * @param duration temp allowlist duration in milliseconds.
+ * @param type temp allowlist type defined at {@link BroadcastOptions.TempAllowListType}
+ * @param tag
+ */
public abstract void tempWhitelistForPendingIntent(int callerPid, int callerUid, int targetUid,
- long duration, String tag);
+ long duration, int type, String tag);
public abstract int broadcastIntentInPackage(String packageName, @Nullable String featureId,
int uid, int realCallingUid, int realCallingPid, Intent intent, String resolvedType,
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index f541e1a..d0d5df9 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -54,6 +54,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
+import android.window.IRemoteTransition;
import android.window.WindowContainerToken;
import java.lang.annotation.Retention;
@@ -298,6 +299,8 @@
private static final String KEY_SPECS_FUTURE = "android:activity.specsFuture";
private static final String KEY_REMOTE_ANIMATION_ADAPTER
= "android:activity.remoteAnimationAdapter";
+ private static final String KEY_REMOTE_TRANSITION =
+ "android:activity.remoteTransition";
/**
* @see #setLaunchCookie
@@ -380,6 +383,7 @@
private IAppTransitionAnimationSpecsFuture mSpecsFuture;
private RemoteAnimationAdapter mRemoteAnimationAdapter;
private IBinder mLaunchCookie;
+ private IRemoteTransition mRemoteTransition;
/**
* Create an ActivityOptions specifying a custom animation to run when
@@ -959,6 +963,21 @@
return opts;
}
+ /**
+ * Create an {@link ActivityOptions} instance that lets the application control the entire
+ * animation using a {@link RemoteAnimationAdapter}.
+ * @hide
+ */
+ @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
+ public static ActivityOptions makeRemoteAnimation(RemoteAnimationAdapter remoteAnimationAdapter,
+ IRemoteTransition remoteTransition) {
+ final ActivityOptions opts = new ActivityOptions();
+ opts.mRemoteAnimationAdapter = remoteAnimationAdapter;
+ opts.mAnimationType = ANIM_REMOTE_ANIMATION;
+ opts.mRemoteTransition = remoteTransition;
+ return opts;
+ }
+
/** @hide */
public boolean getLaunchTaskBehind() {
return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
@@ -1064,6 +1083,8 @@
}
mRemoteAnimationAdapter = opts.getParcelable(KEY_REMOTE_ANIMATION_ADAPTER);
mLaunchCookie = opts.getBinder(KEY_LAUNCH_COOKIE);
+ mRemoteTransition = IRemoteTransition.Stub.asInterface(opts.getBinder(
+ KEY_REMOTE_TRANSITION));
}
/**
@@ -1223,6 +1244,11 @@
}
/** @hide */
+ public IRemoteTransition getRemoteTransition() {
+ return mRemoteTransition;
+ }
+
+ /** @hide */
public static ActivityOptions fromBundle(Bundle bOptions) {
return bOptions != null ? new ActivityOptions(bOptions) : null;
}
@@ -1724,6 +1750,9 @@
if (mLaunchCookie != null) {
b.putBinder(KEY_LAUNCH_COOKIE, mLaunchCookie);
}
+ if (mRemoteTransition != null) {
+ b.putBinder(KEY_REMOTE_TRANSITION, mRemoteTransition.asBinder());
+ }
return b;
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index dd016a2..fe13fd4 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -31,7 +31,6 @@
import android.app.job.JobSchedulerFrameworkInitializer;
import android.app.people.PeopleManager;
import android.app.prediction.AppPredictionManager;
-import android.app.role.RoleControllerManager;
import android.app.role.RoleManager;
import android.app.search.SearchUiManager;
import android.app.slice.SliceManager;
@@ -1315,14 +1314,6 @@
return new RoleManager(ctx.getOuterContext());
}});
- registerService(Context.ROLE_CONTROLLER_SERVICE, RoleControllerManager.class,
- new CachedServiceFetcher<RoleControllerManager>() {
- @Override
- public RoleControllerManager createService(ContextImpl ctx)
- throws ServiceNotFoundException {
- return new RoleControllerManager(ctx.getOuterContext());
- }});
-
registerService(Context.DYNAMIC_SYSTEM_SERVICE, DynamicSystemManager.class,
new CachedServiceFetcher<DynamicSystemManager>() {
@Override
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index ab0901d..a866082 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -605,6 +605,7 @@
* or {@code null} if no system wallpaper exists or if the calling application
* is not able to access the wallpaper.
*/
+ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
public Drawable getDrawable() {
final ColorManagementProxy cmProxy = getColorManagementProxy();
Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, cmProxy);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 71af5e3..54e1ac43 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2536,6 +2536,22 @@
"android.app.extra.PROVISIONING_SUPPORTED_MODES";
/**
+ * A boolean extra which determines whether to skip the ownership disclaimer screen during the
+ * provisioning flow. The default value is {@code false}.
+ *
+ * If the value is {@code true}, it is the responsibility of the provisioning initiator to
+ * show the relevant disclaimer.
+ *
+ * <p>This extra is only respected when provided alongside the {@link
+ * #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE} intent action.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_PROVISIONING_SKIP_OWNERSHIP_DISCLAIMER =
+ "android.app.extra.PROVISIONING_SKIP_OWNERSHIP_DISCLAIMER";
+
+ /**
* An {@link ArrayList} of {@link Integer} extra specifying the allowed provisioning modes.
* <p>This extra will be passed to the admin app's {@link #ACTION_GET_PROVISIONING_MODE}
* activity, whose result intent must contain {@link #EXTRA_PROVISIONING_MODE} set to one of
@@ -2564,6 +2580,30 @@
public static final int PROVISIONING_MODE_MANAGED_PROFILE_ON_PERSONAL_DEVICE = 3;
/**
+ * A {@code boolean} flag that indicates whether the provisioning flow should return before
+ * starting the admin app's {@link #ACTION_ADMIN_POLICY_COMPLIANCE} handler. The default value
+ * is {@code true}.
+ *
+ * <p>If this extra is set to {@code true}, then when the provisioning flow returns back to the
+ * provisioning initiator, provisioning will not be complete. The provisioning initiator can
+ * use this opportunity to do its own preparatory steps prior to the launch of the admin app's
+ * {@link #ACTION_ADMIN_POLICY_COMPLIANCE} handler. It is the responsibility of the
+ * provisioning initiator to ensure that the provisioning flow is then resumed and completed.
+ *
+ * <p>If this extra is set to {@code false}, then when the provisioning flow returns back to
+ * the provisioning initiator, provisioning will be complete. Note that device owner
+ * provisioning is not currently supported for the this scenario.
+ *
+ * <p>This extra is only respected when provided alongside the {@link
+ * #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE} intent action.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE =
+ "android.app.extra.PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE";
+
+ /**
* Activity action: Starts the administrator to show policy compliance for the provisioning.
* This action is used any time that the administrator has an opportunity to show policy
* compliance before the end of setup wizard. This could happen as part of the admin-integrated
@@ -2690,6 +2730,60 @@
/** @hide */
@TestApi
public static final int OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES = 22;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_CLEAR_APPLICATION_USER_DATA = 23;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_INSTALL_CA_CERT = 24;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_INSTALL_KEY_PAIR = 25;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_INSTALL_SYSTEM_UPDATE = 26;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_REMOVE_ACTIVE_ADMIN = 27;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_REMOVE_KEY_PAIR = 28;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_REQUEST_BUGREPORT = 29;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_ALWAYS_ON_VPN_PACKAGE = 30;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_CAMERA_DISABLED = 31;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_FACTORY_RESET_PROTECTION_POLICY = 32;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_GLOBAL_PRIVATE_DNS = 33;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_LOGOUT_ENABLED = 34;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_MASTER_VOLUME_MUTED = 35;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_OVERRIDE_APNS_ENABLED = 36;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_PERMISSION_GRANT_STATE = 37;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_PERMISSION_POLICY = 38;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_RESTRICTIONS_PROVIDER = 39;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_UNINSTALL_CA_CERT = 40;
private static final String PREFIX_OPERATION = "OPERATION_";
@@ -2716,7 +2810,25 @@
OPERATION_SET_LOCK_TASK_PACKAGES,
OPERATION_SET_PACKAGES_SUSPENDED,
OPERATION_SET_TRUST_AGENT_CONFIGURATION,
- OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES
+ OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES,
+ OPERATION_CLEAR_APPLICATION_USER_DATA,
+ OPERATION_INSTALL_CA_CERT,
+ OPERATION_INSTALL_KEY_PAIR,
+ OPERATION_INSTALL_SYSTEM_UPDATE,
+ OPERATION_REMOVE_ACTIVE_ADMIN,
+ OPERATION_REMOVE_KEY_PAIR,
+ OPERATION_REQUEST_BUGREPORT,
+ OPERATION_SET_ALWAYS_ON_VPN_PACKAGE,
+ OPERATION_SET_CAMERA_DISABLED,
+ OPERATION_SET_FACTORY_RESET_PROTECTION_POLICY,
+ OPERATION_SET_GLOBAL_PRIVATE_DNS,
+ OPERATION_SET_LOGOUT_ENABLED,
+ OPERATION_SET_MASTER_VOLUME_MUTED,
+ OPERATION_SET_OVERRIDE_APNS_ENABLED,
+ OPERATION_SET_PERMISSION_GRANT_STATE,
+ OPERATION_SET_PERMISSION_POLICY,
+ OPERATION_SET_RESTRICTIONS_PROVIDER,
+ OPERATION_UNINSTALL_CA_CERT
})
@Retention(RetentionPolicy.SOURCE)
public static @interface DevicePolicyOperation {
@@ -9823,7 +9935,7 @@
* Designates a specific service component as the provider for making permission requests of a
* local or remote administrator of the user.
* <p/>
- * Only a profile owner can designate the restrictions provider.
+ * Only a device owner or profile owner can designate the restrictions provider.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param provider The component name of the service that implements
diff --git a/core/java/android/app/role/RoleControllerManager.java b/core/java/android/app/role/RoleControllerManager.java
index 8dde2c5..ba1f612 100644
--- a/core/java/android/app/role/RoleControllerManager.java
+++ b/core/java/android/app/role/RoleControllerManager.java
@@ -20,8 +20,6 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
-import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.app.ActivityThread;
import android.content.ComponentName;
import android.content.Context;
@@ -48,8 +46,6 @@
*
* @hide
*/
-@SystemService(Context.ROLE_CONTROLLER_SERVICE)
-@TestApi
public class RoleControllerManager {
private static final String LOG_TAG = RoleControllerManager.class.getSimpleName();
@@ -199,32 +195,11 @@
}
/**
- * @see RoleControllerService#onIsApplicationQualifiedForRole(String, String)
- *
- * @deprecated Use {@link #isApplicationVisibleForRole(String, String, Executor, Consumer)}
- * instead.
- *
- * @hide
- */
- @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
- public void isApplicationQualifiedForRole(@NonNull String roleName, @NonNull String packageName,
- @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
- AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> {
- AndroidFuture<Bundle> future = new AndroidFuture<>();
- service.isApplicationQualifiedForRole(roleName, packageName,
- new RemoteCallback(future::complete));
- return future;
- });
- propagateCallback(operation, "isApplicationQualifiedForRole", executor, callback);
- }
-
- /**
* @see RoleControllerService#onIsApplicationVisibleForRole(String, String)
*
* @hide
*/
@RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
- @TestApi
public void isApplicationVisibleForRole(@NonNull String roleName, @NonNull String packageName,
@NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> {
@@ -242,7 +217,6 @@
* @hide
*/
@RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
- @TestApi
public void isRoleVisible(@NonNull String roleName,
@NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> {
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index 8b2e07b..0fcf44d 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -174,6 +174,9 @@
@NonNull
private final Object mListenersLock = new Object();
+ @NonNull
+ private final RoleControllerManager mRoleControllerManager;
+
/**
* @hide
*/
@@ -181,6 +184,7 @@
mContext = context;
mService = IRoleManager.Stub.asInterface(ServiceManager.getServiceOrThrow(
Context.ROLE_SERVICE));
+ mRoleControllerManager = new RoleControllerManager(context);
}
/**
@@ -676,6 +680,44 @@
}
}
+ /**
+ * Check whether a role should be visible to user.
+ *
+ * @param roleName name of the role to check for
+ * @param executor the executor to execute callback on
+ * @param callback the callback to receive whether the role should be visible to user
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
+ @TestApi
+ public void isRoleVisible(@NonNull String roleName,
+ @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+ mRoleControllerManager.isRoleVisible(roleName, executor, callback);
+ }
+
+ /**
+ * Check whether an application is visible for a role.
+ *
+ * While an application can be qualified for a role, it can still stay hidden from user (thus
+ * not visible). If an application is visible for a role, we may show things related to the role
+ * for it, e.g. showing an entry pointing to the role settings in its application info page.
+ *
+ * @param roleName the name of the role to check for
+ * @param packageName the package name of the application to check for
+ * @param executor the executor to execute callback on
+ * @param callback the callback to receive whether the application is visible for the role
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
+ @TestApi
+ public void isApplicationVisibleForRole(@NonNull String roleName, @NonNull String packageName,
+ @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+ mRoleControllerManager.isApplicationVisibleForRole(roleName, packageName, executor,
+ callback);
+ }
+
private static class OnRoleHoldersChangedListenerDelegate
extends IOnRoleHoldersChangedListener.Stub {
diff --git a/core/java/android/app/search/OWNERS b/core/java/android/app/search/OWNERS
new file mode 100644
index 0000000..92835c2
--- /dev/null
+++ b/core/java/android/app/search/OWNERS
@@ -0,0 +1,2 @@
+hyunyoungs@google.com
+sfufa@google.com
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5ccceca..eb70ae1 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4833,16 +4833,6 @@
public static final String ROLE_SERVICE = "role";
/**
- * Official published name of the (internal) role controller service.
- *
- * @see #getSystemService(String)
- * @see android.app.role.RoleControllerService
- *
- * @hide
- */
- public static final String ROLE_CONTROLLER_SERVICE = "role_controller";
-
- /**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.hardware.camera2.CameraManager} for interacting with
* camera devices.
@@ -5096,9 +5086,7 @@
* Service to capture a bugreport.
* @see #getSystemService(String)
* @see android.os.BugreportManager
- * @hide
*/
- @SystemApi
public static final String BUGREPORT_SERVICE = "bugreport";
/**
diff --git a/core/java/android/content/pm/OWNERS b/core/java/android/content/pm/OWNERS
index fd32efc..f0def805 100644
--- a/core/java/android/content/pm/OWNERS
+++ b/core/java/android/content/pm/OWNERS
@@ -6,5 +6,6 @@
per-file PackageParser.java = chiuwinson@google.com
per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS
+per-file AppSearchPerson.java = file:/core/java/android/content/pm/SHORTCUT_OWNERS
per-file *Launcher* = file:/core/java/android/content/pm/LAUNCHER_OWNERS
per-file UserInfo* = file:/MULTIUSER_OWNERS
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 17c4d25..03d4d5e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3513,6 +3513,17 @@
public static final String FEATURE_TUNER = "android.hardware.tv.tuner";
/**
+ * Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports a enabling/disabling sensor privacy for
+ * camera. When sensory privacy for the camera is enabled no camera data is send to clients,
+ * e.g. the view finder in a camera app would appear blank.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle";
+
+ /**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has
* the necessary changes to support app enumeration.
*
diff --git a/core/java/android/hardware/CameraStreamStats.java b/core/java/android/hardware/CameraStreamStats.java
index ae801b6..41d1e25 100644
--- a/core/java/android/hardware/CameraStreamStats.java
+++ b/core/java/android/hardware/CameraStreamStats.java
@@ -19,7 +19,6 @@
import android.os.Parcelable;
import android.util.Log;
-import java.util.ArrayList;
/**
* The camera stream statistics used for passing camera stream information from
* camera service to camera service proxy.
@@ -30,6 +29,8 @@
* @hide
*/
public class CameraStreamStats implements Parcelable {
+ public static final int HISTOGRAM_TYPE_UNKNOWN = 0;
+ public static final int HISTOGRAM_TYPE_CAPTURE_LATENCY = 1;
private int mWidth;
private int mHeight;
@@ -41,6 +42,9 @@
private int mStartLatencyMs;
private int mMaxHalBuffers;
private int mMaxAppBuffers;
+ private int mHistogramType;
+ private float[] mHistogramBins;
+ private long[] mHistogramCounts;
private static final String TAG = "CameraStreamStats";
@@ -55,6 +59,7 @@
mStartLatencyMs = 0;
mMaxHalBuffers = 0;
mMaxAppBuffers = 0;
+ mHistogramType = HISTOGRAM_TYPE_UNKNOWN;
}
public CameraStreamStats(int width, int height, int format,
@@ -70,6 +75,7 @@
mStartLatencyMs = startLatencyMs;
mMaxHalBuffers = maxHalBuffers;
mMaxAppBuffers = maxAppBuffers;
+ mHistogramType = HISTOGRAM_TYPE_UNKNOWN;
}
public static final @android.annotation.NonNull Parcelable.Creator<CameraStreamStats> CREATOR =
@@ -112,6 +118,9 @@
dest.writeInt(mStartLatencyMs);
dest.writeInt(mMaxHalBuffers);
dest.writeInt(mMaxAppBuffers);
+ dest.writeInt(mHistogramType);
+ dest.writeFloatArray(mHistogramBins);
+ dest.writeLongArray(mHistogramCounts);
}
public void readFromParcel(Parcel in) {
@@ -125,6 +134,9 @@
mStartLatencyMs = in.readInt();
mMaxHalBuffers = in.readInt();
mMaxAppBuffers = in.readInt();
+ mHistogramType = in.readInt();
+ mHistogramBins = in.createFloatArray();
+ mHistogramCounts = in.createLongArray();
}
public int getWidth() {
@@ -166,4 +178,16 @@
public int getMaxAppBuffers() {
return mMaxAppBuffers;
}
+
+ public int getHistogramType() {
+ return mHistogramType;
+ }
+
+ public float[] getHistogramBins() {
+ return mHistogramBins;
+ }
+
+ public long[] getHistogramCounts() {
+ return mHistogramCounts;
+ }
}
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index f7c4c2c..ec6c233 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -881,7 +881,11 @@
}
}
- static int getMaxLengthValuesArray(Sensor sensor, int sdkLevel) {
+ /**
+ * Return sensor's maximum length of values array
+ * @hide
+ */
+ public static int getMaxLengthValuesArray(Sensor sensor, int sdkLevel) {
// RotationVector length has changed to 3 to 5 for API level 18
// Set it to 3 for backward compatibility.
if (sensor.mType == Sensor.TYPE_ROTATION_VECTOR
diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java
index 8497525..e165ad6 100644
--- a/core/java/android/hardware/SensorPrivacyManager.java
+++ b/core/java/android/hardware/SensorPrivacyManager.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
@@ -40,14 +41,19 @@
*
* @hide
*/
+@TestApi
@SystemService(Context.SENSOR_PRIVACY_SERVICE)
public final class SensorPrivacyManager {
- /** Microphone */
+ /** Microphone
+ * @hide */
+ @TestApi
public static final int INDIVIDUAL_SENSOR_MICROPHONE =
SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
- /** Camera */
+ /** Camera
+ * @hide */
+ @TestApi
public static final int INDIVIDUAL_SENSOR_CAMERA =
SensorPrivacyIndividualEnabledSensorProto.CAMERA;
@@ -66,6 +72,8 @@
* A class implementing this interface can register with the {@link
* android.hardware.SensorPrivacyManager} to receive notification when the sensor privacy
* state changes.
+ *
+ * @hide
*/
public interface OnSensorPrivacyChangedListener {
/**
@@ -101,6 +109,8 @@
/**
* Returns the single instance of the SensorPrivacyManager.
+ *
+ * @hide
*/
public static SensorPrivacyManager getInstance(Context context) {
synchronized (sInstanceLock) {
@@ -121,6 +131,8 @@
* Sets sensor privacy to the specified state.
*
* @param enable the state to which sensor privacy should be set.
+ *
+ * @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void setSensorPrivacy(boolean enable) {
@@ -137,6 +149,8 @@
*
* @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
* privacy changes.
+ *
+ * @hide
*/
public void addSensorPrivacyListener(final OnSensorPrivacyChangedListener listener) {
synchronized (mListeners) {
@@ -166,6 +180,8 @@
* @param sensor the sensor to listen to changes to
* @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
* privacy changes.
+ *
+ * @hide
*/
public void addSensorPrivacyListener(@IndividualSensor int sensor,
final OnSensorPrivacyChangedListener listener) {
@@ -196,6 +212,8 @@
*
* @param listener the OnSensorPrivacyChangedListener to be unregistered from notifications when
* sensor privacy changes.
+ *
+ * @hide
*/
public void removeSensorPrivacyListener(OnSensorPrivacyChangedListener listener) {
synchronized (mListeners) {
@@ -215,6 +233,8 @@
* Returns whether sensor privacy is currently enabled.
*
* @return true if sensor privacy is currently enabled, false otherwise.
+ *
+ * @hide
*/
public boolean isSensorPrivacyEnabled() {
try {
@@ -228,7 +248,10 @@
* Returns whether sensor privacy is currently enabled for a specific sensor.
*
* @return true if sensor privacy is currently enabled, false otherwise.
+ *
+ * @hide
*/
+ @TestApi
public boolean isIndividualSensorPrivacyEnabled(@IndividualSensor int sensor) {
try {
return mService.isIndividualSensorPrivacyEnabled(mContext.getUserId(), sensor);
@@ -242,7 +265,10 @@
*
* @param sensor the sensor which to change the state for
* @param enable the state to which sensor privacy should be set.
+ *
+ * @hide
*/
+ @TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void setIndividualSensorPrivacy(@IndividualSensor int sensor,
boolean enable) {
@@ -259,7 +285,10 @@
*
* @param sensor the sensor which to change the state for
* @param enable the state to which sensor privacy should be set.
+ *
+ * @hide
*/
+ @TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void setIndividualSensorPrivacyForProfileGroup(@IndividualSensor int sensor,
boolean enable) {
diff --git a/core/java/android/hardware/input/InputDeviceSensorManager.java b/core/java/android/hardware/input/InputDeviceSensorManager.java
index 56c2cdd..89db857 100644
--- a/core/java/android/hardware/input/InputDeviceSensorManager.java
+++ b/core/java/android/hardware/input/InputDeviceSensorManager.java
@@ -25,6 +25,7 @@
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.TriggerEventListener;
+import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -32,6 +33,7 @@
import android.os.Message;
import android.os.RemoteException;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.InputDevice;
import com.android.internal.annotations.GuardedBy;
@@ -65,8 +67,8 @@
@GuardedBy("mInputSensorLock")
private final ArrayList<InputSensorEventListenerDelegate> mInputSensorEventListeners =
new ArrayList<InputSensorEventListenerDelegate>();
- private HandlerThread mSensorThread = null;
- private Handler mSensorHandler = null;
+ private final HandlerThread mSensorThread;
+ private final Handler mSensorHandler;
public InputDeviceSensorManager(InputManager inputManager) {
mInputManager = inputManager;
@@ -125,9 +127,7 @@
@Override
public void onInputDeviceChanged(int deviceId) {
synchronized (mInputSensorLock) {
- if (mSensors.containsKey(deviceId)) {
- mSensors.remove(deviceId);
- }
+ mSensors.remove(deviceId);
updateInputDeviceSensorInfoLocked(deviceId);
}
}
@@ -196,16 +196,21 @@
+ " timestamp=" + timestamp + " sensorType=" + sensorType);
}
synchronized (mInputSensorLock) {
- SensorEvent event = createSensorEvent(
- InputDevice.getDevice(deviceId), sensorType, accuracy, timestamp, values);
- if (event == null) {
- Slog.wtf(TAG, "Failed to create SensorEvent.");
- return;
- }
+ Sensor sensor = getInputDeviceSensorLocked(deviceId, sensorType);
for (int i = 0; i < mInputSensorEventListeners.size(); i++) {
InputSensorEventListenerDelegate listener =
mInputSensorEventListeners.get(i);
if (listener.hasSensorRegistered(deviceId, sensorType)) {
+ SensorEvent event = listener.getSensorEvent(sensor);
+ if (event == null) {
+ Slog.wtf(TAG, "Failed to get SensorEvent.");
+ return;
+ }
+ event.sensor = sensor;
+ event.accuracy = accuracy;
+ event.timestamp = timestamp;
+ System.arraycopy(values, 0, event.values, 0, event.values.length);
+ // Call listener for sensor changed
listener.sendSensorChanged(event);
}
}
@@ -249,15 +254,19 @@
private final SensorEventListener mListener;
private final int mDelayUs;
private final int mMaxBatchReportLatencyUs;
+ // List of sensors being listened to
private List<Sensor> mSensors = new ArrayList<Sensor>();
+ // Sensor event array by sensor type, preallocate sensor events for each sensor of listener
+ // to avoid allocation and garbage collection for each listener callback.
+ private final SparseArray<SensorEvent> mSensorEvents = new SparseArray<SensorEvent>();
InputSensorEventListenerDelegate(SensorEventListener listener, Sensor sensor,
int delayUs, int maxBatchReportLatencyUs, Handler handler) {
super(handler != null ? handler.getLooper() : Looper.myLooper());
mListener = listener;
- mSensors.add(sensor);
mDelayUs = delayUs;
mMaxBatchReportLatencyUs = maxBatchReportLatencyUs;
+ addSensor(sensor);
}
public List<Sensor> getSensors() {
@@ -276,10 +285,12 @@
// and the sensor list is cleared.
if (sensor == null) {
mSensors.clear();
+ mSensorEvents.clear();
}
for (Sensor s : mSensors) {
if (sensorEquals(s, sensor)) {
mSensors.remove(sensor);
+ mSensorEvents.remove(sensor.getType());
}
}
}
@@ -295,6 +306,10 @@
}
}
mSensors.add(sensor);
+ final int vecLength = sensor.getMaxLengthValuesArray(sensor, Build.VERSION.SDK_INT);
+ SensorEvent event = new SensorEvent(sensor, SensorManager.SENSOR_STATUS_NO_CONTACT,
+ 0 /* timestamp */, new float[vecLength]);
+ mSensorEvents.put(sensor.getType(), event);
}
/**
@@ -320,6 +335,13 @@
}
/**
+ * Get SensorEvent object for input device, with specified sensor.
+ */
+ private SensorEvent getSensorEvent(@NonNull Sensor sensor) {
+ return mSensorEvents.get(sensor.getType());
+ }
+
+ /**
* Send sensor changed message
*/
public void sendSensorChanged(SensorEvent event) {
@@ -360,26 +382,6 @@
}
/**
- * Create SensorEvent object for input device, with specified device ID, sensor Type,
- * sensor event timestamp, accuracy, and sensor values.
- */
- private SensorEvent createSensorEvent(InputDevice inputDevice, int sensorType, int accuracy,
- long timestamp, float[] values) {
- synchronized (mInputSensorLock) {
- Sensor sensor = getInputDeviceSensorLocked(inputDevice.getId(), sensorType);
- if (sensor == null) {
- Slog.wtf(TAG, "Can't get sensor type " + sensorType + " for input device "
- + inputDevice);
- }
- SensorEvent event = new SensorEvent(sensor, accuracy, timestamp, values);
- if (event == null) {
- Slog.wtf(TAG, "Failed to create SensorEvent.");
- }
- return event;
- }
- }
-
- /**
* Return the default sensor object for input device, for specific sensor type.
*/
private Sensor getSensorForInputDevice(int deviceId, int type) {
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index c029dea..cad0db2 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -160,7 +160,7 @@
/** @hide */
public static final int FOREGROUND_THRESHOLD_STATE =
- ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
/**
* {@link Intent} extra that indicates which {@link NetworkTemplate} rule it
diff --git a/core/java/android/net/vcn/VcnTransportInfo.java b/core/java/android/net/vcn/VcnTransportInfo.java
new file mode 100644
index 0000000..4d8cf91
--- /dev/null
+++ b/core/java/android/net/vcn/VcnTransportInfo.java
@@ -0,0 +1,125 @@
+/*
+ * 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.vcn;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.TransportInfo;
+import android.net.wifi.WifiInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.SubscriptionManager;
+
+import java.util.Objects;
+
+/**
+ * VcnTransportInfo contains information about the VCN's underlying transports for SysUi.
+ *
+ * <p>Presence of this class in the NetworkCapabilities.TransportInfo implies that the network is a
+ * VCN.
+ *
+ * <p>VcnTransportInfo must exist on top of either an underlying Wifi or Cellular Network. If the
+ * underlying Network is WiFi, the subId will be {@link
+ * SubscriptionManager#INVALID_SUBSCRIPTION_ID}. If the underlying Network is Cellular, the WifiInfo
+ * will be {@code null}.
+ *
+ * @hide
+ */
+public class VcnTransportInfo implements TransportInfo, Parcelable {
+ @Nullable private final WifiInfo mWifiInfo;
+ private final int mSubId;
+
+ public VcnTransportInfo(@NonNull WifiInfo wifiInfo) {
+ this(wifiInfo, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ }
+
+ public VcnTransportInfo(int subId) {
+ this(null /* wifiInfo */, subId);
+ }
+
+ private VcnTransportInfo(@Nullable WifiInfo wifiInfo, int subId) {
+ if (wifiInfo == null && subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ throw new IllegalArgumentException(
+ "VcnTransportInfo requires either non-null WifiInfo or valid subId");
+ }
+
+ mWifiInfo = wifiInfo;
+ mSubId = subId;
+ }
+
+ /**
+ * Get the {@link WifiInfo} for this VcnTransportInfo.
+ *
+ * <p>If the underlying Network for the associated VCN is Cellular, returns null.
+ *
+ * @return the WifiInfo if there is an underlying WiFi connection, else null.
+ */
+ @Nullable
+ public WifiInfo getWifiInfo() {
+ return mWifiInfo;
+ }
+
+ /**
+ * Get the subId for the VCN Network associated with this VcnTransportInfo.
+ *
+ * <p>If the underlying Network for the associated VCN is WiFi, returns {@link
+ * SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
+ *
+ * @return the Subscription ID if a cellular underlying Network is present, else {@link
+ * android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID}.
+ */
+ public int getSubId() {
+ return mSubId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mWifiInfo, mSubId);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof VcnTransportInfo)) return false;
+ final VcnTransportInfo that = (VcnTransportInfo) o;
+
+ return Objects.equals(mWifiInfo, that.mWifiInfo) && mSubId == that.mSubId;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {}
+
+ /** Implement the Parcelable interface */
+ public static final @NonNull Creator<VcnTransportInfo> CREATOR =
+ new Creator<VcnTransportInfo>() {
+ public VcnTransportInfo createFromParcel(Parcel in) {
+ // return null instead of a default VcnTransportInfo to avoid leaking
+ // information about this being a VCN Network (instead of macro cellular, etc)
+ return null;
+ }
+
+ public VcnTransportInfo[] newArray(int size) {
+ return new VcnTransportInfo[size];
+ }
+ };
+}
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 33736d3..305c686 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -22,6 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressAutoDoc;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.app.ActivityManager;
@@ -40,12 +41,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
-/**
- * Class that provides a privileged API to capture and consume bugreports.
- *
- * @hide
- */
-@SystemApi
+/** Class that provides a privileged API to capture and consume bugreports. */
@SystemService(Context.BUGREPORT_SERVICE)
public final class BugreportManager {
@@ -60,28 +56,30 @@
mBinder = binder;
}
- /**
- * An interface describing the callback for bugreport progress and status.
- */
+ /** An interface describing the callback for bugreport progress and status. */
public abstract static class BugreportCallback {
- /** @hide */
+ /**
+ * Possible error codes taking a bugreport can encounter.
+ *
+ * @hide
+ */
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "BUGREPORT_ERROR_" }, value = {
- BUGREPORT_ERROR_INVALID_INPUT,
- BUGREPORT_ERROR_RUNTIME,
- BUGREPORT_ERROR_USER_DENIED_CONSENT,
- BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT,
- BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS
- })
-
- /** Possible error codes taking a bugreport can encounter */
+ @IntDef(
+ prefix = {"BUGREPORT_ERROR_"},
+ value = {
+ BUGREPORT_ERROR_INVALID_INPUT,
+ BUGREPORT_ERROR_RUNTIME,
+ BUGREPORT_ERROR_USER_DENIED_CONSENT,
+ BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT,
+ BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS
+ })
public @interface BugreportErrorCode {}
/** The input options were invalid */
public static final int BUGREPORT_ERROR_INVALID_INPUT =
IDumpstateListener.BUGREPORT_ERROR_INVALID_INPUT;
- /** A runtime error occured */
+ /** A runtime error occurred */
public static final int BUGREPORT_ERROR_RUNTIME =
IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR;
@@ -99,6 +97,7 @@
/**
* Called when there is a progress update.
+ *
* @param progress the progress in [0.0, 100.0]
*/
public void onProgress(@FloatRange(from = 0f, to = 100f) float progress) {}
@@ -113,14 +112,12 @@
* out, but the bugreport could be available in the internal directory of dumpstate for
* manual retrieval.
*
- * <p> If {@code BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS} is passed, then the
- * caller should try later, as only one bugreport can be in progress at a time.
+ * <p>If {@code BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS} is passed, then the caller
+ * should try later, as only one bugreport can be in progress at a time.
*/
public void onError(@BugreportErrorCode int errorCode) {}
- /**
- * Called when taking bugreport finishes successfully.
- */
+ /** Called when taking bugreport finishes successfully. */
public void onFinished() {}
/**
@@ -137,20 +134,23 @@
* seconds to return in the worst case. {@code callback} will receive progress and status
* updates.
*
- * <p>The bugreport artifacts will be copied over to the given file descriptors only if the
- * user consents to sharing with the calling app.
+ * <p>The bugreport artifacts will be copied over to the given file descriptors only if the user
+ * consents to sharing with the calling app.
*
* <p>{@link BugreportManager} takes ownership of {@code bugreportFd} and {@code screenshotFd}.
*
- * @param bugreportFd file to write the bugreport. This should be opened in write-only,
- * append mode.
- * @param screenshotFd file to write the screenshot, if necessary. This should be opened
- * in write-only, append mode.
+ * @param bugreportFd file to write the bugreport. This should be opened in write-only, append
+ * mode.
+ * @param screenshotFd file to write the screenshot, if necessary. This should be opened in
+ * write-only, append mode.
* @param params options that specify what kind of a bugreport should be taken
* @param callback callback for progress and status updates
+ * @hide
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.DUMP)
- public void startBugreport(@NonNull ParcelFileDescriptor bugreportFd,
+ public void startBugreport(
+ @NonNull ParcelFileDescriptor bugreportFd,
@Nullable ParcelFileDescriptor screenshotFd,
@NonNull BugreportParams params,
@NonNull @CallbackExecutor Executor executor,
@@ -164,17 +164,21 @@
boolean isScreenshotRequested = screenshotFd != null;
if (screenshotFd == null) {
// Binder needs a valid File Descriptor to be passed
- screenshotFd = ParcelFileDescriptor.open(new File("/dev/null"),
- ParcelFileDescriptor.MODE_READ_ONLY);
+ screenshotFd =
+ ParcelFileDescriptor.open(
+ new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
}
- DumpstateListener dsListener = new DumpstateListener(executor, callback,
- isScreenshotRequested);
+ DumpstateListener dsListener =
+ new DumpstateListener(executor, callback, isScreenshotRequested);
// Note: mBinder can get callingUid from the binder transaction.
- mBinder.startBugreport(-1 /* callingUid */,
+ mBinder.startBugreport(
+ -1 /* callingUid */,
mContext.getOpPackageName(),
bugreportFd.getFileDescriptor(),
screenshotFd.getFileDescriptor(),
- params.getMode(), dsListener, isScreenshotRequested);
+ params.getMode(),
+ dsListener,
+ isScreenshotRequested);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (FileNotFoundException e) {
@@ -189,14 +193,60 @@
}
/**
+ * Starts a connectivity bugreport.
+ *
+ * <p>The connectivity bugreport is a specialized version of bugreport that only includes
+ * information specifically for debugging connectivity-related issues (e.g. telephony, wi-fi,
+ * and IP networking issues). It is intended primarily for use by OEMs and network providers
+ * such as mobile network operators. In addition to generally excluding information that isn't
+ * targeted to connectivity debugging, this type of bugreport excludes PII and sensitive
+ * information that isn't strictly necessary for connectivity debugging.
+ *
+ * <p>The calling app MUST have a context-specific reason for requesting a connectivity
+ * bugreport, such as detecting a connectivity-related issue. This API SHALL NOT be used to
+ * perform random sampling from a fleet of public end-user devices.
+ *
+ * <p>Calling this API will cause the system to ask the user for consent every single time. The
+ * bugreport artifacts will be copied over to the given file descriptors only if the user
+ * consents to sharing with the calling app.
+ *
+ * <p>This starts a bugreport in the background. However the call itself can take several
+ * seconds to return in the worst case. {@code callback} will receive progress and status
+ * updates.
+ *
+ * <p>Requires that the calling app has carrier privileges (see {@link
+ * android.telephony.TelephonyManager#hasCarrierPrivileges}) on any active subscription.
+ *
+ * @param bugreportFd file to write the bugreport. This should be opened in write-only, append
+ * mode.
+ * @param callback callback for progress and status updates.
+ */
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ public void startConnectivityBugreport(
+ @NonNull ParcelFileDescriptor bugreportFd,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull BugreportCallback callback) {
+ startBugreport(
+ bugreportFd,
+ null /* screenshotFd */,
+ new BugreportParams(BugreportParams.BUGREPORT_MODE_TELEPHONY),
+ executor,
+ callback);
+ }
+
+ /**
* Cancels the currently running bugreport.
*
* <p>Apps are only able to cancel their own bugreports. App A cannot cancel a bugreport started
* by app B.
*
+ * <p>Requires permission: {@link android.Manifest.permission#DUMP} or that the calling app has
+ * carrier privileges (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on
+ * any active subscription.
+ *
* @throws SecurityException if trying to cancel another app's bugreport in progress
*/
- @RequiresPermission(android.Manifest.permission.DUMP)
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
public void cancelBugreport() {
try {
mBinder.cancelBugreport(-1 /* callingUid */, mContext.getOpPackageName());
@@ -209,23 +259,26 @@
* Requests a bugreport.
*
* <p>This requests the platform/system to take a bugreport and makes the final bugreport
- * available to the user. The user may choose to share it with another app, but the bugreport
- * is never given back directly to the app that requested it.
+ * available to the user. The user may choose to share it with another app, but the bugreport is
+ * never given back directly to the app that requested it.
*
- * @param params {@link BugreportParams} that specify what kind of a bugreport should
- * be taken, please note that not all kinds of bugreport allow for a
- * progress notification
- * @param shareTitle title on the final share notification
+ * @param params {@link BugreportParams} that specify what kind of a bugreport should be taken,
+ * please note that not all kinds of bugreport allow for a progress notification
+ * @param shareTitle title on the final share notification
* @param shareDescription description on the final share notification
+ * @hide
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.DUMP)
- public void requestBugreport(@NonNull BugreportParams params, @Nullable CharSequence shareTitle,
+ public void requestBugreport(
+ @NonNull BugreportParams params,
+ @Nullable CharSequence shareTitle,
@Nullable CharSequence shareDescription) {
try {
String title = shareTitle == null ? null : shareTitle.toString();
String description = shareDescription == null ? null : shareDescription.toString();
- ActivityManager.getService().requestBugReportWithDescription(title, description,
- params.getMode());
+ ActivityManager.getService()
+ .requestBugReportWithDescription(title, description, params.getMode());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -236,8 +289,8 @@
private final BugreportCallback mCallback;
private final boolean mIsScreenshotRequested;
- DumpstateListener(Executor executor, BugreportCallback callback,
- boolean isScreenshotRequested) {
+ DumpstateListener(
+ Executor executor, BugreportCallback callback, boolean isScreenshotRequested) {
mExecutor = executor;
mCallback = callback;
mIsScreenshotRequested = isScreenshotRequested;
@@ -247,9 +300,7 @@
public void onProgress(int progress) throws RemoteException {
final long identity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> {
- mCallback.onProgress(progress);
- });
+ mExecutor.execute(() -> mCallback.onProgress(progress));
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -259,9 +310,7 @@
public void onError(int errorCode) throws RemoteException {
final long identity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> {
- mCallback.onError(errorCode);
- });
+ mExecutor.execute(() -> mCallback.onError(errorCode));
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -271,9 +320,7 @@
public void onFinished() throws RemoteException {
final long identity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> {
- mCallback.onFinished();
- });
+ mExecutor.execute(() -> mCallback.onFinished());
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -288,20 +335,19 @@
Handler mainThreadHandler = new Handler(Looper.getMainLooper());
mainThreadHandler.post(
() -> {
- int message = success ? R.string.bugreport_screenshot_success_toast
- : R.string.bugreport_screenshot_failure_toast;
+ int message =
+ success
+ ? R.string.bugreport_screenshot_success_toast
+ : R.string.bugreport_screenshot_failure_toast;
Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
});
}
@Override
- public void onUiIntensiveBugreportDumpsFinished()
- throws RemoteException {
+ public void onUiIntensiveBugreportDumpsFinished() throws RemoteException {
final long identity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> {
- mCallback.onEarlyReportFinished();
- });
+ mExecutor.execute(() -> mCallback.onEarlyReportFinished());
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java
index e599776..c28b59b 100644
--- a/core/java/android/permission/PermissionUsageHelper.java
+++ b/core/java/android/permission/PermissionUsageHelper.java
@@ -183,8 +183,9 @@
}
Map<String, List<OpUsage>> rawUsages = getOpUsages(ops);
+ Set<List<PackageAttribution>> proxyChains = getProxyChains(rawUsages.get(MICROPHONE));
Map<PackageAttribution, CharSequence> packagesWithAttributionLabels =
- getTrustedAttributions(rawUsages.get(MICROPHONE));
+ getTrustedAttributions(rawUsages.get(MICROPHONE), proxyChains);
List<String> usedPermGroups = new ArrayList<>(rawUsages.keySet());
for (int permGroupNum = 0; permGroupNum < usedPermGroups.size(); permGroupNum++) {
@@ -192,10 +193,14 @@
String permGroup = usedPermGroups.get(permGroupNum);
Map<PackageAttribution, CharSequence> pkgAttrLabels = packagesWithAttributionLabels;
+ Set<List<PackageAttribution>> proxies = proxyChains;
if (!MICROPHONE.equals(permGroup)) {
pkgAttrLabels = new ArrayMap<>();
+ proxies = new ArraySet<>();
}
- removeDuplicates(rawUsages.get(permGroup), pkgAttrLabels.keySet());
+
+ List<OpUsage> permUsages = removeDuplicatesAndProxies(rawUsages.get(permGroup),
+ pkgAttrLabels.keySet(), proxies);
if (permGroup.equals(OPSTR_PHONE_CALL_MICROPHONE)) {
isPhone = true;
@@ -205,9 +210,8 @@
permGroup = CAMERA;
}
- int numUsages = rawUsages.get(permGroup).size();
- for (int usageNum = 0; usageNum < numUsages; usageNum++) {
- OpUsage usage = rawUsages.get(permGroup).get(usageNum);
+ for (int usageNum = 0; usageNum < permUsages.size(); usageNum++) {
+ OpUsage usage = permUsages.get(usageNum);
usages.add(new PermGroupUsage(usage.packageName, usage.uid, permGroup,
usage.lastAccessTime, usage.isRunning, isPhone,
packagesWithAttributionLabels.get(usage.toPackageAttr())));
@@ -278,7 +282,7 @@
AppOpsManager.OpEventProxyInfo proxy = attrOpEntry.getLastProxyInfo(opFlags);
if (proxy != null && proxy.getPackageName() != null) {
proxyUsage = new OpUsage(proxy.getPackageName(), proxy.getAttributionTag(),
- uid, lastAccessTime, isRunning, null);
+ proxy.getUid(), lastAccessTime, isRunning, null);
}
String permGroupName = getGroupForOp(op);
@@ -323,17 +327,15 @@
* trusted attribution label, if there is one
*/
private ArrayMap<PackageAttribution, CharSequence> getTrustedAttributions(
- List<OpUsage> usages) {
+ List<OpUsage> usages, Set<List<PackageAttribution>> proxyChains) {
ArrayMap<PackageAttribution, CharSequence> attributions = new ArrayMap<>();
if (usages == null) {
return attributions;
}
- Set<List<PackageAttribution>> proxyChains = getProxyChains(usages);
Map<PackageAttribution, CharSequence> trustedLabels =
getTrustedAttributionLabels(usages);
-
for (List<PackageAttribution> chain : proxyChains) {
// If this chain is empty, or has only one link, then do not show any special labels
if (chain.size() <= 1) {
@@ -413,37 +415,24 @@
* the chain has the previous one listed as a proxy usage.
*/
private Set<List<PackageAttribution>> getProxyChains(List<OpUsage> usages) {
- ArrayMap<PackageAttribution, List<PackageAttribution>> proxyChains = new ArrayMap<>();
+ if (usages == null) {
+ return new ArraySet<>();
+ }
+
+ ArrayMap<PackageAttribution, ArrayList<PackageAttribution>> proxyChains = new ArrayMap<>();
// map of usages that still need to be removed, or added to a chain
ArrayMap<PackageAttribution, OpUsage> remainingUsages = new ArrayMap<>();
// map of usage.proxy -> usage, telling us if a usage is a proxy
ArrayMap<PackageAttribution, PackageAttribution> proxies = new ArrayMap<>();
- for (int i = 0; i < remainingUsages.size(); i++) {
+ for (int i = 0; i < usages.size(); i++) {
OpUsage usage = usages.get(i);
remainingUsages.put(usage.toPackageAttr(), usage);
if (usage.proxy != null) {
proxies.put(usage.proxy.toPackageAttr(), usage.toPackageAttr());
}
}
- // find and remove all one-link chains (that is, all proxied apps whose proxy is not
- // included in the usage list), and apps that are neither proxy nor proxied.
- for (int usageNum = 0; usageNum < usages.size(); usageNum++) {
- OpUsage usage = usages.get(usageNum);
- PackageAttribution usageAttr = usage.toPackageAttr();
- if (usage.proxy == null) {
- if (!proxies.containsKey(usageAttr)) {
- remainingUsages.remove(usageAttr);
- }
- continue;
- }
- PackageAttribution proxyAttr = usage.proxy.toPackageAttr();
- if (!remainingUsages.containsKey(proxyAttr)) {
- remainingUsages.remove(usageAttr);
- }
- }
-
- // find all possible starting points for chains
+ // find all possible end points for chains
List<PackageAttribution> keys = new ArrayList<>(remainingUsages.keySet());
for (int usageNum = 0; usageNum < remainingUsages.size(); usageNum++) {
OpUsage usage = remainingUsages.get(keys.get(usageNum));
@@ -451,16 +440,21 @@
continue;
}
PackageAttribution usageAttr = usage.toPackageAttr();
- // If this usage has a proxy, but is not a proxy, it is the start of a chain.
+ // If this usage has a proxy, but is not a proxy, it is the end of a chain.
+ // If it has no proxy, and isn't a proxy, remove it.
if (!proxies.containsKey(usageAttr) && usage.proxy != null) {
- proxyChains.put(usageAttr, List.of(usageAttr));
+ ArrayList<PackageAttribution> proxyList = new ArrayList<>();
+ proxyList.add(usageAttr);
+ proxyChains.put(usageAttr, proxyList);
+ } else if (!proxies.containsKey(usageAttr) && usage.proxy == null) {
+ remainingUsages.remove(keys.get(usageNum));
}
}
- // assemble the chains
+ // assemble the chains in reverse order, then invert them
for (int numStart = 0; numStart < proxyChains.size(); numStart++) {
PackageAttribution currPackageAttr = proxyChains.keyAt(numStart);
- List<PackageAttribution> proxyChain = proxyChains.get(currPackageAttr);
+ ArrayList<PackageAttribution> proxyChain = proxyChains.get(currPackageAttr);
OpUsage currentUsage = remainingUsages.get(currPackageAttr);
if (currentUsage == null || proxyChain == null) {
continue;
@@ -484,6 +478,8 @@
proxyChain.add(currPackageAttr);
}
+ // invert the lists, so the element without a proxy is first on the list
+ Collections.reverse(proxyChain);
}
return new ArraySet<>(proxyChains.values());
@@ -590,7 +586,7 @@
CharSequence label = getAttributionLabel(usage);
if (trustedMap.get(usage.packageName).equals(label)) {
- toSetMap.put(usage.toPackageAttr(), label);
+ toSetMap.put(opUsage.toPackageAttr(), label);
}
}
@@ -619,34 +615,76 @@
}
}
- private void removeDuplicates(List<OpUsage> rawUsages,
- Set<PackageAttribution> specialAttributions) {
- List<OpUsage> toRemove = new ArrayList<>();
+ /**
+ * If we have multiple usages of a
+ * @param rawUsages The list of all usages that we wish to
+ * @param specialAttributions A set of all usages that have a special label
+ * @param proxies A list of proxy chains- all links but the last on the chain should be removed,
+ * if the last link has a special label
+ * @return A list of usages without duplicates or proxy usages.
+ */
+ private List<OpUsage> removeDuplicatesAndProxies(List<OpUsage> rawUsages,
+ Set<PackageAttribution> specialAttributions,
+ Set<List<PackageAttribution>> proxies) {
+ List<OpUsage> deDuped = new ArrayList<>();
if (rawUsages == null) {
- return;
+ return deDuped;
}
- for (int usageNum = 0; usageNum < rawUsages.size(); usageNum++) {
- PackageAttribution usageAttr = rawUsages.get(usageNum).toPackageAttr();
- // If this attribution has a special attribution, do not remove it
- if (specialAttributions.contains(usageAttr)) {
+ List<PackageAttribution> toRemoveProxies = new ArrayList<>();
+ for (List<PackageAttribution> proxyList: proxies) {
+ PackageAttribution lastLink = proxyList.get(proxyList.size() - 1);
+ if (!specialAttributions.contains(lastLink)) {
continue;
}
-
- // Search the rest of the list for apps with the same uid. If there is one, mark this
- // usage for removal.
- for (int otherUsageNum = usageNum + 1; otherUsageNum < rawUsages.size();
- otherUsageNum++) {
- if (rawUsages.get(otherUsageNum).uid == usageAttr.uid) {
- toRemove.add(rawUsages.get(usageNum));
- break;
+ for (int proxyNum = 0; proxyNum < proxyList.size(); proxyNum++) {
+ if (!proxyList.get(proxyNum).equals(lastLink)) {
+ toRemoveProxies.add(proxyList.get(proxyNum));
}
}
}
- for (int i = 0; i < toRemove.size(); i++) {
- rawUsages.remove(toRemove.get(i));
+ for (int usageNum = 0; usageNum < rawUsages.size(); usageNum++) {
+ OpUsage usage = rawUsages.get(usageNum);
+
+ // If this attribution has a special attribution, do not remove it
+ if (specialAttributions.contains(usage.toPackageAttr())) {
+ deDuped.add(usage);
+ }
+
+ // If this attribution is a proxy, remove it
+ if (toRemoveProxies.contains(usage.toPackageAttr())) {
+ continue;
+ }
+
+
+ // Search the rest of the list for usages with the same UID. If this is the most recent
+ // usage for that uid, keep it. Otherwise, remove it
+ boolean isMostRecentForUid = true;
+ for (int otherUsageNum = 0; otherUsageNum < rawUsages.size(); otherUsageNum++) {
+ OpUsage otherUsage = rawUsages.get(otherUsageNum);
+ if (otherUsage.uid == usage.uid) {
+ if (otherUsage.isRunning && !usage.isRunning) {
+ isMostRecentForUid = false;
+ } else if (usage.isRunning
+ && otherUsage.lastAccessTime >= usage.lastAccessTime) {
+ isMostRecentForUid = false;
+ } else if (otherUsage.lastAccessTime >= usage.lastAccessTime) {
+ isMostRecentForUid = false;
+ }
+
+ if (!isMostRecentForUid) {
+ break;
+ }
+ }
+ }
+
+ if (isMostRecentForUid) {
+ deDuped.add(usage);
+ }
}
+
+ return deDuped;
}
private boolean isUserSensitive(String packageName, UserHandle user, String op) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 9db7ca0..27ba72b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1018,6 +1018,20 @@
"android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
/**
+ * Activity Action: Show settings to manage all SIM profiles.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_MANAGE_ALL_SUBSCRIPTIONS_SETTINGS =
+ "android.settings.MANAGE_ALL_SUBSCRIPTIONS_SETTINGS";
+
+ /**
* Activity Action: Show screen for controlling which apps can draw on top of other apps.
* <p>
* In some cases, a matching Activity may not exist, so ensure you safeguard against this.
@@ -8440,14 +8454,6 @@
"emergency_gesture_sound_enabled";
/**
- * The default number to call in emergency gesture
- *
- * @hide
- */
- public static final String EMERGENCY_GESTURE_CALL_NUMBER =
- "emergency_gesture_call_number";
-
- /**
* Whether the camera launch gesture to double tap the power button when the screen is off
* should be disabled.
*
diff --git a/core/java/android/service/search/OWNERS b/core/java/android/service/search/OWNERS
new file mode 100644
index 0000000..92835c2
--- /dev/null
+++ b/core/java/android/service/search/OWNERS
@@ -0,0 +1,2 @@
+hyunyoungs@google.com
+sfufa@google.com
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index ac5d14e..258a72c 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -270,7 +270,7 @@
pw.print(" clipRect="); clipRect.printShortString(pw);
pw.print(" contentInsets="); contentInsets.printShortString(pw);
pw.print(" prefixOrderIndex="); pw.print(prefixOrderIndex);
- pw.print(" position="); position.dump(pw);
+ pw.print(" position="); printPoint(position, pw);
pw.print(" sourceContainerBounds="); sourceContainerBounds.printShortString(pw);
pw.print(" screenSpaceBounds="); screenSpaceBounds.printShortString(pw);
pw.print(" localBounds="); localBounds.printShortString(pw);
@@ -303,6 +303,10 @@
proto.end(token);
}
+ private static void printPoint(Point p, PrintWriter pw) {
+ pw.print("["); pw.print(p.x); pw.print(","); pw.print(p.y); pw.print("]");
+ }
+
public static final @android.annotation.NonNull Creator<RemoteAnimationTarget> CREATOR
= new Creator<RemoteAnimationTarget>() {
public RemoteAnimationTarget createFromParcel(Parcel in) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 4f7e841..45fa41b 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -663,24 +663,34 @@
}
/**
- * Message for taking fullscreen screenshot
+ * Invoke screenshot flow to capture a full-screen image.
* @hide
*/
int TAKE_SCREENSHOT_FULLSCREEN = 1;
/**
- * Message for taking screenshot of selected region.
+ * Invoke screenshot flow allowing the user to select a region.
* @hide
*/
int TAKE_SCREENSHOT_SELECTED_REGION = 2;
/**
- * Message for handling a screenshot flow with an image provided by the caller.
+ * Invoke screenshot flow with an image provided by the caller.
* @hide
*/
int TAKE_SCREENSHOT_PROVIDED_IMAGE = 3;
/**
+ * Enum listing the types of screenshot requests available.
+ *
+ * @hide
+ */
+ @IntDef({TAKE_SCREENSHOT_FULLSCREEN,
+ TAKE_SCREENSHOT_SELECTED_REGION,
+ TAKE_SCREENSHOT_PROVIDED_IMAGE})
+ @interface ScreenshotType {}
+
+ /**
* Enum listing the possible sources from which a screenshot was originated. Used for logging.
*
* @hide
diff --git a/core/java/android/view/textclassifier/OWNERS b/core/java/android/view/textclassifier/OWNERS
index ac80d9f..4bcdeea 100644
--- a/core/java/android/view/textclassifier/OWNERS
+++ b/core/java/android/view/textclassifier/OWNERS
@@ -6,3 +6,5 @@
svetoslavganov@google.com
augale@google.com
joannechung@google.com
+tonymak@google.com
+licha@google.com
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index e4de400..ed20d26 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -196,11 +196,6 @@
initImageView();
- // ImageView is not important by default, unless app developer overrode attribute.
- if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
- setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO);
- }
-
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.ImageView, defStyleAttr, defStyleRes);
saveAttributeDataForStyleable(context, R.styleable.ImageView,
@@ -265,6 +260,15 @@
sCompatDrawableVisibilityDispatch = targetSdkVersion < Build.VERSION_CODES.N;
sCompatDone = true;
}
+
+ // By default, ImageView is not important for autofill but important for content capture.
+ // Developers can override these defaults via the corresponding attributes.
+ if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+ setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO);
+ }
+ if (getImportantForContentCapture() == IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
+ setImportantForContentCapture(IMPORTANT_FOR_CONTENT_CAPTURE_YES);
+ }
}
@Override
diff --git a/core/java/android/window/IRemoteTransition.aidl b/core/java/android/window/IRemoteTransition.aidl
new file mode 100644
index 0000000..e0ddf05
--- /dev/null
+++ b/core/java/android/window/IRemoteTransition.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.view.IRemoteAnimationFinishedCallback;
+import android.view.SurfaceControl;
+import android.window.TransitionInfo;
+
+/**
+ * Interface allowing remote processes to play transition animations.
+ * The usage flow is as follows:
+ * <p><ol>
+ * <li>The remote tags a lifecycle event with an IRemoteTransition (via a parameter in
+ * ActivityOptions#makeRemoteAnimation) or a transition matches a filter registered via
+ * Transitions#registerRemote.
+ * <li>Shell then associates the transition for the event with the IRemoteTransition
+ * <li>Shell receives onTransitionReady and delegates the animation to the IRemoteTransition
+ * via {@link #startAnimation}.
+ * <li>Once the IRemoteTransition is done animating, it will call the finishCallback.
+ * <li>Shell/Core finish-up the transition.
+ * </ul>
+ *
+ * {@hide}
+ */
+oneway interface IRemoteTransition {
+ /**
+ * Starts a transition animation. Once complete, the implementation should call
+ * `finishCallback`.
+ */
+ void startAnimation(in TransitionInfo info, in SurfaceControl.Transaction t,
+ in IRemoteAnimationFinishedCallback finishCallback);
+}
diff --git a/core/java/android/window/ITransitionPlayer.aidl b/core/java/android/window/ITransitionPlayer.aidl
index 55d47cb..af37fbc 100644
--- a/core/java/android/window/ITransitionPlayer.aidl
+++ b/core/java/android/window/ITransitionPlayer.aidl
@@ -16,10 +16,9 @@
package android.window;
-import android.app.ActivityManager;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
-import android.window.WindowContainerTransaction;
+import android.window.TransitionRequestInfo;
/**
* Implemented by WMShell to initiate and play transition animations.
@@ -56,12 +55,9 @@
* Called when something in WMCore requires a transition to play -- for example when an Activity
* is started in a new Task.
*
- * @param type The {@link WindowManager#TransitionType} of the transition to start.
* @param transitionToken An identifying token for the transition that needs to be started.
* Pass this to {@link IWindowOrganizerController#startTransition}.
- * @param triggerTask If non-null, the task containing the activity whose lifecycle change
- * (start or finish) has caused this transition to occur.
+ * @param request Information about this particular request.
*/
- void requestStartTransition(int type, in IBinder transitionToken,
- in ActivityManager.RunningTaskInfo triggerTask);
+ void requestStartTransition(in IBinder transitionToken, in TransitionRequestInfo request);
}
diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl b/core/java/android/window/TransitionFilter.aidl
similarity index 64%
copy from media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
copy to core/java/android/window/TransitionFilter.aidl
index edf96dd..19c76d1 100644
--- a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
+++ b/core/java/android/window/TransitionFilter.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,6 @@
* limitations under the License.
*/
-package android.media.tv.tunerresourcemanager;
+package android.window;
-/**
- * Simple container of the FrontendInfo struct defined in the TunerHAL 1.0 interface.
- *
- * @hide
- */
-parcelable TunerFrontendInfo {
- int handle;
-
- int frontendType;
-
- int exclusiveGroupId;
-}
+parcelable TransitionFilter;
diff --git a/core/java/android/window/TransitionFilter.java b/core/java/android/window/TransitionFilter.java
new file mode 100644
index 0000000..4421f06
--- /dev/null
+++ b/core/java/android/window/TransitionFilter.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.WindowConfiguration;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A parcelable filter that can be used for rerouting transitions to a remote. This is a local
+ * representation so that the transition system doesn't need to make blocking queries over
+ * binder.
+ *
+ * @hide
+ */
+public final class TransitionFilter implements Parcelable {
+
+ /**
+ * When non-null: this is a list of transition types that this filter applies to. This filter
+ * will fail for transitions that aren't one of these types.
+ */
+ @Nullable public int[] mTypeSet = null;
+
+ /**
+ * A list of required changes. To pass, a transition must meet all requirements.
+ */
+ @Nullable public Requirement[] mRequirements = null;
+
+ public TransitionFilter() {
+ }
+
+ private TransitionFilter(Parcel in) {
+ mTypeSet = in.createIntArray();
+ mRequirements = in.createTypedArray(Requirement.CREATOR);
+ }
+
+ /** @return true if `info` meets all the requirements to pass this filter. */
+ public boolean matches(@NonNull TransitionInfo info) {
+ if (mTypeSet != null) {
+ // non-null typeset, so make sure info is one of the types.
+ boolean typePass = false;
+ for (int i = 0; i < mTypeSet.length; ++i) {
+ if (info.getType() == mTypeSet[i]) {
+ typePass = true;
+ break;
+ }
+ }
+ if (!typePass) return false;
+ }
+ // Make sure info meets all of the requirements.
+ if (mRequirements != null) {
+ for (int i = 0; i < mRequirements.length; ++i) {
+ if (!mRequirements[i].matches(info)) return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ /** @hide */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeIntArray(mTypeSet);
+ dest.writeTypedArray(mRequirements, flags);
+ }
+
+ @NonNull
+ public static final Creator<TransitionFilter> CREATOR =
+ new Creator<TransitionFilter>() {
+ @Override
+ public TransitionFilter createFromParcel(Parcel in) {
+ return new TransitionFilter(in);
+ }
+
+ @Override
+ public TransitionFilter[] newArray(int size) {
+ return new TransitionFilter[size];
+ }
+ };
+
+ @Override
+ /** @hide */
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{types=[");
+ if (mTypeSet != null) {
+ for (int i = 0; i < mTypeSet.length; ++i) {
+ sb.append((i == 0 ? "" : ",") + mTypeSet[i]);
+ }
+ }
+ sb.append("] checks=[");
+ if (mRequirements != null) {
+ for (int i = 0; i < mRequirements.length; ++i) {
+ sb.append((i == 0 ? "" : ",") + mRequirements[i]);
+ }
+ }
+ return sb.append("]}").toString();
+ }
+
+ /**
+ * Matches a change that a transition must contain to pass this filter. All requirements in a
+ * filter must be met to pass the filter.
+ */
+ public static final class Requirement implements Parcelable {
+ public int mActivityType = ACTIVITY_TYPE_UNDEFINED;
+ public int[] mModes = null;
+
+ public Requirement() {
+ }
+
+ private Requirement(Parcel in) {
+ mActivityType = in.readInt();
+ mModes = in.createIntArray();
+ }
+
+ /** Go through changes and find if at-least one change matches this filter */
+ boolean matches(@NonNull TransitionInfo info) {
+ for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+ final TransitionInfo.Change change = info.getChanges().get(i);
+ if (change.getParent() != null) {
+ // Only look at the top animating windows.
+ continue;
+ }
+ if (mActivityType != ACTIVITY_TYPE_UNDEFINED) {
+ if (change.getTaskInfo() == null
+ || change.getTaskInfo().getActivityType() != mActivityType) {
+ continue;
+ }
+ }
+ if (mModes != null) {
+ boolean pass = false;
+ for (int m = 0; m < mModes.length; ++m) {
+ if (mModes[m] == change.getMode()) {
+ pass = true;
+ break;
+ }
+ }
+ if (!pass) continue;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /** Check if the request matches this filter. It may generate false positives */
+ boolean matches(@NonNull TransitionRequestInfo request) {
+ // Can't check modes since the transition hasn't been built at this point.
+ if (mActivityType == ACTIVITY_TYPE_UNDEFINED) return true;
+ return request.getTriggerTask() != null
+ && request.getTriggerTask().getActivityType() == mActivityType;
+ }
+
+ @Override
+ /** @hide */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mActivityType);
+ dest.writeIntArray(mModes);
+ }
+
+ @NonNull
+ public static final Creator<Requirement> CREATOR =
+ new Creator<Requirement>() {
+ @Override
+ public Requirement createFromParcel(Parcel in) {
+ return new Requirement(in);
+ }
+
+ @Override
+ public Requirement[] newArray(int size) {
+ return new Requirement[size];
+ }
+ };
+
+ @Override
+ /** @hide */
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder out = new StringBuilder();
+ out.append("{atype=" + WindowConfiguration.activityTypeToString(mActivityType));
+ out.append(" modes=[");
+ if (mModes != null) {
+ for (int i = 0; i < mModes.length; ++i) {
+ out.append((i == 0 ? "" : ",") + TransitionInfo.modeToString(mModes[i]));
+ }
+ }
+ return out.append("]}").toString();
+ }
+ }
+}
diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl b/core/java/android/window/TransitionRequestInfo.aidl
similarity index 64%
rename from media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
rename to core/java/android/window/TransitionRequestInfo.aidl
index edf96dd..d2b9ccf 100644
--- a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
+++ b/core/java/android/window/TransitionRequestInfo.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,6 @@
* limitations under the License.
*/
-package android.media.tv.tunerresourcemanager;
+package android.window;
-/**
- * Simple container of the FrontendInfo struct defined in the TunerHAL 1.0 interface.
- *
- * @hide
- */
-parcelable TunerFrontendInfo {
- int handle;
-
- int frontendType;
-
- int exclusiveGroupId;
-}
+parcelable TransitionRequestInfo;
diff --git a/core/java/android/window/TransitionRequestInfo.java b/core/java/android/window/TransitionRequestInfo.java
new file mode 100644
index 0000000..cc493ab
--- /dev/null
+++ b/core/java/android/window/TransitionRequestInfo.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.os.Parcelable;
+import android.view.WindowManager;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Used to communicate information about what is changing during a transition to a TransitionPlayer.
+ * @hide
+ */
+@DataClass(genToString = true, genSetters = true, genAidl = true)
+public final class TransitionRequestInfo implements Parcelable {
+
+ /** The type of the transition being requested. */
+ private final @WindowManager.TransitionType int mType;
+
+ /**
+ * If non-null, If non-null, the task containing the activity whose lifecycle change (start or
+ * finish) has caused this transition to occur.
+ */
+ private @Nullable ActivityManager.RunningTaskInfo mTriggerTask;
+
+ /** If non-null, a remote-transition associated with the source of this transition. */
+ private @Nullable IRemoteTransition mRemoteTransition;
+
+
+
+ // Code below generated by codegen v1.0.22.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/window/TransitionRequestInfo.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Creates a new TransitionRequestInfo.
+ *
+ * @param type
+ * The type of the transition being requested.
+ * @param triggerTask
+ * If non-null, If non-null, the task containing the activity whose lifecycle change (start or
+ * finish) has caused this transition to occur.
+ * @param remoteTransition
+ * If non-null, a remote-transition associated with the source of this transition.
+ */
+ @DataClass.Generated.Member
+ public TransitionRequestInfo(
+ @WindowManager.TransitionType int type,
+ @Nullable ActivityManager.RunningTaskInfo triggerTask,
+ @Nullable IRemoteTransition remoteTransition) {
+ this.mType = type;
+ com.android.internal.util.AnnotationValidations.validate(
+ WindowManager.TransitionType.class, null, mType);
+ this.mTriggerTask = triggerTask;
+ this.mRemoteTransition = remoteTransition;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The type of the transition being requested.
+ */
+ @DataClass.Generated.Member
+ public @WindowManager.TransitionType int getType() {
+ return mType;
+ }
+
+ /**
+ * If non-null, If non-null, the task containing the activity whose lifecycle change (start or
+ * finish) has caused this transition to occur.
+ */
+ @DataClass.Generated.Member
+ public @Nullable ActivityManager.RunningTaskInfo getTriggerTask() {
+ return mTriggerTask;
+ }
+
+ /**
+ * If non-null, a remote-transition associated with the source of this transition.
+ */
+ @DataClass.Generated.Member
+ public @Nullable IRemoteTransition getRemoteTransition() {
+ return mRemoteTransition;
+ }
+
+ /**
+ * If non-null, If non-null, the task containing the activity whose lifecycle change (start or
+ * finish) has caused this transition to occur.
+ */
+ @DataClass.Generated.Member
+ public @android.annotation.NonNull TransitionRequestInfo setTriggerTask(@android.annotation.NonNull ActivityManager.RunningTaskInfo value) {
+ mTriggerTask = value;
+ return this;
+ }
+
+ /**
+ * If non-null, a remote-transition associated with the source of this transition.
+ */
+ @DataClass.Generated.Member
+ public @android.annotation.NonNull TransitionRequestInfo setRemoteTransition(@android.annotation.NonNull IRemoteTransition value) {
+ mRemoteTransition = value;
+ return this;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "TransitionRequestInfo { " +
+ "type = " + mType + ", " +
+ "triggerTask = " + mTriggerTask + ", " +
+ "remoteTransition = " + mRemoteTransition +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@android.annotation.NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mTriggerTask != null) flg |= 0x2;
+ if (mRemoteTransition != null) flg |= 0x4;
+ dest.writeByte(flg);
+ dest.writeInt(mType);
+ if (mTriggerTask != null) dest.writeTypedObject(mTriggerTask, flags);
+ if (mRemoteTransition != null) dest.writeStrongInterface(mRemoteTransition);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ TransitionRequestInfo(@android.annotation.NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ int type = in.readInt();
+ ActivityManager.RunningTaskInfo triggerTask = (flg & 0x2) == 0 ? null : (ActivityManager.RunningTaskInfo) in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
+ IRemoteTransition remoteTransition = (flg & 0x4) == 0 ? null : IRemoteTransition.Stub.asInterface(in.readStrongBinder());
+
+ this.mType = type;
+ com.android.internal.util.AnnotationValidations.validate(
+ WindowManager.TransitionType.class, null, mType);
+ this.mTriggerTask = triggerTask;
+ this.mRemoteTransition = remoteTransition;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @android.annotation.NonNull Parcelable.Creator<TransitionRequestInfo> CREATOR
+ = new Parcelable.Creator<TransitionRequestInfo>() {
+ @Override
+ public TransitionRequestInfo[] newArray(int size) {
+ return new TransitionRequestInfo[size];
+ }
+
+ @Override
+ public TransitionRequestInfo createFromParcel(@android.annotation.NonNull android.os.Parcel in) {
+ return new TransitionRequestInfo(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1610060387917L,
+ codegenVersion = "1.0.22",
+ sourceFile = "frameworks/base/core/java/android/window/TransitionRequestInfo.java",
+ inputSignatures = "private final @android.view.WindowManager.TransitionType int mType\nprivate @android.annotation.Nullable android.app.ActivityManager.RunningTaskInfo mTriggerTask\nprivate @android.annotation.Nullable android.window.IRemoteTransition mRemoteTransition\nclass TransitionRequestInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/com/android/internal/widget/OWNERS b/core/java/com/android/internal/widget/OWNERS
index cca39ea..ae566c3 100644
--- a/core/java/com/android/internal/widget/OWNERS
+++ b/core/java/com/android/internal/widget/OWNERS
@@ -1 +1,7 @@
per-file PointerLocationView.java = michaelwr@google.com, svv@google.com
+
+# LockSettings related
+per-file *LockPattern* = file:/services/core/java/com/android/server/locksettings/OWNERS
+per-file *LockScreen* = file:/services/core/java/com/android/server/locksettings/OWNERS
+per-file *Lockscreen* = file:/services/core/java/com/android/server/locksettings/OWNERS
+per-file *LockSettings* = file:/services/core/java/com/android/server/locksettings/OWNERS
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 302ac3c..8dc56ed 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -1946,7 +1946,7 @@
jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria);
- nAudioMix->mAllowPrivilegedPlaybackCapture =
+ nAudioMix->mAllowPrivilegedMediaPlaybackCapture =
env->GetBooleanField(jRule, gAudioMixingRuleFields.mAllowPrivilegedPlaybackCapture);
nAudioMix->mVoiceCommunicationCaptureAllowed =
env->GetBooleanField(jRule, gAudioMixingRuleFields.mVoiceCommunicationCaptureAllowed);
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 2ff474b..4dc8121 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1784,7 +1784,7 @@
heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
break;
}
- android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &heap_tagging_level, sizeof(heap_tagging_level));
+ mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, heap_tagging_level);
// Now that we've used the flag, clear it so that we don't pass unknown flags to the ART runtime.
runtime_flags &= ~RuntimeFlags::MEMORY_TAG_LEVEL_MASK;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 51fb264..b705a01 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2676,11 +2676,11 @@
The app can check whether it has this authorization by calling
{@link android.provider.Settings#canDrawOverlays
Settings.canDrawOverlays()}.
- <p>Protection level: signature|appop|installer|pre23|development|recents -->
+ <p>Protection level: signature|appop|preinstalled|pre23|development -->
<permission android:name="android.permission.SYSTEM_ALERT_WINDOW"
android:label="@string/permlab_systemAlertWindow"
android:description="@string/permdesc_systemAlertWindow"
- android:protectionLevel="signature|appop|installer|pre23|development|recents" />
+ android:protectionLevel="signature|appop|preinstalled|pre23|development" />
<!-- @SystemApi @hide Allows an application to create windows using the type
{@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY},
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index ef54db1a..be7ecfc 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -9013,6 +9013,11 @@
changed at runtime by calling
{@link android.media.tv.TvInputManager#updateTvInputInfo(android.media.tv.TvInputInfo)}. -->
<attr name="tunerCount" format="integer" />
+ <!-- Attribute whether the TV input service can pause recording programs.
+ This value can be changed at runtime by calling
+ {@link android.media.tv.TvInputManager#updateTvInputInfo(android.media.tv.TvInputInfo)}
+ . -->
+ <attr name="canPauseRecording" format="boolean" />
</declare-styleable>
<!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1845faa..529db3f5 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -58,6 +58,7 @@
<item><xliff:g id="id">@string/status_bar_hotspot</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_mobile</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_airplane</xliff:g></item>
+ <item><xliff:g id="id">@string/status_bar_no_calling</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_battery</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_sensors_off</xliff:g></item>
</string-array>
@@ -94,6 +95,7 @@
<string translatable="false" name="status_bar_microphone">microphone</string>
<string translatable="false" name="status_bar_camera">camera</string>
<string translatable="false" name="status_bar_airplane">airplane</string>
+ <string translatable="false" name="status_bar_no_calling">no_calling</string>
<string translatable="false" name="status_bar_sensors_off">sensors_off</string>
<string translatable="false" name="status_bar_screen_record">screen_record</string>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index c3164ab..bac50f1 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3047,6 +3047,7 @@
<public name="rollbackDataPolicy" />
<public name="allowClickWhenDisabled" />
<public name="windowLayoutAffinity" />
+ <public name="canPauseRecording" />
<!-- @hide -->
<public name="windowBackgroundBlurRadius"/>
<public name="requireDeviceScreenOn" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5715b31..317a76f 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -110,7 +110,7 @@
<!-- Displayed as the title for a success/failure report enabling/disabling caller ID. -->
<string name="ClipMmi">Incoming Caller ID</string>
<!-- Displayed as the title for a success/failure report enabling/disabling caller ID. -->
- <string name="ClirMmi">Outgoing Caller ID</string>
+ <string name="ClirMmi">Hide Outgoing Caller ID</string>
<!-- Displayed as the title for a success/failure report enabling/disabling connected line ID. -->
<string name="ColpMmi">Connected Line ID</string>
<!-- Displayed as the title for a success/failure report enabling/disabling connected line ID restriction. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c72a0cd..12acfd7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2947,6 +2947,7 @@
<java-symbol type="string" name="status_bar_secure" />
<java-symbol type="string" name="status_bar_clock" />
<java-symbol type="string" name="status_bar_airplane" />
+ <java-symbol type="string" name="status_bar_no_calling" />
<java-symbol type="string" name="status_bar_mobile" />
<java-symbol type="string" name="status_bar_ethernet" />
<java-symbol type="string" name="status_bar_vpn" />
diff --git a/core/tests/coretests/src/android/content/OWNERS b/core/tests/coretests/src/android/content/OWNERS
index 912db1e..696aa11 100644
--- a/core/tests/coretests/src/android/content/OWNERS
+++ b/core/tests/coretests/src/android/content/OWNERS
@@ -1,3 +1,4 @@
per-file ContextTest.java = file:/services/core/java/com/android/server/wm/OWNERS
per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS
+per-file AppSearchPersonTest.java = file:/core/java/android/content/pm/SHORTCUT_OWNERS
per-file *Launcher* = file:/core/java/android/content/pm/LAUNCHER_OWNERS
diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
index 05ff218..465ea17 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
@@ -48,7 +48,9 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
+import java.util.HashMap;
import java.util.Locale;
+import java.util.Map;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -145,9 +147,13 @@
} catch (IOException e) {
throw new RuntimeException(e);
}
+ Map<String, File> updatableFontMap = new HashMap<>();
+ for (File file : new File(TEST_UPDATABLE_FONT_DIR).listFiles()) {
+ updatableFontMap.put(file.getName(), file);
+ }
final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(TEST_FONTS_XML,
- TEST_FONT_DIR, TEST_UPDATABLE_FONT_DIR, oemCustomization, fallbackMap);
+ TEST_FONT_DIR, updatableFontMap, oemCustomization, fallbackMap);
Typeface.initSystemDefaultTypefaces(fontMap, fallbackMap, aliases);
}
diff --git a/core/tests/coretests/src/android/view/autofill/OWNERS b/core/tests/coretests/src/android/view/autofill/OWNERS
new file mode 100644
index 0000000..9a30e82
--- /dev/null
+++ b/core/tests/coretests/src/android/view/autofill/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 351486
+
+include /core/java/android/view/autofill/OWNERS
diff --git a/core/tests/coretests/src/android/view/contentcapture/OWNERS b/core/tests/coretests/src/android/view/contentcapture/OWNERS
new file mode 100644
index 0000000..24561c5
--- /dev/null
+++ b/core/tests/coretests/src/android/view/contentcapture/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 544200
+
+include /core/java/android/view/contentcapture/OWNERS
diff --git a/core/tests/coretests/src/android/view/textclassifier/OWNERS b/core/tests/coretests/src/android/view/textclassifier/OWNERS
new file mode 100644
index 0000000..46b3cb8
--- /dev/null
+++ b/core/tests/coretests/src/android/view/textclassifier/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/textclassifier/OWNERS
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index fb8b17c..201f649 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -102,6 +102,14 @@
}
prebuilt_etc {
+ name: "privapp_whitelist_com.android.imsserviceentitlement",
+ product_specific: true,
+ sub_dir: "permissions",
+ src: "com.android.imsserviceentitlement.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
name: "privapp_whitelist_com.android.launcher3",
system_ext_specific: true,
sub_dir: "permissions",
diff --git a/data/etc/com.android.imsserviceentitlement.xml b/data/etc/com.android.imsserviceentitlement.xml
new file mode 100644
index 0000000..4fd91c3
--- /dev/null
+++ b/data/etc/com.android.imsserviceentitlement.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<permissions>
+ <privapp-permissions package="com.android.imsserviceentitlement">
+ <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+ <permission name="android.permission.MODIFY_PHONE_STATE"/>
+ </privapp-permissions>
+</permissions>
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 73fff72..af100c9 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -31,6 +31,7 @@
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.regex.Pattern;
/**
@@ -50,19 +51,21 @@
* Parse the fonts.xml
*/
public static FontConfig parse(InputStream in, String fontDir,
- @Nullable String updatableFontDir) throws XmlPullParserException, IOException {
+ @Nullable Map<String, File> updatableFontMap)
+ throws XmlPullParserException, IOException {
try {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(in, null);
parser.nextTag();
- return readFamilies(parser, fontDir, updatableFontDir);
+ return readFamilies(parser, fontDir, updatableFontMap);
} finally {
in.close();
}
}
private static FontConfig readFamilies(XmlPullParser parser, String fontDir,
- @Nullable String updatableFontDir) throws XmlPullParserException, IOException {
+ @Nullable Map<String, File> updatableFontMap)
+ throws XmlPullParserException, IOException {
List<FontConfig.Family> families = new ArrayList<>();
List<FontConfig.Alias> aliases = new ArrayList<>();
@@ -71,7 +74,7 @@
if (parser.getEventType() != XmlPullParser.START_TAG) continue;
String tag = parser.getName();
if (tag.equals("family")) {
- families.add(readFamily(parser, fontDir, updatableFontDir));
+ families.add(readFamily(parser, fontDir, updatableFontMap));
} else if (tag.equals("alias")) {
aliases.add(readAlias(parser));
} else {
@@ -86,7 +89,8 @@
* Reads a family element
*/
public static FontConfig.Family readFamily(XmlPullParser parser, String fontDir,
- @Nullable String updatableFontDir) throws XmlPullParserException, IOException {
+ @Nullable Map<String, File> updatableFontMap)
+ throws XmlPullParserException, IOException {
final String name = parser.getAttributeValue(null, "name");
final String lang = parser.getAttributeValue("", "lang");
final String variant = parser.getAttributeValue(null, "variant");
@@ -95,7 +99,7 @@
if (parser.getEventType() != XmlPullParser.START_TAG) continue;
final String tag = parser.getName();
if (tag.equals("font")) {
- fonts.add(readFont(parser, fontDir, updatableFontDir));
+ fonts.add(readFont(parser, fontDir, updatableFontMap));
} else {
skip(parser);
}
@@ -117,7 +121,8 @@
Pattern.compile("^[ \\n\\r\\t]+|[ \\n\\r\\t]+$");
private static FontConfig.Font readFont(XmlPullParser parser, String fontDir,
- @Nullable String updatableFontDir) throws XmlPullParserException, IOException {
+ @Nullable Map<String, File> updatableFontMap)
+ throws XmlPullParserException, IOException {
String indexStr = parser.getAttributeValue(null, "index");
int index = indexStr == null ? 0 : Integer.parseInt(indexStr);
List<FontVariationAxis> axes = new ArrayList<FontVariationAxis>();
@@ -139,20 +144,20 @@
}
}
String sanitizedName = FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");
- String fontName = findFontFile(sanitizedName, fontDir, updatableFontDir);
+ String fontName = findFontFile(sanitizedName, fontDir, updatableFontMap);
return new FontConfig.Font(fontName, index, axes.toArray(
new FontVariationAxis[axes.size()]), weight, isItalic, fallbackFor);
}
- private static String findFontFile(String fileName, String fontDir,
- @Nullable String updatableFontDir) {
- if (updatableFontDir != null) {
- String updatableFontName = updatableFontDir + fileName;
- if (new File(updatableFontName).exists()) {
- return updatableFontName;
+ private static String findFontFile(String name, String fontDir,
+ @Nullable Map<String, File> updatableFontMap) {
+ if (updatableFontMap != null) {
+ File updatedFile = updatableFontMap.get(name);
+ if (updatedFile != null) {
+ return updatedFile.getAbsolutePath();
}
}
- return fontDir + fileName;
+ return fontDir + name;
}
private static FontVariationAxis readAxis(XmlPullParser parser)
diff --git a/graphics/java/android/graphics/Point.java b/graphics/java/android/graphics/Point.java
index 61a4749..cf2f970 100644
--- a/graphics/java/android/graphics/Point.java
+++ b/graphics/java/android/graphics/Point.java
@@ -20,8 +20,6 @@
import android.os.Parcel;
import android.os.Parcelable;
-import java.io.PrintWriter;
-
/**
* Point holds two integer coordinates
*/
@@ -72,17 +70,6 @@
return this.x == x && this.y == y;
}
- /**
- * Dumps a human-readable shortened string of the point into the given
- * stream
- *
- * @param pw The {@link PrintWriter} into which the string representation of
- * the point will be written.
- */
- public final void dump(@NonNull PrintWriter pw) {
- pw.print("["); pw.print(x); pw.print(","); pw.print(y); pw.print("]");
- }
-
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java
index 2d626b9..8dd7f31 100644
--- a/graphics/java/android/graphics/RecordingCanvas.java
+++ b/graphics/java/android/graphics/RecordingCanvas.java
@@ -220,7 +220,7 @@
CanvasProperty<Float> progress, RuntimeShader shader) {
nDrawRipple(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
radius.getNativeContainer(), paint.getNativeContainer(),
- progress.getNativeContainer(), shader.getNativeShaderFactory());
+ progress.getNativeContainer(), shader.getNativeShaderBuilder());
}
/**
diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java
index 7f2e503..1ace322 100644
--- a/graphics/java/android/graphics/RuntimeShader.java
+++ b/graphics/java/android/graphics/RuntimeShader.java
@@ -17,7 +17,6 @@
package android.graphics;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import libcore.util.NativeAllocationRegistry;
@@ -33,14 +32,12 @@
RuntimeShader.class.getClassLoader(), nativeGetFinalizer());
}
- private byte[] mUniforms;
- private Shader[] mInputShaders;
private boolean mIsOpaque;
/**
- * Current native shader factory instance.
+ * Current native shader builder instance.
*/
- private long mNativeInstanceRuntimeShaderFactory;
+ private long mNativeInstanceRuntimeShaderBuilder;
/**
* Creates a new RuntimeShader.
@@ -50,80 +47,86 @@
* on number of uniforms declared by sksl.
* @param isOpaque True if all pixels have alpha 1.0f.
*/
- public RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms, boolean isOpaque) {
- this(sksl, uniforms, null, isOpaque, ColorSpace.get(ColorSpace.Named.SRGB));
- }
-
- /**
- * Creates a new RuntimeShader.
- *
- * @param sksl The text of SKSL program to run on the GPU.
- * @param uniforms Array of parameters passed by the SKSL shader. Array size depends
- * on number of uniforms declared by sksl.
- * @param shaderInputs Array of shaders passed to the SKSL shader. Array size depends
- * on the number of input shaders declared in the sksl
- * @param isOpaque True if all pixels have alpha 1.0f.
- */
- public RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms,
- @Nullable Shader[] shaderInputs, boolean isOpaque) {
- this(sksl, uniforms, shaderInputs, isOpaque, ColorSpace.get(ColorSpace.Named.SRGB));
- }
-
- private RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms,
- @Nullable Shader[] shaderInputs, boolean isOpaque,
- ColorSpace colorSpace) {
- super(colorSpace);
- mUniforms = uniforms;
- mInputShaders = shaderInputs;
+ public RuntimeShader(@NonNull String sksl, boolean isOpaque) {
+ super(ColorSpace.get(ColorSpace.Named.SRGB));
mIsOpaque = isOpaque;
- mNativeInstanceRuntimeShaderFactory = nativeCreateShaderFactory(sksl);
- NoImagePreloadHolder.sRegistry.registerNativeAllocation(this,
- mNativeInstanceRuntimeShaderFactory);
+ mNativeInstanceRuntimeShaderBuilder = nativeCreateBuilder(sksl);
+ NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+ this, mNativeInstanceRuntimeShaderBuilder);
}
/**
- * Sets new value for shader parameters.
+ * Sets the uniform value corresponding to this shader. If the shader does not have a uniform
+ * with that name or if the uniform is declared with a type other than float then an
+ * IllegalArgumentException is thrown.
*
- * @param uniforms Array of parameters passed by the SKSL shader. Array size depends
- * on number of uniforms declared by mSksl.
+ * @param uniformName name matching the uniform declared in the SKSL shader
+ * @param value
*/
- public void updateUniforms(@Nullable byte[] uniforms) {
- mUniforms = uniforms;
+ public void setUniform(@NonNull String uniformName, float value) {
+ setUniform(uniformName, new float[] {value});
+ }
+
+ /**
+ * Sets the uniform value corresponding to this shader. If the shader does not have a uniform
+ * with that name or if the uniform is declared with a type other than float2/vec2 then an
+ * IllegalArgumentException is thrown.
+ *
+ * @param uniformName name matching the uniform declared in the SKSL shader
+ * @param value1
+ * @param value2
+ */
+ public void setUniform(@NonNull String uniformName, float value1, float value2) {
+ setUniform(uniformName, new float[] {value1, value2});
+ }
+
+ /**
+ * Sets the uniform value corresponding to this shader. If the shader does not have a uniform
+ * with that name or if the uniform is declared with a type other than a vecN/floatN where N is
+ * the size of the values array then an IllegalArgumentException is thrown.
+ *
+ * @param uniformName name matching the uniform declared in the SKSL shader
+ * @param values
+ */
+ public void setUniform(@NonNull String uniformName, float[] values) {
+ nativeUpdateUniforms(mNativeInstanceRuntimeShaderBuilder, uniformName, values);
discardNativeInstance();
}
/**
- * Sets new values for the shaders that serve as inputs to this shader.
+ * Sets the uniform shader that is declares as input to this shader. If the shader does not
+ * have a uniform shader with that name then an IllegalArgumentException is thrown.
*
- * @param shaderInputs Array of Shaders passed into the SKSL shader. Array size depends
- * on number of input shaders declared by sksl.
+ * @param shaderName name matching the uniform declared in the SKSL shader
+ * @param shader shader passed into the SKSL shader for sampling
*/
- public void updateInputShaders(@Nullable Shader[] shaderInputs) {
- mInputShaders = shaderInputs;
+ public void setInputShader(@NonNull String shaderName, @NonNull Shader shader) {
+ nativeUpdateShader(
+ mNativeInstanceRuntimeShaderBuilder, shaderName, shader.getNativeInstance());
discardNativeInstance();
}
/** @hide */
@Override
protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
- long[] nativeShaders = mInputShaders.length > 0 ? new long[mInputShaders.length] : null;
- for (int i = 0; i < mInputShaders.length; i++) {
- nativeShaders[i] = mInputShaders[i].getNativeInstance(filterFromPaint);
- }
-
- return nativeCreate(mNativeInstanceRuntimeShaderFactory, nativeMatrix, mUniforms,
- nativeShaders, colorSpace().getNativeInstance(), mIsOpaque);
+ return nativeCreateShader(mNativeInstanceRuntimeShaderBuilder, nativeMatrix, mIsOpaque);
}
- public long getNativeShaderFactory() {
- return mNativeInstanceRuntimeShaderFactory;
+ public long getNativeShaderBuilder() {
+ return mNativeInstanceRuntimeShaderBuilder;
}
- private static native long nativeCreate(long shaderFactory, long matrix, byte[] inputs,
- long[] shaderInputs, long colorSpaceHandle, boolean isOpaque);
-
- private static native long nativeCreateShaderFactory(String sksl);
+ public boolean isOpaque() {
+ return mIsOpaque;
+ }
private static native long nativeGetFinalizer();
+ private static native long nativeCreateBuilder(String sksl);
+ private static native long nativeCreateShader(
+ long shaderBuilder, long matrix, boolean isOpaque);
+ private static native void nativeUpdateUniforms(
+ long shaderBuilder, String uniformName, float[] uniforms);
+ private static native void nativeUpdateShader(
+ long shaderBuilder, String shaderName, long shader);
}
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
index 16a53c2..93b1fcc 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -92,7 +92,7 @@
readFontCustomization("/product/etc/fonts_customization.xml", "/product/fonts/");
Map<String, FontFamily[]> map = new ArrayMap<>();
// TODO: use updated fonts
- buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/", null /* updatableFontDir */,
+ buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/", null /* updatableFontMap */,
oemCustomization, map);
Set<Font> res = new HashSet<>();
for (FontFamily[] families : map.values()) {
@@ -228,7 +228,7 @@
}
/**
- * @see #buildSystemFallback(String, String, String, FontCustomizationParser.Result, Map)
+ * @see #buildSystemFallback(String, String, Map, FontCustomizationParser.Result, Map)
* @hide
*/
@VisibleForTesting
@@ -236,7 +236,7 @@
@NonNull String fontDir,
@NonNull FontCustomizationParser.Result oemCustomization,
@NonNull Map<String, FontFamily[]> fallbackMap) {
- return buildSystemFallback(xmlPath, fontDir, null /* updatableFontDir */,
+ return buildSystemFallback(xmlPath, fontDir, null /* updatableFontMap */,
oemCustomization, fallbackMap);
}
@@ -246,8 +246,7 @@
* @param xmlPath A full path string to the fonts.xml file.
* @param fontDir A full path string to the system font directory. This must end with
* slash('/').
- * @param updatableFontDir A full path string to the updatable system font directory. This
- * must end with slash('/').
+ * @param updatableFontMap A map from font file name to updated font file path.
* @param fallbackMap An output system fallback map. Caller must pass empty map.
* @return a list of aliases
* @hide
@@ -255,12 +254,12 @@
@VisibleForTesting
public static FontConfig.Alias[] buildSystemFallback(@NonNull String xmlPath,
@NonNull String fontDir,
- @Nullable String updatableFontDir,
+ @Nullable Map<String, File> updatableFontMap,
@NonNull FontCustomizationParser.Result oemCustomization,
@NonNull Map<String, FontFamily[]> fallbackMap) {
try {
final FileInputStream fontsIn = new FileInputStream(xmlPath);
- final FontConfig fontConfig = FontListParser.parse(fontsIn, fontDir, updatableFontDir);
+ final FontConfig fontConfig = FontListParser.parse(fontsIn, fontDir, updatableFontMap);
final HashMap<String, ByteBuffer> bufferCache = new HashMap<String, ByteBuffer>();
final FontConfig.Family[] xmlFamilies = fontConfig.getFamilies();
@@ -329,12 +328,12 @@
/** @hide */
public static Pair<FontConfig.Alias[], Map<String, FontFamily[]>>
- initializeSystemFonts(@Nullable String updatableFontDir) {
+ initializeSystemFonts(@Nullable Map<String, File> updatableFontMap) {
final FontCustomizationParser.Result oemCustomization =
readFontCustomization("/product/etc/fonts_customization.xml", "/product/fonts/");
Map<String, FontFamily[]> map = new ArrayMap<>();
FontConfig.Alias[] aliases = buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/",
- updatableFontDir, oemCustomization, map);
+ updatableFontMap, oemCustomization, map);
synchronized (LOCK) {
sFamilyMap = map;
}
diff --git a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java
index 6c733ba..33e8ded 100644
--- a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java
+++ b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java
@@ -139,7 +139,9 @@
int inputConsumed = ArrayUtils.copy(input, inputOffset, mChunk, mChunkLength,
inputLength);
inputLength -= inputConsumed;
- inputOffset += inputOffset;
+ inputOffset += inputConsumed;
+ mChunkLength += inputConsumed;
+ if (mChunkLength < mChunkSizeMax) return output;
byte[] o = mKeyStoreStream.update(mChunk);
if (o != null) {
output = ArrayUtils.concat(output, o);
diff --git a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
index 0290d9f..2cfb13e 100644
--- a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
+++ b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
@@ -1,6 +1,12 @@
{
"version": "1.0.0",
"messages": {
+ "-2076257741": {
+ "message": "Transition requested: %s %s",
+ "level": "VERBOSE",
+ "group": "WM_SHELL_TRANSITIONS",
+ "at": "com\/android\/wm\/shell\/transition\/Transitions.java"
+ },
"-1683614271": {
"message": "Existing task: id=%d component=%s",
"level": "VERBOSE",
@@ -133,12 +139,6 @@
"group": "WM_SHELL_TASK_ORG",
"at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
},
- "846958769": {
- "message": "Transition requested: type=%d %s",
- "level": "VERBOSE",
- "group": "WM_SHELL_TRANSITIONS",
- "at": "com\/android\/wm\/shell\/transition\/Transitions.java"
- },
"900599280": {
"message": "Can't pair unresizeable tasks task1.isResizeable=%b task1.isResizeable=%b",
"level": "ERROR",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
index 0146b72..7aedc1b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
@@ -71,6 +71,7 @@
@Override
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
final Point positionInParent = taskInfo.positionInParent;
mSyncQueue.runInSync(t -> t.setPosition(leash, positionInParent.x, positionInParent.y));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/SplitScreenTransitions.java
index 94b2cc0..d066cf9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/SplitScreenTransitions.java
@@ -36,6 +36,7 @@
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
import android.window.WindowContainerTransaction;
import com.android.wm.shell.common.TransactionPool;
@@ -76,9 +77,11 @@
}
@Override
- public WindowContainerTransaction handleRequest(@WindowManager.TransitionType int type,
- @NonNull IBinder transition, @Nullable ActivityManager.RunningTaskInfo triggerTask) {
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @Nullable TransitionRequestInfo request) {
WindowContainerTransaction out = null;
+ final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask();
+ final @WindowManager.TransitionType int type = request.getType();
if (mSplitScreen.isDividerVisible()) {
// try to handle everything while in split-screen
out = new WindowContainerTransaction();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 4cd2c50..f1e06f7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -26,11 +26,11 @@
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityManager;
import android.os.IBinder;
import android.util.ArrayMap;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
import android.window.WindowContainerTransaction;
import com.android.wm.shell.common.ShellExecutor;
@@ -99,8 +99,8 @@
@Nullable
@Override
- public WindowContainerTransaction handleRequest(int type, @NonNull IBinder transition,
- @Nullable ActivityManager.RunningTaskInfo triggerTask) {
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @NonNull TransitionRequestInfo request) {
return null;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
new file mode 100644
index 0000000..cf141c6a
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.transition;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.Pair;
+import android.view.IRemoteAnimationFinishedCallback;
+import android.view.SurfaceControl;
+import android.window.IRemoteTransition;
+import android.window.TransitionFilter;
+import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.common.ShellExecutor;
+
+import java.util.ArrayList;
+
+/**
+ * Handler that deals with RemoteTransitions. It will only request to handle a transition
+ * if the request includes a specific remote.
+ */
+public class RemoteTransitionHandler implements Transitions.TransitionHandler {
+ private final ShellExecutor mMainExecutor;
+
+ /** Includes remotes explicitly requested by, eg, ActivityOptions */
+ private final ArrayMap<IBinder, IRemoteTransition> mPendingRemotes = new ArrayMap<>();
+
+ /** Ordered by specificity. Last filters will be checked first */
+ private final ArrayList<Pair<TransitionFilter, IRemoteTransition>> mFilters =
+ new ArrayList<>();
+
+ RemoteTransitionHandler(@NonNull ShellExecutor mainExecutor) {
+ mMainExecutor = mainExecutor;
+ }
+
+ void addFiltered(TransitionFilter filter, IRemoteTransition remote) {
+ mFilters.add(new Pair<TransitionFilter, IRemoteTransition>(filter, remote));
+ }
+
+ void removeFiltered(IRemoteTransition remote) {
+ for (int i = mFilters.size() - 1; i >= 0; --i) {
+ if (mFilters.get(i).second == remote) {
+ mFilters.remove(i);
+ }
+ }
+ }
+
+ @Override
+ public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction t, @NonNull Runnable finishCallback) {
+ IRemoteTransition pendingRemote = mPendingRemotes.remove(transition);
+ if (pendingRemote == null) {
+ // If no explicit remote, search filters until one matches
+ for (int i = mFilters.size() - 1; i >= 0; --i) {
+ if (mFilters.get(i).first.matches(info)) {
+ pendingRemote = mFilters.get(i).second;
+ break;
+ }
+ }
+ }
+
+ if (pendingRemote == null) return false;
+
+ final IRemoteTransition remote = pendingRemote;
+ final IBinder.DeathRecipient remoteDied = () -> {
+ Log.e(Transitions.TAG, "Remote transition died, finishing");
+ mMainExecutor.execute(finishCallback);
+ };
+ IRemoteAnimationFinishedCallback cb = new IRemoteAnimationFinishedCallback.Stub() {
+ @Override
+ public void onAnimationFinished() throws RemoteException {
+ if (remote.asBinder() != null) {
+ remote.asBinder().unlinkToDeath(remoteDied, 0 /* flags */);
+ }
+ mMainExecutor.execute(finishCallback);
+ }
+ };
+ try {
+ if (remote.asBinder() != null) {
+ remote.asBinder().linkToDeath(remoteDied, 0 /* flags */);
+ }
+ remote.startAnimation(info, t, cb);
+ } catch (RemoteException e) {
+ Log.e(Transitions.TAG, "Error running remote transition.", e);
+ mMainExecutor.execute(finishCallback);
+ }
+ return true;
+ }
+
+ @Override
+ @Nullable
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @Nullable TransitionRequestInfo request) {
+ IRemoteTransition remote = request.getRemoteTransition();
+ if (remote == null) return null;
+ mPendingRemotes.put(transition, remote);
+ return new WindowContainerTransaction();
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 3b2ac70..c085168 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -25,15 +25,18 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityManager;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.util.ArrayMap;
+import android.util.Log;
import android.view.SurfaceControl;
import android.view.WindowManager;
+import android.window.IRemoteTransition;
import android.window.ITransitionPlayer;
+import android.window.TransitionFilter;
import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
@@ -44,6 +47,7 @@
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import java.util.ArrayList;
@@ -51,7 +55,7 @@
/** Plays transition animations */
public class Transitions {
- private static final String TAG = "ShellTransitions";
+ static final String TAG = "ShellTransitions";
/** Set to {@code true} to enable shell transitions. */
public static final boolean ENABLE_SHELL_TRANSITIONS =
@@ -61,6 +65,7 @@
private final ShellExecutor mMainExecutor;
private final ShellExecutor mAnimExecutor;
private final TransitionPlayerImpl mPlayerImpl;
+ private final RemoteTransitionHandler mRemoteTransitionHandler;
/** List of possible handlers. Ordered by specificity (eg. tapped back to front). */
private final ArrayList<TransitionHandler> mHandlers = new ArrayList<>();
@@ -80,10 +85,28 @@
mPlayerImpl = new TransitionPlayerImpl();
// The very last handler (0 in the list) should be the default one.
mHandlers.add(new DefaultTransitionHandler(pool, mainExecutor, animExecutor));
+ // Next lowest priority is remote transitions.
+ mRemoteTransitionHandler = new RemoteTransitionHandler(mainExecutor);
+ mHandlers.add(mRemoteTransitionHandler);
+ }
+
+ private Transitions() {
+ mOrganizer = null;
+ mMainExecutor = null;
+ mAnimExecutor = null;
+ mPlayerImpl = null;
+ mRemoteTransitionHandler = null;
+ }
+
+ /** Create an empty/non-registering transitions object for system-ui tests. */
+ @VisibleForTesting
+ public static Transitions createEmptyForTesting() {
+ return new Transitions();
}
/** Register this transition handler with Core */
public void register(ShellTaskOrganizer taskOrganizer) {
+ if (mPlayerImpl == null) return;
taskOrganizer.registerTransitionPlayer(mPlayerImpl);
}
@@ -109,6 +132,19 @@
mHandlers.set(0, handler);
}
+ /** Register a remote transition to be used when `filter` matches an incoming transition */
+ @ExternalThread
+ public void registerRemote(@NonNull TransitionFilter filter,
+ @NonNull IRemoteTransition remoteTransition) {
+ mMainExecutor.execute(() -> mRemoteTransitionHandler.addFiltered(filter, remoteTransition));
+ }
+
+ /** Unregisters a remote transition and all associated filters */
+ @ExternalThread
+ public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) {
+ mMainExecutor.execute(() -> mRemoteTransitionHandler.removeFiltered(remoteTransition));
+ }
+
/** @return true if the transition was triggered by opening something vs closing something */
public static boolean isOpeningType(@WindowManager.TransitionType int type) {
return type == TRANSIT_OPEN
@@ -126,6 +162,8 @@
if (info.getRootLeash().isValid()) {
t.show(info.getRootLeash());
}
+ // Put animating stuff above this line and put static stuff below it.
+ int zSplitLine = info.getChanges().size();
// changes should be ordered top-to-bottom in z
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
@@ -152,7 +190,7 @@
t.setMatrix(leash, 1, 0, 0, 1);
if (isOpening) {
// put on top with 0 alpha
- t.setLayer(leash, info.getChanges().size() - i);
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - i);
if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) {
// This received a transferred starting window, so make it immediately
// visible.
@@ -162,19 +200,19 @@
}
} else {
// put on bottom and leave it visible
- t.setLayer(leash, -i);
+ t.setLayer(leash, zSplitLine - i);
t.setAlpha(leash, 1.f);
}
} else if (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK) {
if (isOpening) {
// put on bottom and leave visible
- t.setLayer(leash, -i);
+ t.setLayer(leash, zSplitLine - i);
} else {
// put on top
- t.setLayer(leash, info.getChanges().size() - i);
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - i);
}
} else { // CHANGE
- t.setLayer(leash, info.getChanges().size() - i);
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - i);
}
}
}
@@ -219,7 +257,8 @@
private void onFinish(IBinder transition) {
if (!mActiveTransitions.containsKey(transition)) {
- throw new IllegalStateException("Trying to finish an already-finished transition.");
+ Log.e(TAG, "Trying to finish a non-running transition. Maybe remote crashed?");
+ return;
}
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
"Transition animations finished, notifying core %s", transition);
@@ -227,24 +266,24 @@
mOrganizer.finishTransition(transition, null, null);
}
- void requestStartTransition(int type, @NonNull IBinder transitionToken,
- @Nullable ActivityManager.RunningTaskInfo triggerTask) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition requested: type=%d %s",
- type, transitionToken);
-
+ void requestStartTransition(@NonNull IBinder transitionToken,
+ @Nullable TransitionRequestInfo request) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition requested: %s %s",
+ transitionToken, request);
if (mActiveTransitions.containsKey(transitionToken)) {
throw new RuntimeException("Transition already started " + transitionToken);
}
final ActiveTransition active = new ActiveTransition();
WindowContainerTransaction wct = null;
for (int i = mHandlers.size() - 1; i >= 0; --i) {
- wct = mHandlers.get(i).handleRequest(type, transitionToken, triggerTask);
+ wct = mHandlers.get(i).handleRequest(transitionToken, request);
if (wct != null) {
active.mFirstHandler = mHandlers.get(i);
break;
}
}
- IBinder transition = mOrganizer.startTransition(type, transitionToken, wct);
+ IBinder transition = mOrganizer.startTransition(
+ request.getType(), transitionToken, wct);
mActiveTransitions.put(transition, active);
}
@@ -267,6 +306,7 @@
* for a particular transition. Otherwise, it is only called if no other handler before
* it handled the transition.
*
+ * @param finishCallback Call this when finished. This MUST be called on main thread.
* @return true if transition was handled, false if not (falls-back to default).
*/
boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@@ -274,15 +314,15 @@
/**
* Potentially handles a startTransition request.
- * @param type The transition type
- * @param triggerTask The task which triggered this transition request.
- * @return WCT to apply with transition-start or null if this handler isn't handling
- * the request.
+ *
+ * @param transition The transition whose start is being requested.
+ * @param request Information about what is requested.
+ * @return WCT to apply with transition-start or null. If a WCT is returned here, this
+ * handler will be the first in line to animate.
*/
@Nullable
- WindowContainerTransaction handleRequest(@WindowManager.TransitionType int type,
- @NonNull IBinder transition,
- @Nullable ActivityManager.RunningTaskInfo triggerTask);
+ WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @NonNull TransitionRequestInfo request);
}
@BinderThread
@@ -296,11 +336,9 @@
}
@Override
- public void requestStartTransition(int i, IBinder iBinder,
- ActivityManager.RunningTaskInfo runningTaskInfo) throws RemoteException {
- mMainExecutor.execute(() -> {
- Transitions.this.requestStartTransition(i, iBinder, runningTaskInfo);
- });
+ public void requestStartTransition(IBinder iBinder,
+ TransitionRequestInfo request) throws RemoteException {
+ mMainExecutor.execute(() -> Transitions.this.requestStartTransition(iBinder, request));
}
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index c46e59a..f3bee4b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -16,15 +16,21 @@
package com.android.wm.shell.transition;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -37,9 +43,14 @@
import android.app.ActivityManager.RunningTaskInfo;
import android.os.Binder;
import android.os.IBinder;
+import android.os.RemoteException;
+import android.view.IRemoteAnimationFinishedCallback;
import android.view.SurfaceControl;
import android.view.WindowManager;
+import android.window.IRemoteTransition;
+import android.window.TransitionFilter;
import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
@@ -84,7 +95,8 @@
transitions.replaceDefaultHandlerForTest(mDefaultHandler);
IBinder transitToken = new Binder();
- transitions.requestStartTransition(TRANSIT_OPEN, transitToken, null /* trigger */);
+ transitions.requestStartTransition(transitToken,
+ new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
verify(mOrganizer, times(1)).startTransition(eq(TRANSIT_OPEN), eq(transitToken), any());
TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN)
.addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
@@ -118,10 +130,10 @@
@Nullable
@Override
- public WindowContainerTransaction handleRequest(int type, @NonNull IBinder transition,
- @Nullable RunningTaskInfo triggerTask) {
- return (triggerTask != null
- && triggerTask.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW)
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @NonNull TransitionRequestInfo request) {
+ final RunningTaskInfo task = request.getTriggerTask();
+ return (task != null && task.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW)
? handlerWCT : null;
}
};
@@ -132,7 +144,8 @@
.addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
// Make a request that will be rejected by the testhandler.
- transitions.requestStartTransition(TRANSIT_OPEN, transitToken, null /* trigger */);
+ transitions.requestStartTransition(transitToken,
+ new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
verify(mOrganizer, times(1)).startTransition(eq(TRANSIT_OPEN), eq(transitToken), isNull());
transitions.onTransitionReady(transitToken, open, mock(SurfaceControl.Transaction.class));
assertEquals(1, mDefaultHandler.activeCount());
@@ -143,7 +156,8 @@
// Make a request that will be handled by testhandler but not animated by it.
RunningTaskInfo mwTaskInfo =
createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
- transitions.requestStartTransition(TRANSIT_OPEN, transitToken, mwTaskInfo);
+ transitions.requestStartTransition(transitToken,
+ new TransitionRequestInfo(TRANSIT_OPEN, mwTaskInfo, null /* remote */));
verify(mOrganizer, times(1)).startTransition(
eq(TRANSIT_OPEN), eq(transitToken), eq(handlerWCT));
transitions.onTransitionReady(transitToken, open, mock(SurfaceControl.Transaction.class));
@@ -157,9 +171,10 @@
// the test handler gets first shot at animating since it claimed to handle it.
TestTransitionHandler topHandler = new TestTransitionHandler();
transitions.addHandler(topHandler);
- transitions.requestStartTransition(TRANSIT_CHANGE, transitToken, mwTaskInfo);
+ transitions.requestStartTransition(transitToken,
+ new TransitionRequestInfo(TRANSIT_CHANGE, mwTaskInfo, null /* remote */));
verify(mOrganizer, times(1)).startTransition(
- eq(TRANSIT_OPEN), eq(transitToken), eq(handlerWCT));
+ eq(TRANSIT_CHANGE), eq(transitToken), eq(handlerWCT));
TransitionInfo change = new TransitionInfoBuilder(TRANSIT_CHANGE)
.addChange(TRANSIT_CHANGE).build();
transitions.onTransitionReady(transitToken, change, mock(SurfaceControl.Transaction.class));
@@ -170,6 +185,110 @@
mMainExecutor.flushAll();
}
+ @Test
+ public void testRequestRemoteTransition() {
+ Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mMainExecutor,
+ mAnimExecutor);
+ transitions.replaceDefaultHandlerForTest(mDefaultHandler);
+
+ final boolean[] remoteCalled = new boolean[]{false};
+ IRemoteTransition testRemote = new IRemoteTransition.Stub() {
+ @Override
+ public void startAnimation(TransitionInfo info, SurfaceControl.Transaction t,
+ IRemoteAnimationFinishedCallback finishCallback) throws RemoteException {
+ remoteCalled[0] = true;
+ finishCallback.onAnimationFinished();
+ }
+ };
+ IBinder transitToken = new Binder();
+ transitions.requestStartTransition(transitToken,
+ new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, testRemote));
+ verify(mOrganizer, times(1)).startTransition(eq(TRANSIT_OPEN), eq(transitToken), any());
+ TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+ transitions.onTransitionReady(transitToken, info, mock(SurfaceControl.Transaction.class));
+ assertEquals(0, mDefaultHandler.activeCount());
+ assertTrue(remoteCalled[0]);
+ mDefaultHandler.finishAll();
+ mMainExecutor.flushAll();
+ verify(mOrganizer, times(1)).finishTransition(eq(transitToken), any(), any());
+ }
+
+ @Test
+ public void testTransitionFilterActivityType() {
+ TransitionFilter filter = new TransitionFilter();
+ filter.mRequirements =
+ new TransitionFilter.Requirement[]{new TransitionFilter.Requirement()};
+ filter.mRequirements[0].mActivityType = ACTIVITY_TYPE_HOME;
+ filter.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
+
+ final TransitionInfo openHome = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN,
+ createTaskInfo(1, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME)).build();
+ assertTrue(filter.matches(openHome));
+
+ final TransitionInfo openStd = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN, createTaskInfo(
+ 1, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD)).build();
+ assertFalse(filter.matches(openStd));
+ }
+
+ @Test
+ public void testTransitionFilterMultiRequirement() {
+ // filter that requires at-least one opening and one closing app
+ TransitionFilter filter = new TransitionFilter();
+ filter.mRequirements = new TransitionFilter.Requirement[]{
+ new TransitionFilter.Requirement(), new TransitionFilter.Requirement()};
+ filter.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
+ filter.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
+
+ final TransitionInfo openOnly = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN).build();
+ assertFalse(filter.matches(openOnly));
+
+ final TransitionInfo openClose = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+ assertTrue(filter.matches(openClose));
+ }
+
+ @Test
+ public void testRegisteredRemoteTransition() {
+ Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mMainExecutor,
+ mAnimExecutor);
+ transitions.replaceDefaultHandlerForTest(mDefaultHandler);
+
+ final boolean[] remoteCalled = new boolean[]{false};
+ IRemoteTransition testRemote = new IRemoteTransition.Stub() {
+ @Override
+ public void startAnimation(TransitionInfo info, SurfaceControl.Transaction t,
+ IRemoteAnimationFinishedCallback finishCallback) throws RemoteException {
+ remoteCalled[0] = true;
+ finishCallback.onAnimationFinished();
+ }
+ };
+
+ TransitionFilter filter = new TransitionFilter();
+ filter.mRequirements =
+ new TransitionFilter.Requirement[]{new TransitionFilter.Requirement()};
+ filter.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
+
+ transitions.registerRemote(filter, testRemote);
+ mMainExecutor.flushAll();
+
+ IBinder transitToken = new Binder();
+ transitions.requestStartTransition(transitToken,
+ new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
+ verify(mOrganizer, times(1)).startTransition(eq(TRANSIT_OPEN), eq(transitToken), any());
+ TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+ transitions.onTransitionReady(transitToken, info, mock(SurfaceControl.Transaction.class));
+ assertEquals(0, mDefaultHandler.activeCount());
+ assertTrue(remoteCalled[0]);
+ mDefaultHandler.finishAll();
+ mMainExecutor.flushAll();
+ verify(mOrganizer, times(1)).finishTransition(eq(transitToken), any(), any());
+ }
+
class TransitionInfoBuilder {
final TransitionInfo mInfo;
@@ -209,8 +328,8 @@
@Nullable
@Override
- public WindowContainerTransaction handleRequest(int type, @NonNull IBinder transition,
- @Nullable RunningTaskInfo triggerTask) {
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @NonNull TransitionRequestInfo request) {
return null;
}
@@ -240,4 +359,10 @@
return taskInfo;
}
+ private static RunningTaskInfo createTaskInfo(int taskId) {
+ RunningTaskInfo taskInfo = new RunningTaskInfo();
+ taskInfo.taskId = taskId;
+ return taskInfo;
+ }
+
}
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 815ffde..1ebc489 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -819,10 +819,10 @@
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) {
+ const SkRuntimeShaderBuilder& effectBuilder) {
sk_sp<uirenderer::skiapipeline::AnimatedRipple> drawable(
new uirenderer::skiapipeline::AnimatedRipple(x, y, radius, paint, progress,
- runtimeEffect));
+ effectBuilder));
mCanvas->drawDrawable(drawable.get());
}
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index e6fc9da..82b7de4 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -152,7 +152,7 @@
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) override;
+ const SkRuntimeShaderBuilder& effectBuilder) override;
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override;
virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override;
diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h
index ea9fea97..fa0c45b 100644
--- a/libs/hwui/canvas/CanvasOps.h
+++ b/libs/hwui/canvas/CanvasOps.h
@@ -161,7 +161,7 @@
}
SkRuntimeShaderBuilder::BuilderUniform radiusU =
- runtimeEffectBuilder.uniform("in_maxRadius");
+ runtimeEffectBuilder.uniform("in_radius");
if (radiusU.fVar != nullptr) {
radiusU = radius->value;
}
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 9304b7a..184b11e 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -31,7 +31,7 @@
class SkAnimatedImage;
class SkCanvasState;
-class SkRuntimeEffect;
+class SkRuntimeShaderBuilder;
class SkVertices;
namespace minikin {
@@ -139,7 +139,7 @@
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) = 0;
+ const SkRuntimeShaderBuilder& effectBuilder) = 0;
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) = 0;
virtual void drawRenderNode(uirenderer::RenderNode* renderNode) = 0;
diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp
index aaec60b..ad3fd55 100644
--- a/libs/hwui/jni/Shader.cpp
+++ b/libs/hwui/jni/Shader.cpp
@@ -1,3 +1,6 @@
+#undef LOG_TAG
+#define LOG_TAG "ShaderJNI"
+
#include "GraphicsJNI.h"
#include "SkColorFilter.h"
#include "SkGradientShader.h"
@@ -232,53 +235,72 @@
///////////////////////////////////////////////////////////////////////////////////////////////
-static jlong RuntimeShader_create(JNIEnv* env, jobject, jlong shaderFactory, jlong matrixPtr,
- jbyteArray inputs, jlongArray inputShaders, jlong colorSpaceHandle, jboolean isOpaque) {
- SkRuntimeEffect* effect = reinterpret_cast<SkRuntimeEffect*>(shaderFactory);
- AutoJavaByteArray arInputs(env, inputs);
-
- std::vector<sk_sp<SkShader>> shaderVector;
- if (inputShaders) {
- jsize shaderCount = env->GetArrayLength(inputShaders);
- shaderVector.resize(shaderCount);
- jlong* arrayPtr = env->GetLongArrayElements(inputShaders, NULL);
- for (int i = 0; i < shaderCount; i++) {
- shaderVector[i] = sk_ref_sp(reinterpret_cast<SkShader*>(arrayPtr[i]));
- }
- env->ReleaseLongArrayElements(inputShaders, arrayPtr, 0);
- }
-
- sk_sp<SkData> fData;
- fData = SkData::MakeWithCopy(arInputs.ptr(), arInputs.length());
- const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
- sk_sp<SkShader> shader = effect->makeShader(fData, shaderVector.data(), shaderVector.size(),
- matrix, isOpaque == JNI_TRUE);
- ThrowIAE_IfNull(env, shader);
-
- return reinterpret_cast<jlong>(shader.release());
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////
-static jlong RuntimeShader_createShaderFactory(JNIEnv* env, jobject, jstring sksl) {
+static jlong RuntimeShader_createShaderBuilder(JNIEnv* env, jobject, jstring sksl) {
ScopedUtfChars strSksl(env, sksl);
auto result = SkRuntimeEffect::Make(SkString(strSksl.c_str()));
sk_sp<SkRuntimeEffect> effect = std::get<0>(result);
- if (!effect) {
+ if (effect.get() == nullptr) {
const auto& err = std::get<1>(result);
doThrowIAE(env, err.c_str());
+ return 0;
}
- return reinterpret_cast<jlong>(effect.release());
+ return reinterpret_cast<jlong>(new SkRuntimeShaderBuilder(std::move(effect)));
}
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-static void Effect_safeUnref(SkRuntimeEffect* effect) {
- SkSafeUnref(effect);
+static void SkRuntimeShaderBuilder_delete(SkRuntimeShaderBuilder* builder) {
+ delete builder;
}
static jlong RuntimeShader_getNativeFinalizer(JNIEnv*, jobject) {
- return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Effect_safeUnref));
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(&SkRuntimeShaderBuilder_delete));
+}
+
+static jlong RuntimeShader_create(JNIEnv* env, jobject, jlong shaderBuilder, jlong matrixPtr,
+ jboolean isOpaque) {
+ SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(shaderBuilder);
+ const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
+ sk_sp<SkShader> shader = builder->makeShader(matrix, isOpaque == JNI_TRUE);
+ ThrowIAE_IfNull(env, shader);
+ return reinterpret_cast<jlong>(shader.release());
+}
+
+static inline int ThrowIAEFmt(JNIEnv* env, const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ return jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", fmt, args);
+ va_end(args);
+}
+
+static void RuntimeShader_updateUniforms(JNIEnv* env, jobject, jlong shaderBuilder,
+ jstring jUniformName, jfloatArray jvalues) {
+ SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(shaderBuilder);
+ ScopedUtfChars name(env, jUniformName);
+ AutoJavaFloatArray autoValues(env, jvalues, 0, kRO_JNIAccess);
+
+ SkRuntimeShaderBuilder::BuilderUniform uniform = builder->uniform(name.c_str());
+ if (uniform.fVar == nullptr) {
+ ThrowIAEFmt(env, "unable to find uniform named %s", name.c_str());
+ } else if (!uniform.set<float>(autoValues.ptr(), autoValues.length())) {
+ ThrowIAEFmt(env, "mismatch in byte size for uniform [expected: %zu actual: %zu]",
+ uniform.fVar->sizeInBytes(), sizeof(float) * autoValues.length());
+ }
+}
+
+static void RuntimeShader_updateShader(JNIEnv* env, jobject, jlong shaderBuilder,
+ jstring jUniformName, jlong shaderHandle) {
+ SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(shaderBuilder);
+ ScopedUtfChars name(env, jUniformName);
+ SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
+
+ SkRuntimeShaderBuilder::BuilderChild child = builder->child(name.c_str());
+ if (child.fIndex == -1) {
+ ThrowIAEFmt(env, "unable to find shader named %s", name.c_str());
+ return;
+ }
+
+ builder->child(name.c_str()) = sk_ref_sp(shader);
}
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -313,10 +335,11 @@
};
static const JNINativeMethod gRuntimeShaderMethods[] = {
- { "nativeGetFinalizer", "()J", (void*)RuntimeShader_getNativeFinalizer },
- { "nativeCreate", "(JJ[B[JJZ)J", (void*)RuntimeShader_create },
- { "nativeCreateShaderFactory", "(Ljava/lang/String;)J",
- (void*)RuntimeShader_createShaderFactory },
+ {"nativeGetFinalizer", "()J", (void*)RuntimeShader_getNativeFinalizer},
+ {"nativeCreateShader", "(JJZ)J", (void*)RuntimeShader_create},
+ {"nativeCreateBuilder", "(Ljava/lang/String;)J", (void*)RuntimeShader_createShaderBuilder},
+ {"nativeUpdateUniforms", "(JLjava/lang/String;[F)V", (void*)RuntimeShader_updateUniforms},
+ {"nativeUpdateShader", "(JLjava/lang/String;J)V", (void*)RuntimeShader_updateShader},
};
int register_android_graphics_Shader(JNIEnv* env)
diff --git a/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp b/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp
index a74e561..926e233 100644
--- a/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp
+++ b/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp
@@ -144,7 +144,8 @@
static void android_view_DisplayListCanvas_drawRippleProps(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr,
jlong xPropPtr, jlong yPropPtr,
jlong radiusPropPtr, jlong paintPropPtr,
- jlong progressPropPtr, jlong effectPtr) {
+ jlong progressPropPtr,
+ jlong builderPtr) {
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
@@ -152,8 +153,8 @@
CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
CanvasPropertyPrimitive* progressProp =
reinterpret_cast<CanvasPropertyPrimitive*>(progressPropPtr);
- SkRuntimeEffect* effect = reinterpret_cast<SkRuntimeEffect*>(effectPtr);
- canvas->drawRipple(xProp, yProp, radiusProp, paintProp, progressProp, sk_ref_sp(effect));
+ SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(builderPtr);
+ canvas->drawRipple(xProp, yProp, radiusProp, paintProp, progressProp, *builder);
}
static void android_view_DisplayListCanvas_drawWebViewFunctor(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jint functor) {
diff --git a/libs/hwui/pipeline/skia/AnimatedDrawables.h b/libs/hwui/pipeline/skia/AnimatedDrawables.h
index 3142d92..7859145 100644
--- a/libs/hwui/pipeline/skia/AnimatedDrawables.h
+++ b/libs/hwui/pipeline/skia/AnimatedDrawables.h
@@ -61,13 +61,13 @@
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect)
+ const SkRuntimeShaderBuilder& effectBuilder)
: mX(x)
, mY(y)
, mRadius(radius)
, mPaint(paint)
, mProgress(progress)
- , mRuntimeEffectBuilder(std::move(runtimeEffect)) {}
+ , mRuntimeEffectBuilder(effectBuilder) {}
protected:
virtual SkRect onGetBounds() override {
@@ -83,7 +83,7 @@
}
SkRuntimeShaderBuilder::BuilderUniform radiusU =
- mRuntimeEffectBuilder.uniform("in_maxRadius");
+ mRuntimeEffectBuilder.uniform("in_radius");
if (radiusU.fVar != nullptr) {
radiusU = mRadius->value;
}
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 5f35155..9e91dff 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -90,9 +90,9 @@
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) {
+ const SkRuntimeShaderBuilder& effectBuilder) {
drawDrawable(mDisplayList->allocateDrawable<AnimatedRipple>(x, y, radius, paint, progress,
- runtimeEffect));
+ effectBuilder));
}
void SkiaRecordingCanvas::enableZ(bool enableZ) {
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index ee308f0..32c1791 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -71,7 +71,7 @@
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) override;
+ const SkRuntimeShaderBuilder& effectBuilder) override;
virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
diff --git a/location/java/android/location/CorrelationVector.java b/location/java/android/location/CorrelationVector.java
new file mode 100644
index 0000000..eca35dd
--- /dev/null
+++ b/location/java/android/location/CorrelationVector.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+import android.annotation.FloatRange;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Contains info about the correlation output of incoming GNSS signal and a local copy of
+ * its corresponding spreading code at a given frequency offset.
+ *
+ * @hide
+ */
+@SystemApi
+public final class CorrelationVector implements Parcelable {
+
+ private final double mSamplingWidthMeters;
+ private final double mSamplingStartMeters;
+ private final int mFrequencyOffsetMetersPerSecond;
+ @NonNull private final int[] mMagnitude;
+
+ /**
+ * Returns the space between correlation samples in meters.
+ */
+ @FloatRange(from = 0.0f, fromInclusive = false)
+ public double getSamplingWidthMeters() {
+ return mSamplingWidthMeters;
+ }
+
+ /**
+ * Returns the offset of the first sampling bin in meters.
+ *
+ * <p>The following sampling bins are located at positive offsets from this value as follows:
+ * samplingStartMeters, samplingStartMeters + samplingWidthMeters, ... , samplingStartMeters +
+ * (magnitude.size-1) * samplingWidthMeters.
+ *
+ */
+ @FloatRange(from = 0.0f)
+ public double getSamplingStartMeters() {
+ return mSamplingStartMeters;
+ }
+
+ /**
+ * Returns the frequency offset from reported pseudorange rate for this CorrelationVector.
+ */
+ @IntRange(from = 0)
+ public int getFrequencyOffsetMetersPerSecond() {
+ return mFrequencyOffsetMetersPerSecond;
+ }
+
+ /**
+ * Returns the data array representing normalized correlation magnitude values.
+ *
+ * <p>The data are normalized correlation magnitude values from -1 to 1, the reported value must
+ * be encoded as signed 16 bit integer where 1 is represented by 32767 and -1 is represented
+ * by -32768.
+ *
+ */
+ @NonNull
+ public int[] getMagnitude() {
+ return mMagnitude.clone();
+ }
+
+ private CorrelationVector(Builder builder) {
+ Preconditions.checkNotNull(builder.mMagnitude, "Magnitude array must not be null");
+ Preconditions.checkArgumentPositive(builder.mMagnitude.length,
+ "Magnitude array must have non-zero length");
+ Preconditions.checkArgumentNonNegative(builder.mFrequencyOffsetMetersPerSecond,
+ "FrequencyOffsetMetersPerSecond must be non-negative (greater than or equal to 0)");
+ Preconditions.checkArgument(builder.mSamplingWidthMeters > 0.0,
+ "SamplingWidthMeters must be positive (greater than 0)");
+ Preconditions.checkArgument(builder.mSamplingStartMeters >= 0.0,
+ "SamplingStartMeters must be non-negative (greater than or equal to 0)");
+ mMagnitude = builder.mMagnitude;
+ mFrequencyOffsetMetersPerSecond = builder.mFrequencyOffsetMetersPerSecond;
+ mSamplingWidthMeters = builder.mSamplingWidthMeters;
+ mSamplingStartMeters = builder.mSamplingStartMeters;
+ }
+
+ private CorrelationVector(Parcel in) {
+ mSamplingWidthMeters = in.readDouble();
+ mSamplingStartMeters = in.readDouble();
+ mFrequencyOffsetMetersPerSecond = in.readInt();
+ mMagnitude = new int[in.readInt()];
+ in.readIntArray(mMagnitude);
+ }
+
+ /*
+ * Method definitions to support Parcelable operations.
+ */
+ public static final @NonNull Parcelable.Creator<CorrelationVector> CREATOR =
+ new Parcelable.Creator<CorrelationVector>() {
+ @Override
+ public CorrelationVector createFromParcel(Parcel parcel) {
+ return new CorrelationVector(parcel);
+ }
+
+ @Override
+ public CorrelationVector[] newArray(int size) {
+ return new CorrelationVector[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return "CorrelationVector{"
+ + "FrequencyOffsetMetersPerSecond=" + mFrequencyOffsetMetersPerSecond
+ + ", SamplingWidthMeters=" + mSamplingWidthMeters
+ + ", SamplingStartMeters=" + mSamplingStartMeters
+ + ", Magnitude=" + Arrays.toString(mMagnitude)
+ + '}';
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeDouble(mSamplingWidthMeters);
+ dest.writeDouble(mSamplingStartMeters);
+ dest.writeInt(mFrequencyOffsetMetersPerSecond);
+ dest.writeInt(mMagnitude.length);
+ dest.writeIntArray(mMagnitude);
+ }
+
+ /**
+ * Returns true if this {@link CorrelationVector} is equivalent to the given object.
+ * Returns false otherwise.
+ */
+ @Override
+ public boolean equals(Object object) {
+ if (object == this) {
+ return true;
+ }
+ if (!(object instanceof CorrelationVector)) {
+ return false;
+ }
+ CorrelationVector c = (CorrelationVector) object;
+ return Arrays.equals(mMagnitude, c.getMagnitude())
+ && Double.compare(mSamplingWidthMeters, c.getSamplingWidthMeters()) == 0
+ && Double.compare(mSamplingStartMeters, c.getSamplingStartMeters()) == 0
+ && Integer.compare(mFrequencyOffsetMetersPerSecond,
+ c.getFrequencyOffsetMetersPerSecond()) == 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSamplingWidthMeters, mSamplingStartMeters,
+ mFrequencyOffsetMetersPerSecond, Arrays.hashCode(mMagnitude));
+ }
+
+ /**
+ * Builder class for CorrelationVector.
+ */
+ public static final class Builder {
+
+ private double mSamplingWidthMeters;
+ private double mSamplingStartMeters;
+ private int mFrequencyOffsetMetersPerSecond;
+ @NonNull private int[] mMagnitude;
+
+ /** Sets the space between correlation samples in meters. */
+ @NonNull
+ public Builder setSamplingWidthMeters(
+ @FloatRange(from = 0.0f, fromInclusive = false) double samplingWidthMeters) {
+ mSamplingWidthMeters = samplingWidthMeters;
+ return this;
+ }
+
+ /** Sets the offset of the first sampling bin in meters. */
+ @NonNull
+ public Builder setSamplingStartMeters(@FloatRange(from = 0.0f) double samplingStartMeters) {
+ mSamplingStartMeters = samplingStartMeters;
+ return this;
+ }
+
+ /** Sets the frequency offset from reported pseudorange rate for this CorrelationVector */
+ @NonNull
+ public Builder setFrequencyOffsetMetersPerSecond(
+ @IntRange(from = 0) int frequencyOffsetMetersPerSecond) {
+ mFrequencyOffsetMetersPerSecond = frequencyOffsetMetersPerSecond;
+ return this;
+ }
+
+ /** Sets the data array representing normalized correlation magnitude values. */
+ @NonNull
+ public Builder setMagnitude(@NonNull int[] magnitude) {
+ mMagnitude = magnitude;
+ return this;
+ }
+
+ /**
+ * Build CorrelationVector object.
+ *
+ * @return instance of CorrelationVector
+ */
+ @NonNull
+ public CorrelationVector build() {
+ return new CorrelationVector(this);
+ }
+ }
+}
diff --git a/location/java/android/location/GnssCapabilities.java b/location/java/android/location/GnssCapabilities.java
index b650a9f..a5e2815 100644
--- a/location/java/android/location/GnssCapabilities.java
+++ b/location/java/android/location/GnssCapabilities.java
@@ -58,6 +58,8 @@
/** @hide */
public static final int TOP_HAL_CAPABILITY_ANTENNA_INFO = 2048;
/** @hide */
+ public static final int TOP_HAL_CAPABILITY_CORRELATION_VECTOR = 4096;
+ /** @hide */
public static final int TOP_HAL_CAPABILITY_SATELLITE_PVT = 8192;
/** @hide */
@@ -67,7 +69,8 @@
TOP_HAL_CAPABILITY_MEASUREMENTS, TOP_HAL_CAPABILITY_NAV_MESSAGES,
TOP_HAL_CAPABILITY_LOW_POWER_MODE, TOP_HAL_CAPABILITY_SATELLITE_BLOCKLIST,
TOP_HAL_CAPABILITY_MEASUREMENT_CORRECTIONS, TOP_HAL_CAPABILITY_ANTENNA_INFO,
- TOP_HAL_CAPABILITY_SATELLITE_PVT})
+ TOP_HAL_CAPABILITY_CORRELATION_VECTOR, TOP_HAL_CAPABILITY_SATELLITE_PVT})
+
@Retention(RetentionPolicy.SOURCE)
public @interface TopHalCapabilityFlags {}
@@ -337,6 +340,17 @@
}
/**
+ * Returns {@code true} if GNSS chipset supports correlation vectors as part of measurements
+ * outputs, {@code false} otherwise.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean hasMeasurementCorrelationVectors() {
+ return (mTopFlags & TOP_HAL_CAPABILITY_CORRELATION_VECTOR) != 0;
+ }
+
+ /**
* Returns {@code true} if GNSS chipset supports line-of-sight satellite identification
* measurement corrections, {@code false} otherwise.
*
@@ -533,6 +547,9 @@
if (hasAntennaInfo()) {
builder.append("ANTENNA_INFO ");
}
+ if (hasMeasurementCorrelationVectors()) {
+ builder.append("MEASUREMENT_CORRELATION_VECTORS ");
+ }
if (hasMeasurementCorrectionsLosSats()) {
builder.append("LOS_SATS ");
}
@@ -720,6 +737,17 @@
}
/**
+ * Sets correlation vector capability.
+ *
+ * @hide
+ */
+ @SystemApi
+ public @NonNull Builder setHasMeasurementCorrelationVectors(boolean capable) {
+ mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_CORRELATION_VECTOR, capable);
+ return this;
+ }
+
+ /**
* Sets measurement corrections line-of-sight satellites capabilitity.
*
* @hide
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index 5509a6c6..3d188c0 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -38,6 +38,9 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
/**
* A class representing a GNSS satellite measurement, containing raw and computed information.
@@ -70,6 +73,7 @@
private double mSatelliteInterSignalBiasNanos;
private double mSatelliteInterSignalBiasUncertaintyNanos;
@Nullable private SatellitePvt mSatellitePvt;
+ @Nullable private Collection<CorrelationVector> mReadOnlyCorrelationVectors;
// The following enumerations must be in sync with the values declared in GNSS HAL.
@@ -77,6 +81,7 @@
private static final int HAS_CODE_TYPE = (1 << 14);
private static final int HAS_BASEBAND_CN0 = (1 << 15);
private static final int HAS_SATELLITE_PVT = (1 << 20);
+ private static final int HAS_CORRELATION_VECTOR = (1 << 21);
/**
* The status of the multipath indicator.
@@ -173,8 +178,8 @@
* @hide
*/
@IntDef(flag = true, prefix = { "ADR_STATE_" }, value = {
- ADR_STATE_VALID, ADR_STATE_RESET, ADR_STATE_CYCLE_SLIP, ADR_STATE_HALF_CYCLE_RESOLVED,
- ADR_STATE_HALF_CYCLE_REPORTED
+ ADR_STATE_UNKNOWN, ADR_STATE_VALID, ADR_STATE_RESET, ADR_STATE_CYCLE_SLIP,
+ ADR_STATE_HALF_CYCLE_RESOLVED, ADR_STATE_HALF_CYCLE_REPORTED
})
@Retention(RetentionPolicy.SOURCE)
public @interface AdrState {}
@@ -279,6 +284,7 @@
mSatelliteInterSignalBiasUncertaintyNanos =
measurement.mSatelliteInterSignalBiasUncertaintyNanos;
mSatellitePvt = measurement.mSatellitePvt;
+ mReadOnlyCorrelationVectors = measurement.mReadOnlyCorrelationVectors;
}
/**
@@ -1712,6 +1718,7 @@
*
* <p>The value is only available if {@link #hasSatellitePvt()} is
* {@code true}.
+ *
* @hide
*/
@Nullable
@@ -1745,6 +1752,58 @@
resetFlag(HAS_SATELLITE_PVT);
}
+ /**
+ * Returns {@code true} if {@link #getCorrelationVectors()} is available,
+ * {@code false} otherwise.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean hasCorrelationVectors() {
+ return isFlagSet(HAS_CORRELATION_VECTOR);
+ }
+
+ /**
+ * Gets read-only collection of CorrelationVector with each CorrelationVector corresponding to a
+ * frequency offset.
+ *
+ * <p>To represent correlation values over a 2D spaces (delay and frequency), a
+ * CorrelationVector is required per frequency offset, and each CorrelationVector contains
+ * correlation values at equally spaced spatial offsets.
+ *
+ * @hide
+ */
+ @Nullable
+ @SystemApi
+ public Collection<CorrelationVector> getCorrelationVectors() {
+ return mReadOnlyCorrelationVectors;
+ }
+
+ /**
+ * Sets the CorrelationVectors.
+ *
+ * @hide
+ */
+ @TestApi
+ public void setCorrelationVectors(@Nullable Collection<CorrelationVector> correlationVectors) {
+ if (correlationVectors == null || correlationVectors.isEmpty()) {
+ resetCorrelationVectors();
+ } else {
+ setFlag(HAS_CORRELATION_VECTOR);
+ mReadOnlyCorrelationVectors = Collections.unmodifiableCollection(correlationVectors);
+ }
+ }
+
+ /**
+ * Resets the CorrelationVectors.
+ *
+ * @hide
+ */
+ @TestApi
+ public void resetCorrelationVectors() {
+ resetFlag(HAS_CORRELATION_VECTOR);
+ mReadOnlyCorrelationVectors = null;
+ }
public static final @NonNull Creator<GnssMeasurement> CREATOR = new Creator<GnssMeasurement>() {
@Override
@@ -1781,6 +1840,15 @@
ClassLoader classLoader = getClass().getClassLoader();
gnssMeasurement.mSatellitePvt = parcel.readParcelable(classLoader);
}
+ if (gnssMeasurement.hasCorrelationVectors()) {
+ CorrelationVector[] correlationVectorsArray =
+ new CorrelationVector[parcel.readInt()];
+ parcel.readTypedArray(correlationVectorsArray, CorrelationVector.CREATOR);
+ Collection<CorrelationVector> corrVecCollection =
+ Arrays.asList(correlationVectorsArray);
+ gnssMeasurement.mReadOnlyCorrelationVectors =
+ Collections.unmodifiableCollection(corrVecCollection);
+ }
return gnssMeasurement;
}
@@ -1821,6 +1889,13 @@
if (hasSatellitePvt()) {
parcel.writeParcelable(mSatellitePvt, flags);
}
+ if (hasCorrelationVectors()) {
+ int correlationVectorCount = mReadOnlyCorrelationVectors.size();
+ CorrelationVector[] correlationVectorArray =
+ mReadOnlyCorrelationVectors.toArray(new CorrelationVector[correlationVectorCount]);
+ parcel.writeInt(correlationVectorArray.length);
+ parcel.writeTypedArray(correlationVectorArray, flags);
+ }
}
@Override
@@ -1928,6 +2003,13 @@
builder.append(mSatellitePvt.toString());
}
+ if (hasCorrelationVectors()) {
+ for (CorrelationVector correlationVector : mReadOnlyCorrelationVectors) {
+ builder.append(correlationVector.toString());
+ builder.append("\n");
+ }
+ }
+
return builder.toString();
}
@@ -1958,6 +2040,7 @@
resetSatelliteInterSignalBiasNanos();
resetSatelliteInterSignalBiasUncertaintyNanos();
resetSatellitePvt();
+ resetCorrelationVectors();
}
private void setFlag(int flag) {
diff --git a/location/java/android/location/GnssMeasurementRequest.java b/location/java/android/location/GnssMeasurementRequest.java
index 613f591..f509252 100644
--- a/location/java/android/location/GnssMeasurementRequest.java
+++ b/location/java/android/location/GnssMeasurementRequest.java
@@ -17,20 +17,38 @@
package android.location;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.Objects;
+
/**
* This class contains extra parameters to pass in a GNSS measurement request.
*/
public final class GnssMeasurementRequest implements Parcelable {
+ private final boolean mCorrelationVectorOutputsEnabled;
private final boolean mFullTracking;
/**
* Creates a {@link GnssMeasurementRequest} with a full list of parameters.
*/
- private GnssMeasurementRequest(boolean fullTracking) {
+ private GnssMeasurementRequest(boolean fullTracking, boolean correlationVectorOutputsEnabled) {
mFullTracking = fullTracking;
+ mCorrelationVectorOutputsEnabled = correlationVectorOutputsEnabled;
+ }
+
+ /**
+ * Represents whether to enable correlation vector outputs.
+ *
+ * <p>If true, enable correlation vectors as part of the raw GNSS measurements outputs.
+ * If false, disable correlation vectors.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean isCorrelationVectorOutputsEnabled() {
+ return mCorrelationVectorOutputsEnabled;
}
/**
@@ -56,7 +74,7 @@
@Override
@NonNull
public GnssMeasurementRequest createFromParcel(@NonNull Parcel parcel) {
- return new GnssMeasurementRequest(parcel.readBoolean());
+ return new GnssMeasurementRequest(parcel.readBoolean(), parcel.readBoolean());
}
@Override
@@ -68,6 +86,7 @@
@Override
public void writeToParcel(@NonNull Parcel parcel, int flags) {
parcel.writeBoolean(mFullTracking);
+ parcel.writeBoolean(mCorrelationVectorOutputsEnabled);
}
@NonNull
@@ -78,6 +97,9 @@
if (mFullTracking) {
s.append("FullTracking");
}
+ if (mCorrelationVectorOutputsEnabled) {
+ s.append(", CorrelationVectorOutPuts");
+ }
s.append(']');
return s.toString();
}
@@ -90,13 +112,15 @@
GnssMeasurementRequest other = (GnssMeasurementRequest) obj;
if (mFullTracking != other.mFullTracking) return false;
-
+ if (mCorrelationVectorOutputsEnabled != other.mCorrelationVectorOutputsEnabled) {
+ return false;
+ }
return true;
}
@Override
public int hashCode() {
- return mFullTracking ? 1 : 0;
+ return Objects.hash(mFullTracking, mCorrelationVectorOutputsEnabled);
}
@Override
@@ -106,6 +130,7 @@
/** Builder for {@link GnssMeasurementRequest} */
public static final class Builder {
+ private boolean mCorrelationVectorOutputsEnabled;
private boolean mFullTracking;
/**
@@ -118,10 +143,25 @@
* Constructs a {@link Builder} instance by copying a {@link GnssMeasurementRequest}.
*/
public Builder(@NonNull GnssMeasurementRequest request) {
+ mCorrelationVectorOutputsEnabled = request.isCorrelationVectorOutputsEnabled();
mFullTracking = request.isFullTracking();
}
/**
+ * Set the value of whether to enable correlation vector outputs, which is false by default.
+ *
+ * <p>If true, enable correlation vectors as part of the raw GNSS measurements outputs.
+ * If false, disable correlation vectors.
+ *
+ * @hide
+ */
+ @SystemApi
+ @NonNull public Builder setCorrelationVectorOutputsEnabled(boolean value) {
+ mCorrelationVectorOutputsEnabled = value;
+ return this;
+ }
+
+ /**
* Set the value of whether to enable full GNSS tracking, which is false by default.
*
* <p>If true, GNSS chipset switches off duty cycling. In such a mode, no clock
@@ -146,7 +186,7 @@
/** Builds a {@link GnssMeasurementRequest} instance as specified by this builder. */
@NonNull
public GnssMeasurementRequest build() {
- return new GnssMeasurementRequest(mFullTracking);
+ return new GnssMeasurementRequest(mFullTracking, mCorrelationVectorOutputsEnabled);
}
}
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 2dc9eb4..0ce1ad0 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -3171,7 +3171,9 @@
for (GnssMeasurementRequest request : requests) {
if (request.isFullTracking()) {
builder.setFullTracking(true);
- break;
+ }
+ if (request.isCorrelationVectorOutputsEnabled()) {
+ builder.setCorrelationVectorOutputsEnabled(true);
}
}
diff --git a/location/java/android/location/LocationManagerInternal.java b/location/java/android/location/LocationManagerInternal.java
index 1027f9c..a6a0e7a 100644
--- a/location/java/android/location/LocationManagerInternal.java
+++ b/location/java/android/location/LocationManagerInternal.java
@@ -80,4 +80,12 @@
*/
// TODO: there is no reason for this to exist as part of any API. move all the logic into gnss
public abstract void sendNiResponse(int notifId, int userResponse);
+
+ /**
+ * Returns the GNSS provided time.
+ *
+ * @return LocationTime object that includes the current time, according to the GNSS location
+ * provider, and the elapsed nanos since boot the current time was computed at.
+ */
+ public abstract @Nullable LocationTime getGnssTimeMillis();
}
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 221147d..0c73348 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -218,7 +218,7 @@
/** @return an error string if the format would not allow Privileged playbackCapture
* null otherwise
* @hide */
- public static String canBeUsedForPrivilegedCapture(AudioFormat format) {
+ public static String canBeUsedForPrivilegedMediaCapture(AudioFormat format) {
int sampleRate = format.getSampleRate();
if (sampleRate > PRIVILEDGED_CAPTURE_MAX_SAMPLE_RATE || sampleRate <= 0) {
return "Privileged audio capture sample rate " + sampleRate
@@ -448,8 +448,8 @@
}
}
}
- if (mRule.allowPrivilegedPlaybackCapture()) {
- String error = AudioMix.canBeUsedForPrivilegedCapture(mFormat);
+ if (mRule.allowPrivilegedMediaPlaybackCapture()) {
+ String error = AudioMix.canBeUsedForPrivilegedMediaCapture(mFormat);
if (error != null) {
throw new IllegalArgumentException(error);
}
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index de15313..1f07705 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -46,11 +46,11 @@
public class AudioMixingRule {
private AudioMixingRule(int mixType, ArrayList<AudioMixMatchCriterion> criteria,
- boolean allowPrivilegedPlaybackCapture,
+ boolean allowPrivilegedMediaPlaybackCapture,
boolean voiceCommunicationCaptureAllowed) {
mCriteria = criteria;
mTargetMixType = mixType;
- mAllowPrivilegedPlaybackCapture = allowPrivilegedPlaybackCapture;
+ mAllowPrivilegedPlaybackCapture = allowPrivilegedMediaPlaybackCapture;
mVoiceCommunicationCaptureAllowed = voiceCommunicationCaptureAllowed;
}
@@ -204,13 +204,17 @@
private final ArrayList<AudioMixMatchCriterion> mCriteria;
/** @hide */
public ArrayList<AudioMixMatchCriterion> getCriteria() { return mCriteria; }
+ /** Indicates that this rule is intended to capture media or game playback by a system component
+ * with permission CAPTURE_MEDIA_OUTPUT or CAPTURE_AUDIO_OUTPUT.
+ */
+ //TODO b/177061175: rename to mAllowPrivilegedMediaPlaybackCapture
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private boolean mAllowPrivilegedPlaybackCapture = false;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private boolean mVoiceCommunicationCaptureAllowed = false;
/** @hide */
- public boolean allowPrivilegedPlaybackCapture() {
+ public boolean allowPrivilegedMediaPlaybackCapture() {
return mAllowPrivilegedPlaybackCapture;
}
@@ -311,7 +315,7 @@
public static class Builder {
private ArrayList<AudioMixMatchCriterion> mCriteria;
private int mTargetMixType = AudioMix.MIX_TYPE_INVALID;
- private boolean mAllowPrivilegedPlaybackCapture = false;
+ private boolean mAllowPrivilegedMediaPlaybackCapture = false;
// This value should be set internally according to a permission check
private boolean mVoiceCommunicationCaptureAllowed = false;
@@ -434,7 +438,7 @@
* @return the same Builder instance.
*/
public @NonNull Builder allowPrivilegedPlaybackCapture(boolean allow) {
- mAllowPrivilegedPlaybackCapture = allow;
+ mAllowPrivilegedMediaPlaybackCapture = allow;
return this;
}
@@ -639,7 +643,7 @@
*/
public AudioMixingRule build() {
return new AudioMixingRule(mTargetMixType, mCriteria,
- mAllowPrivilegedPlaybackCapture, mVoiceCommunicationCaptureAllowed);
+ mAllowPrivilegedMediaPlaybackCapture, mVoiceCommunicationCaptureAllowed);
}
}
}
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index 697d80c..ede68bd 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -97,7 +97,7 @@
dest.writeInt(mix.getFormat().getEncoding());
dest.writeInt(mix.getFormat().getChannelMask());
// write opt-out respect
- dest.writeBoolean(mix.getRule().allowPrivilegedPlaybackCapture());
+ dest.writeBoolean(mix.getRule().allowPrivilegedMediaPlaybackCapture());
// write voice communication capture allowed flag
dest.writeBoolean(mix.getRule().voiceCommunicationCaptureAllowed());
// write mix rules
@@ -172,7 +172,7 @@
textDump += " channels=0x";
textDump += Integer.toHexString(mix.getFormat().getChannelMask()).toUpperCase() + "\n";
textDump += " ignore playback capture opt out="
- + mix.getRule().allowPrivilegedPlaybackCapture() + "\n";
+ + mix.getRule().allowPrivilegedMediaPlaybackCapture() + "\n";
textDump += " allow voice communication capture="
+ mix.getRule().voiceCommunicationCaptureAllowed() + "\n";
// write mix rules
diff --git a/media/java/android/media/metrics/IPlaybackMetricsManager.aidl b/media/java/android/media/metrics/IPlaybackMetricsManager.aidl
index 47debe9..52d952c 100644
--- a/media/java/android/media/metrics/IPlaybackMetricsManager.aidl
+++ b/media/java/android/media/metrics/IPlaybackMetricsManager.aidl
@@ -16,7 +16,10 @@
package android.media.metrics;
+import android.media.metrics.NetworkEvent;
+import android.media.metrics.PlaybackErrorEvent;
import android.media.metrics.PlaybackMetrics;
+import android.media.metrics.PlaybackStateEvent;
/**
* Interface to the playback manager service.
@@ -25,4 +28,7 @@
interface IPlaybackMetricsManager {
void reportPlaybackMetrics(in String sessionId, in PlaybackMetrics metrics, int userId);
String getSessionId(int userId);
+ void reportNetworkEvent(in String sessionId, in NetworkEvent event, int userId);
+ void reportPlaybackErrorEvent(in String sessionId, in PlaybackErrorEvent event, int userId);
+ void reportPlaybackStateEvent(in String sessionId, in PlaybackStateEvent event, int userId);
}
\ No newline at end of file
diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl b/media/java/android/media/metrics/NetworkEvent.aidl
similarity index 64%
copy from media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
copy to media/java/android/media/metrics/NetworkEvent.aidl
index edf96dd..2b7fa02 100644
--- a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
+++ b/media/java/android/media/metrics/NetworkEvent.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,6 @@
* limitations under the License.
*/
-package android.media.tv.tunerresourcemanager;
+package android.media.metrics;
-/**
- * Simple container of the FrontendInfo struct defined in the TunerHAL 1.0 interface.
- *
- * @hide
- */
-parcelable TunerFrontendInfo {
- int handle;
-
- int frontendType;
-
- int exclusiveGroupId;
-}
+parcelable NetworkEvent;
diff --git a/media/java/android/media/metrics/NetworkEvent.java b/media/java/android/media/metrics/NetworkEvent.java
new file mode 100644
index 0000000..a330bc0
--- /dev/null
+++ b/media/java/android/media/metrics/NetworkEvent.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.metrics;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Playback network event.
+ * @hide
+ */
+public final class NetworkEvent implements Parcelable {
+ public static final int NETWORK_TYPE_NONE = 0;
+ public static final int NETWORK_TYPE_OTHER = 1;
+ public static final int NETWORK_TYPE_WIFI = 2;
+ public static final int NETWORK_TYPE_ETHERNET = 3;
+ public static final int NETWORK_TYPE_2G = 4;
+ public static final int NETWORK_TYPE_3G = 5;
+ public static final int NETWORK_TYPE_4G = 6;
+ public static final int NETWORK_TYPE_5G_NSA = 7;
+ public static final int NETWORK_TYPE_5G_SA = 8;
+
+ private final int mType;
+ private final long mTimeSincePlaybackCreatedMillis;
+
+ /** @hide */
+ @IntDef(prefix = "NETWORK_TYPE_", value = {
+ NETWORK_TYPE_NONE,
+ NETWORK_TYPE_OTHER,
+ NETWORK_TYPE_WIFI,
+ NETWORK_TYPE_ETHERNET,
+ NETWORK_TYPE_2G,
+ NETWORK_TYPE_3G,
+ NETWORK_TYPE_4G,
+ NETWORK_TYPE_5G_NSA,
+ NETWORK_TYPE_5G_SA
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface NetworkType {}
+
+ /**
+ * Network type to string.
+ */
+ public static String networkTypeToString(@NetworkType int value) {
+ switch (value) {
+ case NETWORK_TYPE_NONE:
+ return "NETWORK_TYPE_NONE";
+ case NETWORK_TYPE_OTHER:
+ return "NETWORK_TYPE_OTHER";
+ case NETWORK_TYPE_WIFI:
+ return "NETWORK_TYPE_WIFI";
+ case NETWORK_TYPE_ETHERNET:
+ return "NETWORK_TYPE_ETHERNET";
+ case NETWORK_TYPE_2G:
+ return "NETWORK_TYPE_2G";
+ case NETWORK_TYPE_3G:
+ return "NETWORK_TYPE_3G";
+ case NETWORK_TYPE_4G:
+ return "NETWORK_TYPE_4G";
+ case NETWORK_TYPE_5G_NSA:
+ return "NETWORK_TYPE_5G_NSA";
+ case NETWORK_TYPE_5G_SA:
+ return "NETWORK_TYPE_5G_SA";
+ default:
+ return Integer.toHexString(value);
+ }
+ }
+
+ /**
+ * Creates a new NetworkEvent.
+ *
+ * @hide
+ */
+ public NetworkEvent(@NetworkType int type, long timeSincePlaybackCreatedMillis) {
+ this.mType = type;
+ this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ }
+
+ @NetworkType
+ public int getType() {
+ return mType;
+ }
+
+ public long getTimeSincePlaybackCreatedMillis() {
+ return mTimeSincePlaybackCreatedMillis;
+ }
+
+ @Override
+ public String toString() {
+ return "NetworkEvent { "
+ + "type = " + mType + ", "
+ + "timeSincePlaybackCreatedMillis = " + mTimeSincePlaybackCreatedMillis
+ + " }";
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ NetworkEvent that = (NetworkEvent) o;
+ return mType == that.mType
+ && mTimeSincePlaybackCreatedMillis == that.mTimeSincePlaybackCreatedMillis;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mType, mTimeSincePlaybackCreatedMillis);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ dest.writeInt(mType);
+ dest.writeLong(mTimeSincePlaybackCreatedMillis);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** @hide */
+ /* package-private */ NetworkEvent(@NonNull android.os.Parcel in) {
+ int type = in.readInt();
+ long timeSincePlaybackCreatedMillis = in.readLong();
+
+ this.mType = type;
+ this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ }
+
+ public static final @NonNull Parcelable.Creator<NetworkEvent> CREATOR =
+ new Parcelable.Creator<NetworkEvent>() {
+ @Override
+ public NetworkEvent[] newArray(int size) {
+ return new NetworkEvent[size];
+ }
+
+ @Override
+ public NetworkEvent createFromParcel(@NonNull Parcel in) {
+ return new NetworkEvent(in);
+ }
+ };
+
+ /**
+ * A builder for {@link NetworkEvent}
+ */
+ public static final class Builder {
+ private int mType;
+ private long mTimeSincePlaybackCreatedMillis;
+
+ /**
+ * Creates a new Builder.
+ *
+ * @hide
+ */
+ public Builder() {
+ }
+
+ /**
+ * Sets network type.
+ */
+ public @NonNull Builder setType(@NetworkType int value) {
+ mType = value;
+ return this;
+ }
+
+ /**
+ * Sets timestamp since the creation in milliseconds.
+ */
+ public @NonNull Builder setTimeSincePlaybackCreatedMillis(long value) {
+ mTimeSincePlaybackCreatedMillis = value;
+ return this;
+ }
+
+ /** Builds the instance. */
+ public @NonNull NetworkEvent build() {
+ NetworkEvent o = new NetworkEvent(
+ mType,
+ mTimeSincePlaybackCreatedMillis);
+ return o;
+ }
+ }
+}
diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl b/media/java/android/media/metrics/PlaybackErrorEvent.aidl
similarity index 64%
copy from media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
copy to media/java/android/media/metrics/PlaybackErrorEvent.aidl
index edf96dd..b0d6b4b 100644
--- a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
+++ b/media/java/android/media/metrics/PlaybackErrorEvent.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,6 @@
* limitations under the License.
*/
-package android.media.tv.tunerresourcemanager;
+package android.media.metrics;
-/**
- * Simple container of the FrontendInfo struct defined in the TunerHAL 1.0 interface.
- *
- * @hide
- */
-parcelable TunerFrontendInfo {
- int handle;
-
- int frontendType;
-
- int exclusiveGroupId;
-}
+parcelable PlaybackErrorEvent;
diff --git a/media/java/android/media/metrics/PlaybackErrorEvent.java b/media/java/android/media/metrics/PlaybackErrorEvent.java
new file mode 100644
index 0000000..db70005
--- /dev/null
+++ b/media/java/android/media/metrics/PlaybackErrorEvent.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.metrics;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.util.Objects;
+
+/**
+ * Playback error event.
+ * @hide
+ */
+public final class PlaybackErrorEvent implements Parcelable {
+ public static final int ERROR_CODE_UNKNOWN = 0;
+ public static final int ERROR_CODE_OTHER = 1;
+ public static final int ERROR_CODE_RUNTIME = 2;
+
+ private final @Nullable String mExceptionStack;
+ private final int mErrorCode;
+ private final int mSubErrorCode;
+ private final long mTimeSincePlaybackCreatedMillis;
+
+
+ /** @hide */
+ // TODO: more error types
+ @IntDef(prefix = "ERROR_CODE_", value = {
+ ERROR_CODE_UNKNOWN,
+ ERROR_CODE_OTHER,
+ ERROR_CODE_RUNTIME
+ })
+ @Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+ public @interface ErrorCode {}
+
+ /**
+ * Creates a new PlaybackErrorEvent.
+ *
+ * @hide
+ */
+ public PlaybackErrorEvent(
+ @Nullable String exceptionStack,
+ int errorCode,
+ int subErrorCode,
+ long timeSincePlaybackCreatedMillis) {
+ this.mExceptionStack = exceptionStack;
+ this.mErrorCode = errorCode;
+ this.mSubErrorCode = subErrorCode;
+ this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ }
+
+ /** @hide */
+ @Nullable
+ public String getExceptionStack() {
+ return mExceptionStack;
+ }
+
+ @ErrorCode
+ public int getErrorCode() {
+ return mErrorCode;
+ }
+
+ public int getSubErrorCode() {
+ return mSubErrorCode;
+ }
+
+ public long getTimeSincePlaybackCreatedMillis() {
+ return mTimeSincePlaybackCreatedMillis;
+ }
+
+ @Override
+ public String toString() {
+ return "PlaybackErrorEvent { "
+ + "exceptionStack = " + mExceptionStack + ", "
+ + "errorCode = " + mErrorCode + ", "
+ + "subErrorCode = " + mSubErrorCode + ", "
+ + "timeSincePlaybackCreatedMillis = " + mTimeSincePlaybackCreatedMillis
+ + " }";
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ PlaybackErrorEvent that = (PlaybackErrorEvent) o;
+ return Objects.equals(mExceptionStack, that.mExceptionStack)
+ && mErrorCode == that.mErrorCode
+ && mSubErrorCode == that.mSubErrorCode
+ && mTimeSincePlaybackCreatedMillis == that.mTimeSincePlaybackCreatedMillis;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mExceptionStack, mErrorCode, mSubErrorCode,
+ mTimeSincePlaybackCreatedMillis);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ byte flg = 0;
+ if (mExceptionStack != null) flg |= 0x1;
+ dest.writeByte(flg);
+ if (mExceptionStack != null) dest.writeString(mExceptionStack);
+ dest.writeInt(mErrorCode);
+ dest.writeInt(mSubErrorCode);
+ dest.writeLong(mTimeSincePlaybackCreatedMillis);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** @hide */
+ /* package-private */ PlaybackErrorEvent(@NonNull Parcel in) {
+ byte flg = in.readByte();
+ String exceptionStack = (flg & 0x1) == 0 ? null : in.readString();
+ int errorCode = in.readInt();
+ int subErrorCode = in.readInt();
+ long timeSincePlaybackCreatedMillis = in.readLong();
+
+ this.mExceptionStack = exceptionStack;
+ this.mErrorCode = errorCode;
+ this.mSubErrorCode = subErrorCode;
+ this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ }
+
+ public static final @NonNull Parcelable.Creator<PlaybackErrorEvent> CREATOR =
+ new Parcelable.Creator<PlaybackErrorEvent>() {
+ @Override
+ public PlaybackErrorEvent[] newArray(int size) {
+ return new PlaybackErrorEvent[size];
+ }
+
+ @Override
+ public PlaybackErrorEvent createFromParcel(@NonNull Parcel in) {
+ return new PlaybackErrorEvent(in);
+ }
+ };
+
+ /**
+ * A builder for {@link PlaybackErrorEvent}
+ */
+ public static final class Builder {
+ private @Nullable Exception mException;
+ private int mErrorCode;
+ private int mSubErrorCode;
+ private long mTimeSincePlaybackCreatedMillis;
+
+ /**
+ * Creates a new Builder.
+ *
+ * @hide
+ */
+ public Builder(
+ @Nullable Exception exception,
+ int errorCode,
+ int subErrorCode,
+ long timeSincePlaybackCreatedMillis) {
+ mException = exception;
+ mErrorCode = errorCode;
+ mSubErrorCode = subErrorCode;
+ mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ }
+
+ /**
+ * Sets the {@link Exception} object.
+ */
+ public @NonNull Builder setException(@NonNull Exception value) {
+ mException = value;
+ return this;
+ }
+
+ /**
+ * Sets error code.
+ */
+ public @NonNull Builder setErrorCode(@ErrorCode int value) {
+ mErrorCode = value;
+ return this;
+ }
+
+ /**
+ * Sets sub error code.
+ */
+ public @NonNull Builder setSubErrorCode(int value) {
+ mSubErrorCode = value;
+ return this;
+ }
+
+ /**
+ * Set the timestamp in milliseconds.
+ */
+ public @NonNull Builder setTimeSincePlaybackCreatedMillis(long value) {
+ mTimeSincePlaybackCreatedMillis = value;
+ return this;
+ }
+
+ /** Builds the instance. */
+ public @NonNull PlaybackErrorEvent build() {
+
+ String stack;
+ if (mException.getStackTrace() != null && mException.getStackTrace().length > 0) {
+ // TODO: a better definition of the stack trace
+ stack = mException.getStackTrace()[0].toString();
+ } else {
+ stack = null;
+ }
+
+ PlaybackErrorEvent o = new PlaybackErrorEvent(
+ stack,
+ mErrorCode,
+ mSubErrorCode,
+ mTimeSincePlaybackCreatedMillis);
+ return o;
+ }
+ }
+}
diff --git a/media/java/android/media/metrics/PlaybackMetrics.java b/media/java/android/media/metrics/PlaybackMetrics.java
index 82a5803..070b4e4 100644
--- a/media/java/android/media/metrics/PlaybackMetrics.java
+++ b/media/java/android/media/metrics/PlaybackMetrics.java
@@ -16,11 +16,19 @@
package android.media.metrics;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.util.AnnotationValidations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import java.util.Objects;
/**
@@ -28,38 +36,323 @@
* @hide
*/
public final class PlaybackMetrics implements Parcelable {
- private int mStreamSourceType;
+ // TODO(b/177209128): JavaDoc for the constants.
+ public static final int STREAM_SOURCE_UNKNOWN = 0;
+ public static final int STREAM_SOURCE_NETWORK = 1;
+ public static final int STREAM_SOURCE_DEVICE = 2;
+ public static final int STREAM_SOURCE_MIXED = 3;
+
+ public static final int STREAM_TYPE_UNKNOWN = 0;
+ public static final int STREAM_TYPE_OTHER = 1;
+ public static final int STREAM_TYPE_PROGRESSIVE = 2;
+ public static final int STREAM_TYPE_DASH = 3;
+ public static final int STREAM_TYPE_HLS = 4;
+ public static final int STREAM_TYPE_SS = 5;
+
+ public static final int PLAYBACK_TYPE_VOD = 0;
+ public static final int PLAYBACK_TYPE_LIVE = 1;
+ public static final int PLAYBACK_TYPE_OTHER = 2;
+
+ public static final int DRM_TYPE_NONE = 0;
+ public static final int DRM_TYPE_OTHER = 1;
+ public static final int DRM_TYPE_PLAY_READY = 2;
+ public static final int DRM_TYPE_WIDEVINE_L1 = 3;
+ public static final int DRM_TYPE_WIDEVINE_L3 = 4;
+ // TODO: add DRM_TYPE_CLEARKEY
+
+ public static final int CONTENT_TYPE_MAIN = 0;
+ public static final int CONTENT_TYPE_AD = 1;
+ public static final int CONTENT_TYPE_OTHER = 2;
+
+
+ /** @hide */
+ @IntDef(prefix = "STREAM_SOURCE_", value = {
+ STREAM_SOURCE_UNKNOWN,
+ STREAM_SOURCE_NETWORK,
+ STREAM_SOURCE_DEVICE,
+ STREAM_SOURCE_MIXED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StreamSource {}
+
+ /** @hide */
+ @IntDef(prefix = "STREAM_TYPE_", value = {
+ STREAM_TYPE_UNKNOWN,
+ STREAM_TYPE_OTHER,
+ STREAM_TYPE_PROGRESSIVE,
+ STREAM_TYPE_DASH,
+ STREAM_TYPE_HLS,
+ STREAM_TYPE_SS
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StreamType {}
+
+ /** @hide */
+ @IntDef(prefix = "PLAYBACK_TYPE_", value = {
+ PLAYBACK_TYPE_VOD,
+ PLAYBACK_TYPE_LIVE,
+ PLAYBACK_TYPE_OTHER
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PlaybackType {}
+
+ /** @hide */
+ @IntDef(prefix = "DRM_TYPE_", value = {
+ DRM_TYPE_NONE,
+ DRM_TYPE_OTHER,
+ DRM_TYPE_PLAY_READY,
+ DRM_TYPE_WIDEVINE_L1,
+ DRM_TYPE_WIDEVINE_L3
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DrmType {}
+
+ /** @hide */
+ @IntDef(prefix = "CONTENT_TYPE_", value = {
+ CONTENT_TYPE_MAIN,
+ CONTENT_TYPE_AD,
+ CONTENT_TYPE_OTHER
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ContentType {}
+
+
+
+ private final long mMediaDurationMillis;
+ private final int mStreamSource;
+ private final int mStreamType;
+ private final int mPlaybackType;
+ private final int mDrmType;
+ private final int mContentType;
+ private final @Nullable String mPlayerName;
+ private final @Nullable String mPlayerVersion;
+ private final @NonNull long[] mExperimentIds;
+ private final int mVideoFramesPlayed;
+ private final int mVideoFramesDropped;
+ private final int mAudioUnderrunCount;
+ private final long mNetworkBytesRead;
+ private final long mLocalBytesRead;
+ private final long mNetworkTransferDurationMillis;
/**
* Creates a new PlaybackMetrics.
*
* @hide
*/
- public PlaybackMetrics(int streamSourceType) {
- this.mStreamSourceType = streamSourceType;
+ public PlaybackMetrics(
+ long mediaDurationMillis,
+ int streamSource,
+ int streamType,
+ int playbackType,
+ int drmType,
+ int contentType,
+ @Nullable String playerName,
+ @Nullable String playerVersion,
+ @NonNull long[] experimentIds,
+ int videoFramesPlayed,
+ int videoFramesDropped,
+ int audioUnderrunCount,
+ long networkBytesRead,
+ long localBytesRead,
+ long networkTransferDurationMillis) {
+ this.mMediaDurationMillis = mediaDurationMillis;
+ this.mStreamSource = streamSource;
+ this.mStreamType = streamType;
+ this.mPlaybackType = playbackType;
+ this.mDrmType = drmType;
+ this.mContentType = contentType;
+ this.mPlayerName = playerName;
+ this.mPlayerVersion = playerVersion;
+ this.mExperimentIds = experimentIds;
+ AnnotationValidations.validate(NonNull.class, null, mExperimentIds);
+ this.mVideoFramesPlayed = videoFramesPlayed;
+ this.mVideoFramesDropped = videoFramesDropped;
+ this.mAudioUnderrunCount = audioUnderrunCount;
+ this.mNetworkBytesRead = networkBytesRead;
+ this.mLocalBytesRead = localBytesRead;
+ this.mNetworkTransferDurationMillis = networkTransferDurationMillis;
}
- public int getStreamSourceType() {
- return mStreamSourceType;
+ public long getMediaDurationMillis() {
+ return mMediaDurationMillis;
+ }
+
+ /**
+ * Gets stream source type.
+ */
+ @StreamSource
+ public int getStreamSource() {
+ return mStreamSource;
+ }
+
+ /**
+ * Gets stream type.
+ */
+ @StreamType
+ public int getStreamType() {
+ return mStreamType;
+ }
+
+
+ /**
+ * Gets playback type.
+ */
+ @PlaybackType
+ public int getPlaybackType() {
+ return mPlaybackType;
+ }
+
+ /**
+ * Gets DRM type.
+ */
+ @DrmType
+ public int getDrmType() {
+ return mDrmType;
+ }
+
+ /**
+ * Gets content type.
+ */
+ @ContentType
+ public int getContentType() {
+ return mContentType;
+ }
+
+ /**
+ * Gets player name.
+ */
+ public @Nullable String getPlayerName() {
+ return mPlayerName;
+ }
+
+ /**
+ * Gets player version.
+ */
+ public @Nullable String getPlayerVersion() {
+ return mPlayerVersion;
+ }
+
+ /**
+ * Gets experiment IDs.
+ */
+ public @NonNull long[] getExperimentIds() {
+ return Arrays.copyOf(mExperimentIds, mExperimentIds.length);
+ }
+
+ /**
+ * Gets video frames played.
+ */
+ public int getVideoFramesPlayed() {
+ return mVideoFramesPlayed;
+ }
+
+ /**
+ * Gets video frames dropped.
+ */
+ public int getVideoFramesDropped() {
+ return mVideoFramesDropped;
+ }
+
+ /**
+ * Gets audio underrun count.
+ */
+ public int getAudioUnderrunCount() {
+ return mAudioUnderrunCount;
+ }
+
+ /**
+ * Gets number of network bytes read.
+ */
+ public long getNetworkBytesRead() {
+ return mNetworkBytesRead;
+ }
+
+ /**
+ * Gets number of local bytes read.
+ */
+ public long getLocalBytesRead() {
+ return mLocalBytesRead;
+ }
+
+ /**
+ * Gets network transfer duration in milliseconds.
+ */
+ public long getNetworkTransferDurationMillis() {
+ return mNetworkTransferDurationMillis;
+ }
+
+ @Override
+ public String toString() {
+ return "PlaybackMetrics { "
+ + "mediaDurationMillis = " + mMediaDurationMillis + ", "
+ + "streamSource = " + mStreamSource + ", "
+ + "streamType = " + mStreamType + ", "
+ + "playbackType = " + mPlaybackType + ", "
+ + "drmType = " + mDrmType + ", "
+ + "contentType = " + mContentType + ", "
+ + "playerName = " + mPlayerName + ", "
+ + "playerVersion = " + mPlayerVersion + ", "
+ + "experimentIds = " + Arrays.toString(mExperimentIds) + ", "
+ + "videoFramesPlayed = " + mVideoFramesPlayed + ", "
+ + "videoFramesDropped = " + mVideoFramesDropped + ", "
+ + "audioUnderrunCount = " + mAudioUnderrunCount + ", "
+ + "networkBytesRead = " + mNetworkBytesRead + ", "
+ + "localBytesRead = " + mLocalBytesRead + ", "
+ + "networkTransferDurationMillis = " + mNetworkTransferDurationMillis
+ + " }";
}
@Override
public boolean equals(@Nullable Object o) {
-
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PlaybackMetrics that = (PlaybackMetrics) o;
- return mStreamSourceType == that.mStreamSourceType;
+ return mMediaDurationMillis == that.mMediaDurationMillis
+ && mStreamSource == that.mStreamSource
+ && mStreamType == that.mStreamType
+ && mPlaybackType == that.mPlaybackType
+ && mDrmType == that.mDrmType
+ && mContentType == that.mContentType
+ && Objects.equals(mPlayerName, that.mPlayerName)
+ && Objects.equals(mPlayerVersion, that.mPlayerVersion)
+ && Arrays.equals(mExperimentIds, that.mExperimentIds)
+ && mVideoFramesPlayed == that.mVideoFramesPlayed
+ && mVideoFramesDropped == that.mVideoFramesDropped
+ && mAudioUnderrunCount == that.mAudioUnderrunCount
+ && mNetworkBytesRead == that.mNetworkBytesRead
+ && mLocalBytesRead == that.mLocalBytesRead
+ && mNetworkTransferDurationMillis == that.mNetworkTransferDurationMillis;
}
@Override
public int hashCode() {
- return Objects.hash(mStreamSourceType);
+ return Objects.hash(mMediaDurationMillis, mStreamSource, mStreamType, mPlaybackType,
+ mDrmType, mContentType, mPlayerName, mPlayerVersion, mExperimentIds,
+ mVideoFramesPlayed, mVideoFramesDropped, mAudioUnderrunCount, mNetworkBytesRead,
+ mLocalBytesRead, mNetworkTransferDurationMillis);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mStreamSourceType);
+ long flg = 0;
+ if (mPlayerName != null) flg |= 0x80;
+ if (mPlayerVersion != null) flg |= 0x100;
+ dest.writeLong(flg);
+ dest.writeLong(mMediaDurationMillis);
+ dest.writeInt(mStreamSource);
+ dest.writeInt(mStreamType);
+ dest.writeInt(mPlaybackType);
+ dest.writeInt(mDrmType);
+ dest.writeInt(mContentType);
+ if (mPlayerName != null) dest.writeString(mPlayerName);
+ if (mPlayerVersion != null) dest.writeString(mPlayerVersion);
+ dest.writeLongArray(mExperimentIds);
+ dest.writeInt(mVideoFramesPlayed);
+ dest.writeInt(mVideoFramesDropped);
+ dest.writeInt(mAudioUnderrunCount);
+ dest.writeLong(mNetworkBytesRead);
+ dest.writeLong(mLocalBytesRead);
+ dest.writeLong(mNetworkTransferDurationMillis);
}
@Override
@@ -69,20 +362,231 @@
/** @hide */
/* package-private */ PlaybackMetrics(@NonNull Parcel in) {
- int streamSourceType = in.readInt();
- this.mStreamSourceType = streamSourceType;
+ long flg = in.readLong();
+ long mediaDurationMillis = in.readLong();
+ int streamSource = in.readInt();
+ int streamType = in.readInt();
+ int playbackType = in.readInt();
+ int drmType = in.readInt();
+ int contentType = in.readInt();
+ String playerName = (flg & 0x80) == 0 ? null : in.readString();
+ String playerVersion = (flg & 0x100) == 0 ? null : in.readString();
+ long[] experimentIds = in.createLongArray();
+ int videoFramesPlayed = in.readInt();
+ int videoFramesDropped = in.readInt();
+ int audioUnderrunCount = in.readInt();
+ long networkBytesRead = in.readLong();
+ long localBytesRead = in.readLong();
+ long networkTransferDurationMillis = in.readLong();
+
+ this.mMediaDurationMillis = mediaDurationMillis;
+ this.mStreamSource = streamSource;
+ this.mStreamType = streamType;
+ this.mPlaybackType = playbackType;
+ this.mDrmType = drmType;
+ this.mContentType = contentType;
+ this.mPlayerName = playerName;
+ this.mPlayerVersion = playerVersion;
+ this.mExperimentIds = experimentIds;
+ AnnotationValidations.validate(NonNull.class, null, mExperimentIds);
+ this.mVideoFramesPlayed = videoFramesPlayed;
+ this.mVideoFramesDropped = videoFramesDropped;
+ this.mAudioUnderrunCount = audioUnderrunCount;
+ this.mNetworkBytesRead = networkBytesRead;
+ this.mLocalBytesRead = localBytesRead;
+ this.mNetworkTransferDurationMillis = networkTransferDurationMillis;
}
public static final @NonNull Parcelable.Creator<PlaybackMetrics> CREATOR =
new Parcelable.Creator<PlaybackMetrics>() {
- @Override
- public PlaybackMetrics[] newArray(int size) {
- return new PlaybackMetrics[size];
- }
+ @Override
+ public PlaybackMetrics[] newArray(int size) {
+ return new PlaybackMetrics[size];
+ }
- @Override
- public PlaybackMetrics createFromParcel(@NonNull Parcel in) {
- return new PlaybackMetrics(in);
- }
- };
+ @Override
+ public PlaybackMetrics createFromParcel(@NonNull Parcel in) {
+ return new PlaybackMetrics(in);
+ }
+ };
+
+ /**
+ * A builder for {@link PlaybackMetrics}
+ */
+ public static final class Builder {
+
+ private long mMediaDurationMillis;
+ private int mStreamSource;
+ private int mStreamType;
+ private int mPlaybackType;
+ private int mDrmType;
+ private int mContentType;
+ private @Nullable String mPlayerName;
+ private @Nullable String mPlayerVersion;
+ private @NonNull List<Long> mExperimentIds = new ArrayList<>();
+ private int mVideoFramesPlayed;
+ private int mVideoFramesDropped;
+ private int mAudioUnderrunCount;
+ private long mNetworkBytesRead;
+ private long mLocalBytesRead;
+ private long mNetworkTransferDurationMillis;
+
+ /**
+ * Creates a new Builder.
+ *
+ * @hide
+ */
+ public Builder() {
+ }
+
+ /**
+ * Sets the media duration in milliseconds.
+ */
+ public @NonNull Builder setMediaDurationMillis(long value) {
+ mMediaDurationMillis = value;
+ return this;
+ }
+
+ /**
+ * Sets the stream source type.
+ */
+ public @NonNull Builder setStreamSource(@StreamSource int value) {
+ mStreamSource = value;
+ return this;
+ }
+
+ /**
+ * Sets the stream type.
+ */
+ public @NonNull Builder setStreamType(@StreamType int value) {
+ mStreamType = value;
+ return this;
+ }
+
+ /**
+ * Sets the playback type.
+ */
+ public @NonNull Builder setPlaybackType(@PlaybackType int value) {
+ mPlaybackType = value;
+ return this;
+ }
+
+ /**
+ * Sets the DRM type.
+ */
+ public @NonNull Builder setDrmType(@StreamType int value) {
+ mDrmType = value;
+ return this;
+ }
+
+ /**
+ * Sets the content type.
+ */
+ public @NonNull Builder setContentType(@ContentType int value) {
+ mContentType = value;
+ return this;
+ }
+
+ /**
+ * Sets the player name.
+ */
+ public @NonNull Builder setPlayerName(@NonNull String value) {
+ mPlayerName = value;
+ return this;
+ }
+
+ /**
+ * Sets the player version.
+ */
+ public @NonNull Builder setPlayerVersion(@NonNull String value) {
+ mPlayerVersion = value;
+ return this;
+ }
+
+ /**
+ * Adds the experiment ID.
+ */
+ public @NonNull Builder addExperimentId(long value) {
+ mExperimentIds.add(value);
+ return this;
+ }
+
+ /**
+ * Sets the video frames played.
+ */
+ public @NonNull Builder setVideoFramesPlayed(int value) {
+ mVideoFramesPlayed = value;
+ return this;
+ }
+
+ /**
+ * Sets the video frames dropped.
+ */
+ public @NonNull Builder setVideoFramesDropped(int value) {
+ mVideoFramesDropped = value;
+ return this;
+ }
+
+ /**
+ * Sets the audio underrun count.
+ */
+ public @NonNull Builder setAudioUnderrunCount(int value) {
+ mAudioUnderrunCount = value;
+ return this;
+ }
+
+ /**
+ * Sets the number of network bytes read.
+ */
+ public @NonNull Builder setNetworkBytesRead(long value) {
+ mNetworkBytesRead = value;
+ return this;
+ }
+
+ /**
+ * Sets the number of local bytes read.
+ */
+ public @NonNull Builder setLocalBytesRead(long value) {
+ mLocalBytesRead = value;
+ return this;
+ }
+
+ /**
+ * Sets the network transfer duration in milliseconds.
+ */
+ public @NonNull Builder setNetworkTransferDurationMillis(long value) {
+ mNetworkTransferDurationMillis = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull PlaybackMetrics build() {
+
+ PlaybackMetrics o = new PlaybackMetrics(
+ mMediaDurationMillis,
+ mStreamSource,
+ mStreamType,
+ mPlaybackType,
+ mDrmType,
+ mContentType,
+ mPlayerName,
+ mPlayerVersion,
+ idsToLongArray(),
+ mVideoFramesPlayed,
+ mVideoFramesDropped,
+ mAudioUnderrunCount,
+ mNetworkBytesRead,
+ mLocalBytesRead,
+ mNetworkTransferDurationMillis);
+ return o;
+ }
+
+ private long[] idsToLongArray() {
+ long[] ids = new long[mExperimentIds.size()];
+ for (int i = 0; i < mExperimentIds.size(); i++) {
+ ids[i] = mExperimentIds.get(i);
+ }
+ return ids;
+ }
+ }
}
diff --git a/media/java/android/media/metrics/PlaybackMetricsManager.java b/media/java/android/media/metrics/PlaybackMetricsManager.java
index d51ff47..63a50ae 100644
--- a/media/java/android/media/metrics/PlaybackMetricsManager.java
+++ b/media/java/android/media/metrics/PlaybackMetricsManager.java
@@ -48,6 +48,29 @@
throw e.rethrowFromSystemServer();
}
}
+ /**
+ * Reports network event.
+ * @hide
+ */
+ public void reportNetworkEvent(@NonNull String sessionId, NetworkEvent event) {
+ try {
+ mService.reportNetworkEvent(sessionId, event, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Reports playback state event.
+ * @hide
+ */
+ public void reportPlaybackStateEvent(@NonNull String sessionId, PlaybackStateEvent event) {
+ try {
+ mService.reportPlaybackStateEvent(sessionId, event, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
/**
* Creates a playback session.
@@ -61,4 +84,16 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Reports error event.
+ * @hide
+ */
+ public void reportPlaybackErrorEvent(@NonNull String sessionId, PlaybackErrorEvent event) {
+ try {
+ mService.reportPlaybackErrorEvent(sessionId, event, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/media/java/android/media/metrics/PlaybackSession.java b/media/java/android/media/metrics/PlaybackSession.java
index 4ad8906..061e665 100644
--- a/media/java/android/media/metrics/PlaybackSession.java
+++ b/media/java/android/media/metrics/PlaybackSession.java
@@ -50,6 +50,27 @@
mManager.reportPlaybackMetrics(mId, metrics);
}
+ /**
+ * Reports error event.
+ */
+ public void reportPlaybackErrorEvent(PlaybackErrorEvent event) {
+ mManager.reportPlaybackErrorEvent(mId, event);
+ }
+
+ /**
+ * Reports network event.
+ */
+ public void reportNetworkEvent(NetworkEvent event) {
+ mManager.reportNetworkEvent(mId, event);
+ }
+
+ /**
+ * Reports playback state event.
+ */
+ public void reportPlaybackStateEvent(PlaybackStateEvent event) {
+ mManager.reportPlaybackStateEvent(mId, event);
+ }
+
public @NonNull String getId() {
return mId;
}
diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl b/media/java/android/media/metrics/PlaybackStateEvent.aidl
similarity index 64%
copy from media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
copy to media/java/android/media/metrics/PlaybackStateEvent.aidl
index edf96dd..8b8d05b 100644
--- a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
+++ b/media/java/android/media/metrics/PlaybackStateEvent.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,6 @@
* limitations under the License.
*/
-package android.media.tv.tunerresourcemanager;
+package android.media.metrics;
-/**
- * Simple container of the FrontendInfo struct defined in the TunerHAL 1.0 interface.
- *
- * @hide
- */
-parcelable TunerFrontendInfo {
- int handle;
-
- int frontendType;
-
- int exclusiveGroupId;
-}
+parcelable PlaybackStateEvent;
diff --git a/media/java/android/media/metrics/PlaybackStateEvent.java b/media/java/android/media/metrics/PlaybackStateEvent.java
new file mode 100644
index 0000000..6ce5bf0
--- /dev/null
+++ b/media/java/android/media/metrics/PlaybackStateEvent.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.metrics;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.util.Objects;
+
+/**
+ * Playback state event.
+ * @hide
+ */
+public final class PlaybackStateEvent implements Parcelable {
+ // TODO: more states
+ /** Playback has not started (initial state) */
+ public static final int STATE_NOT_STARTED = 0;
+ /** Playback is buffering in the background for initial playback start */
+ public static final int STATE_JOINING_BACKGROUND = 1;
+ /** Playback is buffering in the foreground for initial playback start */
+ public static final int STATE_JOINING_FOREGROUND = 2;
+ /** Playback is actively playing */
+ public static final int STATE_PLAYING = 3;
+ /** Playback is paused but ready to play */
+ public static final int STATE_PAUSED = 4;
+
+ private int mState;
+ private long mTimeSincePlaybackCreatedMillis;
+
+ // These track ExoPlayer states. See the ExoPlayer documentation for the state transitions.
+ @IntDef(prefix = "STATE_", value = {
+ STATE_NOT_STARTED,
+ STATE_JOINING_BACKGROUND,
+ STATE_JOINING_FOREGROUND,
+ STATE_PLAYING,
+ STATE_PAUSED
+ })
+ @Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+ public @interface State {}
+
+ /**
+ * Converts playback state to string.
+ */
+ public static String stateToString(@State int value) {
+ switch (value) {
+ case STATE_NOT_STARTED:
+ return "STATE_NOT_STARTED";
+ case STATE_JOINING_BACKGROUND:
+ return "STATE_JOINING_BACKGROUND";
+ case STATE_JOINING_FOREGROUND:
+ return "STATE_JOINING_FOREGROUND";
+ case STATE_PLAYING:
+ return "STATE_PLAYING";
+ case STATE_PAUSED:
+ return "STATE_PAUSED";
+ default:
+ return Integer.toHexString(value);
+ }
+ }
+
+ /**
+ * Creates a new PlaybackStateEvent.
+ *
+ * @hide
+ */
+ public PlaybackStateEvent(
+ int state,
+ long timeSincePlaybackCreatedMillis) {
+ this.mState = state;
+ this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ }
+
+ /**
+ * Gets playback state.
+ * @return
+ */
+ public int getState() {
+ return mState;
+ }
+
+ /**
+ * Gets time since the corresponding playback is created in millisecond.
+ */
+ public long getTimeSincePlaybackCreatedMillis() {
+ return mTimeSincePlaybackCreatedMillis;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ PlaybackStateEvent that = (PlaybackStateEvent) o;
+ return mState == that.mState
+ && mTimeSincePlaybackCreatedMillis == that.mTimeSincePlaybackCreatedMillis;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mState, mTimeSincePlaybackCreatedMillis);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mState);
+ dest.writeLong(mTimeSincePlaybackCreatedMillis);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** @hide */
+ /* package-private */ PlaybackStateEvent(@NonNull Parcel in) {
+ int state = in.readInt();
+ long timeSincePlaybackCreatedMillis = in.readLong();
+
+ this.mState = state;
+ this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ }
+
+ public static final @NonNull Parcelable.Creator<PlaybackStateEvent> CREATOR =
+ new Parcelable.Creator<PlaybackStateEvent>() {
+ @Override
+ public PlaybackStateEvent[] newArray(int size) {
+ return new PlaybackStateEvent[size];
+ }
+
+ @Override
+ public PlaybackStateEvent createFromParcel(@NonNull Parcel in) {
+ return new PlaybackStateEvent(in);
+ }
+ };
+
+}
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index ed99fad..d8d1ba13 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -94,6 +94,8 @@
// For the recording session
void startRecording(in IBinder sessionToken, in Uri programUri, in Bundle params, int userId);
void stopRecording(in IBinder sessionToken, int userId);
+ void pauseRecording(in IBinder sessionToken, in Bundle params, int userId);
+ void resumeRecording(in IBinder sessionToken, in Bundle params, int userId);
// For TV input hardware binding
List<TvInputHardwareInfo> getHardwareList();
diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl
index 24b87d5..158cf21 100644
--- a/media/java/android/media/tv/ITvInputSession.aidl
+++ b/media/java/android/media/tv/ITvInputSession.aidl
@@ -58,4 +58,6 @@
// For the recording session
void startRecording(in Uri programUri, in Bundle params);
void stopRecording();
+ void pauseRecording(in Bundle params);
+ void resumeRecording(in Bundle params);
}
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index e89d33d..abccf8d 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -68,6 +68,8 @@
private static final int DO_TIME_SHIFT_ENABLE_POSITION_TRACKING = 19;
private static final int DO_START_RECORDING = 20;
private static final int DO_STOP_RECORDING = 21;
+ private static final int DO_PAUSE_RECORDING = 22;
+ private static final int DO_RESUME_RECORDING = 23;
private final boolean mIsRecordingSession;
private final HandlerCaller mCaller;
@@ -224,6 +226,14 @@
mTvInputRecordingSessionImpl.stopRecording();
break;
}
+ case DO_PAUSE_RECORDING: {
+ mTvInputRecordingSessionImpl.pauseRecording((Bundle) msg.obj);
+ break;
+ }
+ case DO_RESUME_RECORDING: {
+ mTvInputRecordingSessionImpl.resumeRecording((Bundle) msg.obj);
+ break;
+ }
default: {
Log.w(TAG, "Unhandled message code: " + msg.what);
break;
@@ -363,6 +373,16 @@
mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_STOP_RECORDING));
}
+ @Override
+ public void pauseRecording(@Nullable Bundle params) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_PAUSE_RECORDING, params));
+ }
+
+ @Override
+ public void resumeRecording(@Nullable Bundle params) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_RESUME_RECORDING, params));
+ }
+
private final class TvInputEventReceiver extends InputEventReceiver {
public TvInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
diff --git a/media/java/android/media/tv/TvInputHardwareInfo.java b/media/java/android/media/tv/TvInputHardwareInfo.java
index b12f7c5..1249e0d 100644
--- a/media/java/android/media/tv/TvInputHardwareInfo.java
+++ b/media/java/android/media/tv/TvInputHardwareInfo.java
@@ -188,6 +188,17 @@
mCableConnectionStatus = source.readInt();
}
+ /** @hide */
+ public Builder toBuilder() {
+ return new Builder()
+ .deviceId(mDeviceId)
+ .type(mType)
+ .audioType(mAudioType)
+ .audioAddress(mAudioAddress)
+ .hdmiPortId(mHdmiPortId)
+ .cableConnectionStatus(mCableConnectionStatus);
+ }
+
public static final class Builder {
private Integer mDeviceId = null;
private Integer mType = null;
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 195ad5b..54cb2bf 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -143,6 +143,7 @@
// Attributes from XML meta data.
private final String mSetupActivity;
private final boolean mCanRecord;
+ private final boolean mCanPauseRecording;
private final int mTunerCount;
// Attributes specific to HDMI
@@ -264,8 +265,8 @@
private TvInputInfo(ResolveInfo service, String id, int type, boolean isHardwareInput,
CharSequence label, int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected,
- String setupActivity, boolean canRecord, int tunerCount, HdmiDeviceInfo hdmiDeviceInfo,
- boolean isConnectedToHdmiSwitch,
+ String setupActivity, boolean canRecord, boolean canPauseRecording, int tunerCount,
+ HdmiDeviceInfo hdmiDeviceInfo, boolean isConnectedToHdmiSwitch,
@HdmiAddressRelativePosition int hdmiConnectionRelativePosition, String parentId,
Bundle extras) {
mService = service;
@@ -279,6 +280,7 @@
mIconDisconnected = iconDisconnected;
mSetupActivity = setupActivity;
mCanRecord = canRecord;
+ mCanPauseRecording = canPauseRecording;
mTunerCount = tunerCount;
mHdmiDeviceInfo = hdmiDeviceInfo;
mIsConnectedToHdmiSwitch = isConnectedToHdmiSwitch;
@@ -386,6 +388,14 @@
}
/**
+ * Returns {@code true} if this TV input can pause recording TV programs,
+ * {@code false} otherwise.
+ */
+ public boolean canPauseRecording() {
+ return mCanPauseRecording;
+ }
+
+ /**
* Returns domain-specific extras associated with this TV input.
*/
public Bundle getExtras() {
@@ -571,6 +581,7 @@
&& Objects.equals(mIconDisconnected, obj.mIconDisconnected)
&& TextUtils.equals(mSetupActivity, obj.mSetupActivity)
&& mCanRecord == obj.mCanRecord
+ && mCanPauseRecording == obj.mCanPauseRecording
&& mTunerCount == obj.mTunerCount
&& Objects.equals(mHdmiDeviceInfo, obj.mHdmiDeviceInfo)
&& mIsConnectedToHdmiSwitch == obj.mIsConnectedToHdmiSwitch
@@ -606,6 +617,7 @@
dest.writeParcelable(mIconDisconnected, flags);
dest.writeString(mSetupActivity);
dest.writeByte(mCanRecord ? (byte) 1 : 0);
+ dest.writeByte(mCanPauseRecording ? (byte) 1 : 0);
dest.writeInt(mTunerCount);
dest.writeParcelable(mHdmiDeviceInfo, flags);
dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0);
@@ -648,6 +660,7 @@
mIconDisconnected = in.readParcelable(null);
mSetupActivity = in.readString();
mCanRecord = in.readByte() == 1;
+ mCanPauseRecording = in.readByte() == 1;
mTunerCount = in.readInt();
mHdmiDeviceInfo = in.readParcelable(null);
mIsConnectedToHdmiSwitch = in.readByte() == 1;
@@ -695,6 +708,7 @@
private Icon mIconDisconnected;
private String mSetupActivity;
private Boolean mCanRecord;
+ private Boolean mCanPauseRecording;
private Integer mTunerCount;
private TvInputHardwareInfo mTvInputHardwareInfo;
private HdmiDeviceInfo mHdmiDeviceInfo;
@@ -879,6 +893,18 @@
}
/**
+ * Sets whether this TV input can pause recording TV programs or not.
+ *
+ * @param canPauseRecording Whether this TV input can pause recording TV programs.
+ * @return This Builder object to allow for chaining of calls to builder methods.
+ */
+ @NonNull
+ public Builder setCanPauseRecording(boolean canPauseRecording) {
+ this.mCanPauseRecording = canPauseRecording;
+ return this;
+ }
+
+ /**
* Sets domain-specific extras associated with this TV input.
*
* @param extras Domain-specific extras associated with this TV input. Keys <em>must</em> be
@@ -927,7 +953,9 @@
parseServiceMetadata(type);
return new TvInputInfo(mResolveInfo, id, type, isHardwareInput, mLabel, mLabelResId,
mIcon, mIconStandby, mIconDisconnected, mSetupActivity,
- mCanRecord == null ? false : mCanRecord, mTunerCount == null ? 0 : mTunerCount,
+ mCanRecord == null ? false : mCanRecord,
+ mCanPauseRecording == null ? false : mCanPauseRecording,
+ mTunerCount == null ? 0 : mTunerCount,
mHdmiDeviceInfo, isConnectedToHdmiSwitch, hdmiConnectionRelativePosition,
mParentId, mExtras);
}
@@ -997,6 +1025,12 @@
mTunerCount = sa.getInt(
com.android.internal.R.styleable.TvInputService_tunerCount, 1);
}
+ if (mCanPauseRecording == null) {
+ mCanPauseRecording = sa.getBoolean(
+ com.android.internal.R.styleable.TvInputService_canPauseRecording,
+ false);
+ }
+
sa.recycle();
} catch (IOException | XmlPullParserException e) {
throw new IllegalStateException("Failed reading meta-data for " + si.packageName, e);
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index e9959be..98b9ad8 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -2523,6 +2523,40 @@
}
/**
+ * Pauses TV program recording in the current recording session.
+ *
+ * @param params A set of extra parameters which might be handled with this event.
+ */
+ void pauseRecording(@NonNull Bundle params) {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.pauseRecording(mToken, params, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Resumes TV program recording in the current recording session.
+ *
+ * @param params A set of extra parameters which might be handled with this event.
+ */
+ void resumeRecording(@NonNull Bundle params) {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.resumeRecording(mToken, params, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Calls {@link TvInputService.Session#appPrivateCommand(String, Bundle)
* TvInputService.Session.appPrivateCommand()} on the current TvView.
*
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 945fb3b..77fb2b2 100755
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -1873,6 +1873,28 @@
/**
+ * Called when the application requests to pause TV program recording. Recording must pause
+ * immediately when this method is called.
+ *
+ * If the pause request cannot be fulfilled, the session must call
+ * {@link #notifyError(int)}.
+ *
+ * @param params Domain-specific data for recording request.
+ */
+ public void onPauseRecording(@NonNull Bundle params) { }
+
+ /**
+ * Called when the application requests to resume TV program recording. Recording must
+ * resume immediately when this method is called.
+ *
+ * If the resume request cannot be fulfilled, the session must call
+ * {@link #notifyError(int)}.
+ *
+ * @param params Domain-specific data for recording request.
+ */
+ public void onResumeRecording(@NonNull Bundle params) { }
+
+ /**
* Called when the application requests to release all the resources held by this recording
* session.
*/
@@ -1924,6 +1946,22 @@
}
/**
+ * Calls {@link #onPauseRecording(Bundle)}.
+ *
+ */
+ void pauseRecording(@NonNull Bundle params) {
+ onPauseRecording(params);
+ }
+
+ /**
+ * Calls {@link #onResumeRecording(Bundle)}.
+ *
+ */
+ void resumeRecording(@NonNull Bundle params) {
+ onResumeRecording(params);
+ }
+
+ /**
* Calls {@link #onAppPrivateCommand(String, Bundle)}.
*/
void appPrivateCommand(String action, Bundle data) {
diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java
index 23fadac..180e2bd 100644
--- a/media/java/android/media/tv/TvRecordingClient.java
+++ b/media/java/android/media/tv/TvRecordingClient.java
@@ -30,6 +30,7 @@
import android.util.Pair;
import java.util.ArrayDeque;
+import java.util.Objects;
import java.util.Queue;
/**
@@ -49,6 +50,8 @@
private boolean mIsRecordingStarted;
private boolean mIsTuned;
+ private boolean mIsPaused;
+ private boolean mIsRecordingStopping;
private final Queue<Pair<String, Bundle>> mPendingAppPrivateCommands = new ArrayDeque<>();
/**
@@ -113,17 +116,22 @@
if (TextUtils.isEmpty(inputId)) {
throw new IllegalArgumentException("inputId cannot be null or an empty string");
}
- if (mIsRecordingStarted) {
+ if (mIsRecordingStarted && !mIsPaused) {
throw new IllegalStateException("tune failed - recording already started");
}
if (mSessionCallback != null && TextUtils.equals(mSessionCallback.mInputId, inputId)) {
if (mSession != null) {
+ mSessionCallback.mChannelUri = channelUri;
mSession.tune(channelUri, params);
} else {
mSessionCallback.mChannelUri = channelUri;
mSessionCallback.mConnectionParams = params;
}
+ mIsTuned = false;
} else {
+ if (mIsPaused) {
+ throw new IllegalStateException("tune failed - inputId is changed during pause");
+ }
resetInternal();
mSessionCallback = new MySessionCallback(inputId, channelUri, params);
if (mTvInputManager != null) {
@@ -148,6 +156,8 @@
mSession.release();
mIsTuned = false;
mIsRecordingStarted = false;
+ mIsPaused = false;
+ mIsRecordingStopping = false;
mSession = null;
}
}
@@ -169,7 +179,8 @@
*
* @param programUri The URI for the TV program to record, built by
* {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
- * @throws IllegalStateException If {@link #tune} request hasn't been handled yet.
+ * @throws IllegalStateException If {@link #tune} request hasn't been handled yet or during
+ * pause.
*/
public void startRecording(@Nullable Uri programUri) {
startRecording(programUri, Bundle.EMPTY);
@@ -195,11 +206,16 @@
* @param params Domain-specific data for this request. Keys <em>must</em> be a scoped
* name, i.e. prefixed with a package name you own, so that different developers will
* not create conflicting keys.
- * @throws IllegalStateException If {@link #tune} request hasn't been handled yet.
+ * @throws IllegalStateException If {@link #tune} request hasn't been handled yet or during
+ * pause.
*/
public void startRecording(@Nullable Uri programUri, @NonNull Bundle params) {
- if (!mIsTuned) {
- throw new IllegalStateException("startRecording failed - not yet tuned");
+ if (mIsRecordingStopping || !mIsTuned || mIsPaused) {
+ throw new IllegalStateException("startRecording failed -"
+ + "recording not yet stopped or not yet tuned or paused");
+ }
+ if (mIsRecordingStarted) {
+ Log.w(TAG, "startRecording failed - recording already started");
}
if (mSession != null) {
mSession.startRecording(programUri, params);
@@ -225,6 +241,103 @@
}
if (mSession != null) {
mSession.stopRecording();
+ if (mIsRecordingStarted) {
+ mIsRecordingStopping = true;
+ }
+ }
+ }
+
+ /**
+ * Pause TV program recording in the current recording session. Recording is expected to pause
+ * immediately when this method is called. If recording has not yet started in the current
+ * recording session, this method does nothing.
+ *
+ * <p>In pause status, the application can tune during recording. To continue recording,
+ * please call {@link TvRecordingClient#resumeRecording()} to resume instead of
+ * {@link TvRecordingClient#startRecording(Uri)}. Application can stop
+ * the recording with {@link TvRecordingClient#stopRecording()} in recording pause status.
+ *
+ * <p>If the pause request cannot be fulfilled, the recording session will respond by calling
+ * {@link RecordingCallback#onError(int)}.
+ */
+ public void pauseRecording() {
+ pauseRecording(Bundle.EMPTY);
+ }
+
+ /**
+ * Pause TV program recording in the current recording session. Recording is expected to pause
+ * immediately when this method is called. If recording has not yet started in the current
+ * recording session, this method does nothing.
+ *
+ * <p>In pause status, the application can tune during recording. To continue recording,
+ * please call {@link TvRecordingClient#resumeRecording()} to resume instead of
+ * {@link TvRecordingClient#startRecording(Uri)}. Application can stop
+ * the recording with {@link TvRecordingClient#stopRecording()} in recording pause status.
+ *
+ * <p>If the pause request cannot be fulfilled, the recording session will respond by calling
+ * {@link RecordingCallback#onError(int)}.
+ *
+ * @param params Domain-specific data for this request.
+ */
+ public void pauseRecording(@NonNull Bundle params) {
+ if (!mIsRecordingStarted || mIsRecordingStopping) {
+ throw new IllegalStateException(
+ "pauseRecording failed - recording not yet started or stopping");
+ }
+ TvInputInfo info = mTvInputManager.getTvInputInfo(mSessionCallback.mInputId);
+ if (info == null || !info.canPauseRecording()) {
+ throw new UnsupportedOperationException(
+ "pauseRecording failed - operation not supported");
+ }
+ if (mIsPaused) {
+ Log.w(TAG, "pauseRecording failed - recording already paused");
+ }
+ if (mSession != null) {
+ mSession.pauseRecording(params);
+ mIsPaused = true;
+ }
+ }
+
+ /**
+ * Resume TV program recording only in recording pause status in the current recording session.
+ * Recording is expected to resume immediately when this method is called. If recording has not
+ * yet paused in the current recording session, this method does nothing.
+ *
+ * <p>When record is resumed, the recording is continue and can not re-tune. Application can
+ * stop the recording with {@link TvRecordingClient#stopRecording()} after record resumed.
+ *
+ * <p>If the pause request cannot be fulfilled, the recording session will respond by calling
+ * {@link RecordingCallback#onError(int)}.
+ */
+ public void resumeRecording() {
+ resumeRecording(Bundle.EMPTY);
+ }
+
+ /**
+ * Resume TV program recording only in recording pause status in the current recording session.
+ * Recording is expected to resume immediately when this method is called. If recording has not
+ * yet paused in the current recording session, this method does nothing.
+ *
+ * <p>When record is resumed, the recording is continues and can not re-tune. Application can
+ * stop the recording with {@link TvRecordingClient#stopRecording()} after record resumed.
+ *
+ * <p>If the resume request cannot be fulfilled, the recording session will respond by calling
+ * {@link RecordingCallback#onError(int)}.
+ *
+ * @param params Domain-specific data for this request.
+ */
+ public void resumeRecording(@NonNull Bundle params) {
+ if (!mIsRecordingStarted || mIsRecordingStopping || !mIsTuned) {
+ throw new IllegalStateException(
+ "resumeRecording failed - recording not yet started or stopping or "
+ + "not yet tuned");
+ }
+ if (!mIsPaused) {
+ Log.w(TAG, "resumeRecording failed - recording not yet paused");
+ }
+ if (mSession != null) {
+ mSession.resumeRecording(params);
+ mIsPaused = false;
}
}
@@ -367,6 +480,10 @@
Log.w(TAG, "onTuned - session not created");
return;
}
+ if (mIsTuned || !Objects.equals(mChannelUri, channelUri)) {
+ Log.w(TAG, "onTuned - already tuned or not yet tuned to last channel");
+ return;
+ }
mIsTuned = true;
mCallback.onTuned(channelUri);
}
@@ -382,6 +499,8 @@
}
mIsTuned = false;
mIsRecordingStarted = false;
+ mIsPaused = false;
+ mIsRecordingStopping = false;
mSessionCallback = null;
mSession = null;
if (mCallback != null) {
@@ -398,7 +517,13 @@
Log.w(TAG, "onRecordingStopped - session not created");
return;
}
+ if (!mIsRecordingStarted) {
+ Log.w(TAG, "onRecordingStopped - recording not yet started");
+ return;
+ }
mIsRecordingStarted = false;
+ mIsPaused = false;
+ mIsRecordingStopping = false;
mCallback.onRecordingStopped(recordedProgramUri);
}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 46b29f5..7192c07 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -988,9 +988,11 @@
}
/**
- * Gets the initialized frontend information.
+ * Gets the currently initialized and activated frontend information. To get all the available
+ * frontend info on the device, use {@link getAvailableFrontendInfos()}.
*
- * @return The frontend information. {@code null} if the operation failed.
+ * @return The active frontend information. {@code null} if the operation failed.
+ * @throws IllegalStateException if there is no active frontend currently.
*/
@Nullable
public FrontendInfo getFrontendInfo() {
@@ -1007,13 +1009,20 @@
}
/**
- * Get a list all the existed frontend information.
+ * Gets a list of all the available frontend information on the device. To get the information
+ * of the currently active frontend, use {@link getFrontendInfo()}. The active frontend
+ * information is also included in the list of the available frontend information.
*
- * @return The list of all the frontend information. {@code null} if the operation failed.
+ * @return The list of all the available frontend information. {@code null} if the operation
+ * failed.
*/
@Nullable
- public List<FrontendInfo> getFrontendInfoList() {
- return Arrays.asList(getFrontendInfoListInternal());
+ public List<FrontendInfo> getAvailableFrontendInfos() {
+ FrontendInfo[] feInfoList = getFrontendInfoListInternal();
+ if (feInfoList == null) {
+ return null;
+ }
+ return Arrays.asList(feInfoList);
}
/** @hide */
diff --git a/media/java/android/media/tv/tunerresourcemanager/Android.bp b/media/java/android/media/tv/tunerresourcemanager/Android.bp
index 02390bb..c38d919 100644
--- a/media/java/android/media/tv/tunerresourcemanager/Android.bp
+++ b/media/java/android/media/tv/tunerresourcemanager/Android.bp
@@ -1,16 +1,7 @@
filegroup {
name: "framework-media-tv-tunerresourcemanager-sources-aidl",
srcs: [
- "aidl/android/media/tv/tunerresourcemanager/CasSessionRequest.aidl",
- "aidl/android/media/tv/tunerresourcemanager/IResourcesReclaimListener.aidl",
- "aidl/android/media/tv/tunerresourcemanager/ResourceClientProfile.aidl",
- "aidl/android/media/tv/tunerresourcemanager/TunerCiCamRequest.aidl",
- "aidl/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl",
- "aidl/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl",
- "aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl",
- "aidl/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl",
- "aidl/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl",
- "aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl",
+ "aidl/android/media/tv/tunerresourcemanager/*.aidl",
],
path: "aidl",
}
@@ -21,7 +12,7 @@
local_include_dir: "aidl",
backend: {
java: {
- sdk_version: "current",
+ enabled: true,
},
cpp: {
enabled: true,
@@ -33,4 +24,5 @@
srcs: [
":framework-media-tv-tunerresourcemanager-sources-aidl",
],
+ imports: ["tv_tuner_frontend_info_aidl_interface"],
}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
index 6f7adbc..e399fbd 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
+++ b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
@@ -24,6 +24,7 @@
import android.annotation.SystemService;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.media.tv.tuner.TunerFrontendInfo;
import android.os.Binder;
import android.os.RemoteException;
import android.util.Log;
diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
index a1f6687..483d972 100644
--- a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
@@ -16,13 +16,13 @@
package android.media.tv.tunerresourcemanager;
+import android.media.tv.tuner.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.CasSessionRequest;
import android.media.tv.tunerresourcemanager.IResourcesReclaimListener;
import android.media.tv.tunerresourcemanager.ResourceClientProfile;
import android.media.tv.tunerresourcemanager.TunerCiCamRequest;
import android.media.tv.tunerresourcemanager.TunerDemuxRequest;
import android.media.tv.tunerresourcemanager.TunerDescramblerRequest;
-import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
diff --git a/media/jni/tuner/FrontendClient.cpp b/media/jni/tuner/FrontendClient.cpp
index 14761a6..d6d64f6 100644
--- a/media/jni/tuner/FrontendClient.cpp
+++ b/media/jni/tuner/FrontendClient.cpp
@@ -21,18 +21,39 @@
#include "FrontendClient.h"
+using ::aidl::android::media::tv::tuner::TunerFrontendScanAtsc3PlpInfo;
using ::aidl::android::media::tv::tuner::TunerFrontendSettings;
+
+using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard;
+using ::android::hardware::tv::tuner::V1_0::FrontendAnalogType;
+using ::android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
+using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Modulation;
+using ::android::hardware::tv::tuner::V1_0::FrontendDvbcAnnex;
+using ::android::hardware::tv::tuner::V1_0::FrontendDvbcModulation;
+using ::android::hardware::tv::tuner::V1_0::FrontendDvbsModulation;
+using ::android::hardware::tv::tuner::V1_0::FrontendDvbsStandard;
+using ::android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy;
+using ::android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
+using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsModulation;
+using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Modulation;
+using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtModulation;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanAtsc3PlpInfo;
+using ::android::hardware::tv::tuner::V1_0::FrontendType;
using ::android::hardware::tv::tuner::V1_1::Constant;
+using ::android::hardware::tv::tuner::V1_1::FrontendDtmbModulation;
+using ::android::hardware::tv::tuner::V1_1::FrontendDvbtConstellation;
+using ::android::hardware::tv::tuner::V1_1::FrontendModulation;
namespace android {
/////////////// FrontendClient ///////////////////////
-FrontendClient::FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, int id) {
+FrontendClient::FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, int id, int type) {
mTunerFrontend = tunerFrontend;
mAidlCallback = NULL;
mHidlCallback = NULL;
mId = id;
+ mType = type;
}
FrontendClient::~FrontendClient() {
@@ -42,11 +63,13 @@
mAidlCallback = NULL;
mHidlCallback = NULL;
mId = -1;
+ mType = -1;
}
Result FrontendClient::setCallback(sp<FrontendClientCallback> frontendClientCallback) {
if (mTunerFrontend != NULL) {
mAidlCallback = ::ndk::SharedRefBase::make<TunerFrontendCallback>(frontendClientCallback);
+ mAidlCallback->setFrontendType(mType);
mTunerFrontend->setCallback(mAidlCallback);
return Result::SUCCESS;
}
@@ -298,56 +321,21 @@
return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
}
-Status TunerFrontendCallback::onLocked() {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onScanStopped() {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onProgress(int /*percent*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onFrequenciesReport(const vector<int>& /*frequency*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onSymbolRates(const vector<int>& /*rates*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onHierarchy(int /*hierarchy*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onSignalType(int /*signalType*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onPlpIds(const vector<int>& /*plpIds*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onGroupIds(const vector<int>& /*groupIds*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onInputStreamIds(const vector<int>& /*inputStreamIds*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onDvbsStandard(int /*dvbsStandandard*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onAnalogSifStandard(int /*sifStandandard*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onAtsc3PlpInfos(const vector<TunerAtsc3PlpInfo>& /*atsc3PlpInfos*/) {
- return Status::ok();
+Status TunerFrontendCallback::onScanMessage(int messageType,
+ const TunerFrontendScanMessage& message) {
+ if (mFrontendClientCallback != NULL) {
+ if (!is1_1ExtendedScanMessage(messageType)) {
+ mFrontendClientCallback->onScanMessage(
+ static_cast<FrontendScanMessageType>(messageType),
+ getHalScanMessage(messageType, message));
+ } else {
+ mFrontendClientCallback->onScanMessageExt1_1(
+ static_cast<FrontendScanMessageTypeExt1_1>(messageType),
+ getHalScanMessageExt1_1(messageType, message));
+ }
+ return Status::ok();
+ }
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
}
/////////////// IFrontendCallback ///////////////////////
@@ -377,4 +365,167 @@
}
return Void();
}
+
+/////////////// FrontendClientCallback Helper Methods ///////////////////////
+
+FrontendScanMessage TunerFrontendCallback::getHalScanMessage(
+ int messageType, const TunerFrontendScanMessage& message) {
+ FrontendScanMessage scanMessage;
+ switch (messageType) {
+ case (int) FrontendScanMessageType::LOCKED:
+ scanMessage.isLocked(message.get<TunerFrontendScanMessage::isLocked>());
+ break;
+ case (int) FrontendScanMessageType::END:
+ scanMessage.isEnd(message.get<TunerFrontendScanMessage::isEnd>());
+ break;
+ case (int) FrontendScanMessageType::PROGRESS_PERCENT:
+ scanMessage.progressPercent(message.get<TunerFrontendScanMessage::progressPercent>());
+ break;
+ case (int) FrontendScanMessageType::FREQUENCY: {
+ vector<int> f = message.get<TunerFrontendScanMessage::frequencies>();
+ hidl_vec<uint32_t> frequencies(begin(f), end(f));
+ scanMessage.frequencies(frequencies);
+ break;
+ }
+ case (int) FrontendScanMessageType::SYMBOL_RATE: {
+ vector<int> s = message.get<TunerFrontendScanMessage::symbolRates>();
+ hidl_vec<uint32_t> symbolRates(begin(s), end(s));
+ scanMessage.symbolRates(symbolRates);
+ break;
+ }
+ case (int) FrontendScanMessageType::HIERARCHY:
+ scanMessage.hierarchy(static_cast<FrontendDvbtHierarchy>(
+ message.get<TunerFrontendScanMessage::hierarchy>()));
+ break;
+ case (int) FrontendScanMessageType::ANALOG_TYPE:
+ scanMessage.analogType(static_cast<FrontendAnalogType>(
+ message.get<TunerFrontendScanMessage::analogType>()));
+ break;
+ case (int) FrontendScanMessageType::PLP_IDS: {
+ vector<uint8_t> p = message.get<TunerFrontendScanMessage::plpIds>();
+ hidl_vec<uint8_t> plpIds(begin(p), end(p));
+ scanMessage.plpIds(plpIds);
+ break;
+ }
+ case (int) FrontendScanMessageType::GROUP_IDS: {
+ vector<uint8_t> g = message.get<TunerFrontendScanMessage::groupIds>();
+ hidl_vec<uint8_t> groupIds(begin(g), end(g));
+ scanMessage.groupIds(groupIds);
+ break;
+ }
+ case (int) FrontendScanMessageType::INPUT_STREAM_IDS: {
+ vector<char16_t> i = message.get<TunerFrontendScanMessage::inputStreamIds>();
+ hidl_vec<uint16_t> inputStreamIds(begin(i), end(i));
+ scanMessage.inputStreamIds(inputStreamIds);
+ break;
+ }
+ case (int) FrontendScanMessageType::STANDARD: {
+ FrontendScanMessage::Standard std;
+ int standard = message.get<TunerFrontendScanMessage::std>();
+ switch (mType) {
+ case (int) FrontendType::DVBS:
+ std.sStd(static_cast<FrontendDvbsStandard>(standard));
+ scanMessage.std(std);
+ break;
+ case (int) FrontendType::DVBT:
+ std.tStd(static_cast<FrontendDvbtStandard>(standard));
+ scanMessage.std(std);
+ break;
+ case (int) FrontendType::ANALOG:
+ std.sifStd(static_cast<FrontendAnalogSifStandard>(standard));
+ scanMessage.std(std);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case (int) FrontendScanMessageType::ATSC3_PLP_INFO: {
+ vector<TunerFrontendScanAtsc3PlpInfo> plp =
+ message.get<TunerFrontendScanMessage::atsc3PlpInfos>();
+ hidl_vec<FrontendScanAtsc3PlpInfo> plpInfo;
+ for (TunerFrontendScanAtsc3PlpInfo info : plp) {
+ FrontendScanAtsc3PlpInfo p{
+ .plpId = static_cast<uint8_t>(info.plpId),
+ .bLlsFlag = info.llsFlag,
+ };
+ int size = plpInfo.size();
+ plpInfo.resize(size + 1);
+ plpInfo[size] = p;
+ }
+ scanMessage.atsc3PlpInfos(plpInfo);
+ break;
+ }
+ default:
+ break;
+ }
+ return scanMessage;
+}
+
+FrontendScanMessageExt1_1 TunerFrontendCallback::getHalScanMessageExt1_1(
+ int messageType, const TunerFrontendScanMessage& message) {
+ FrontendScanMessageExt1_1 scanMessage;
+ switch (messageType) {
+ case (int) FrontendScanMessageTypeExt1_1::HIGH_PRIORITY:
+ scanMessage.isHighPriority(message.get<TunerFrontendScanMessage::isHighPriority>());
+ break;
+ case (int) FrontendScanMessageTypeExt1_1::DVBC_ANNEX:
+ scanMessage.annex(static_cast<FrontendDvbcAnnex>(
+ message.get<TunerFrontendScanMessage::annex>()));
+ break;
+ case (int) FrontendScanMessageTypeExt1_1::MODULATION: {
+ FrontendModulation m;
+ int modulation = message.get<TunerFrontendScanMessage::modulation>();
+ switch (mType) {
+ case (int) FrontendType::DVBC:
+ m.dvbc(static_cast<FrontendDvbcModulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) FrontendType::DVBS:
+ m.dvbs(static_cast<FrontendDvbsModulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) FrontendType::DVBT:
+ m.dvbt(static_cast<FrontendDvbtConstellation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) FrontendType::ISDBS:
+ m.isdbs(static_cast<FrontendIsdbsModulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) FrontendType::ISDBS3:
+ m.isdbs3(static_cast<FrontendIsdbs3Modulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) FrontendType::ISDBT:
+ m.isdbt(static_cast<FrontendIsdbtModulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) FrontendType::ATSC:
+ m.atsc(static_cast<FrontendAtscModulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) FrontendType::ATSC3:
+ m.atsc3(static_cast<FrontendAtsc3Modulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) hardware::tv::tuner::V1_1::FrontendType::DTMB:
+ m.dtmb(static_cast<FrontendDtmbModulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return scanMessage;
+}
+
+bool TunerFrontendCallback::is1_1ExtendedScanMessage(int messageType) {
+ return messageType >= (int)FrontendScanMessageTypeExt1_1::MODULATION
+ && messageType <= (int)FrontendScanMessageTypeExt1_1::HIGH_PRIORITY;
+}
} // namespace android
diff --git a/media/jni/tuner/FrontendClient.h b/media/jni/tuner/FrontendClient.h
index 32356744..4f95c22 100644
--- a/media/jni/tuner/FrontendClient.h
+++ b/media/jni/tuner/FrontendClient.h
@@ -30,7 +30,7 @@
using ::aidl::android::media::tv::tuner::BnTunerFrontendCallback;
using ::aidl::android::media::tv::tuner::ITunerFrontend;
-using ::aidl::android::media::tv::tuner::TunerAtsc3PlpInfo;
+using ::aidl::android::media::tv::tuner::TunerFrontendScanMessage;
using ::android::hardware::Return;
using ::android::hardware::Void;
@@ -63,34 +63,18 @@
Status onEvent(int frontendEventType);
- Status onLocked();
+ Status onScanMessage(int messageType, const TunerFrontendScanMessage& message);
- Status onScanStopped();
-
- Status onProgress(int percent);
-
- Status onFrequenciesReport(const vector<int>& frequency);
-
- Status onSymbolRates(const vector<int>& rates);
-
- Status onHierarchy(int hierarchy);
-
- Status onSignalType(int signalType);
-
- Status onPlpIds(const vector<int>& plpIds);
-
- Status onGroupIds(const vector<int>& groupIds);
-
- Status onInputStreamIds(const vector<int>& inputStreamIds);
-
- Status onDvbsStandard(int dvbsStandandard);
-
- Status onAnalogSifStandard(int sifStandandard);
-
- Status onAtsc3PlpInfos(const vector<TunerAtsc3PlpInfo>& atsc3PlpInfos);
+ void setFrontendType(int frontendType) { mType = frontendType; }
private:
+ FrontendScanMessage getHalScanMessage(int messageType, const TunerFrontendScanMessage& message);
+ FrontendScanMessageExt1_1 getHalScanMessageExt1_1(int messageType,
+ const TunerFrontendScanMessage& message);
+ bool is1_1ExtendedScanMessage(int messageType);
+
sp<FrontendClientCallback> mFrontendClientCallback;
+ int mType;
};
struct HidlFrontendCallback : public IFrontendCallback {
@@ -111,7 +95,7 @@
struct FrontendClient : public RefBase {
public:
- FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, int id);
+ FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, int id, int type);
~FrontendClient();
/**
@@ -210,6 +194,7 @@
sp<HidlFrontendCallback> mHidlCallback;
int mId;
+ int mType;
};
} // namespace android
diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp
index 39e6ba2..f5e3524 100644
--- a/media/jni/tuner/TunerClient.cpp
+++ b/media/jni/tuner/TunerClient.cpp
@@ -25,8 +25,6 @@
using ::android::hardware::tv::tuner::V1_0::FrontendId;
using ::android::hardware::tv::tuner::V1_0::FrontendType;
-using ::aidl::android::media::tv::tunerresourcemanager::TunerFrontendInfo;
-
namespace android {
sp<ITuner> TunerClient::mTuner;
@@ -98,14 +96,28 @@
// TODO: handle error code
shared_ptr<ITunerFrontend> tunerFrontend;
mTunerService->openFrontend(frontendHandle, &tunerFrontend);
- return new FrontendClient(tunerFrontend, frontendHandle);
+ if (tunerFrontend == NULL) {
+ return NULL;
+ }
+ int id;
+ // TODO: handle error code
+ tunerFrontend->getFrontendId(&id);
+ TunerFrontendInfo aidlFrontendInfo;
+ // TODO: handle error code
+ mTunerService->getFrontendInfo(id, &aidlFrontendInfo);
+ return new FrontendClient(tunerFrontend, frontendHandle, aidlFrontendInfo.type);
}
if (mTuner != NULL) {
int id = getResourceIdFromHandle(frontendHandle, FRONTEND);
sp<IFrontend> hidlFrontend = openHidlFrontendById(id);
if (hidlFrontend != NULL) {
- sp<FrontendClient> frontendClient = new FrontendClient(NULL, id);
+ FrontendInfo hidlInfo;
+ Result res = getHidlFrontendInfo(id, hidlInfo);
+ if (res != Result::SUCCESS) {
+ return NULL;
+ }
+ sp<FrontendClient> frontendClient = new FrontendClient(NULL, id, (int)hidlInfo.type);
frontendClient->setHidlFrontend(hidlFrontend);
return frontendClient;
}
@@ -116,7 +128,7 @@
shared_ptr<FrontendInfo> TunerClient::getFrontendInfo(int id) {
if (mTunerService != NULL) {
- TunerServiceFrontendInfo aidlFrontendInfo;
+ TunerFrontendInfo aidlFrontendInfo;
// TODO: handle error code
mTunerService->getFrontendInfo(id, &aidlFrontendInfo);
return make_shared<FrontendInfo>(FrontendInfoAidlToHidl(aidlFrontendInfo));
@@ -289,7 +301,7 @@
}
TunerFrontendInfo tunerFrontendInfo{
.handle = getResourceHandleFromId((int)ids[i], FRONTEND),
- .frontendType = static_cast<int>(frontendInfo->type),
+ .type = static_cast<int>(frontendInfo->type),
.exclusiveGroupId = static_cast<int>(frontendInfo->exclusiveGroupId),
};
infos.push_back(tunerFrontendInfo);
@@ -438,7 +450,7 @@
return lnbHandles;
}
-FrontendInfo TunerClient::FrontendInfoAidlToHidl(TunerServiceFrontendInfo aidlFrontendInfo) {
+FrontendInfo TunerClient::FrontendInfoAidlToHidl(TunerFrontendInfo aidlFrontendInfo) {
FrontendInfo hidlFrontendInfo {
.type = static_cast<FrontendType>(aidlFrontendInfo.type),
.minFrequency = static_cast<uint32_t>(aidlFrontendInfo.minFrequency),
diff --git a/media/jni/tuner/TunerClient.h b/media/jni/tuner/TunerClient.h
index a3d2d02c..8a1181a 100644
--- a/media/jni/tuner/TunerClient.h
+++ b/media/jni/tuner/TunerClient.h
@@ -18,8 +18,8 @@
#define _ANDROID_MEDIA_TV_TUNER_CLIENT_H_
#include <aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.h>
-#include <aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.h>
#include <aidl/android/media/tv/tuner/ITunerService.h>
+#include <aidl/android/media/tv/tuner/TunerFrontendInfo.h>
#include <android/hardware/tv/tuner/1.1/ITuner.h>
#include <android/hardware/tv/tuner/1.1/types.h>
@@ -29,7 +29,7 @@
#include "LnbClient.h"
using ::aidl::android::media::tv::tuner::ITunerService;
-using ::aidl::android::media::tv::tuner::TunerServiceFrontendInfo;
+using ::aidl::android::media::tv::tuner::TunerFrontendInfo;
using ::aidl::android::media::tv::tunerresourcemanager::ITunerResourceManager;
using ::android::hardware::tv::tuner::V1_0::DemuxCapabilities;
@@ -141,7 +141,7 @@
sp<ILnb> openHidlLnbByName(string name, LnbId& lnbId);
sp<IDescrambler> openHidlDescrambler();
vector<int> getLnbHandles();
- FrontendInfo FrontendInfoAidlToHidl(TunerServiceFrontendInfo aidlFrontendInfo);
+ FrontendInfo FrontendInfoAidlToHidl(TunerFrontendInfo aidlFrontendInfo);
void updateTunerResources();
void updateFrontendResources();
void updateLnbResources();
diff --git a/native/android/include_platform/android/activity_manager.h b/native/android/include_platform/android/activity_manager.h
index 0ecd56d..aa86c74 100644
--- a/native/android/include_platform/android/activity_manager.h
+++ b/native/android/include_platform/android/activity_manager.h
@@ -115,8 +115,6 @@
AACTIVITYMANAGER_IMPORTANCE_GONE = 1000,
};
-#if __ANDROID_API__ >= 31
-
/**
* Adds a UidImportanceListener to the ActivityManager.
*
@@ -169,8 +167,6 @@
*/
int32_t AActivityManager_getUidImportance(uid_t uid) __INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
__END_DECLS
#endif // __AACTIVITYMANAGER_H__
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 4120a732..3751564 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -22,22 +22,20 @@
"-Wunreachable-code",
],
- // our source files
- //
srcs: [
- "aassetstreamadaptor.cpp",
- "bitmap.cpp",
"imagedecoder.cpp",
],
shared_libs: [
- "libandroid",
"libandroid_runtime",
"libhwui",
"liblog",
],
- header_libs: [ "libhwui_internal_headers" ],
+ header_libs: [
+ "libhwui_internal_headers",
+ "jni_headers",
+ ],
static_libs: ["libarect"],
@@ -48,7 +46,24 @@
ldflags: ["-Wl,--hash-style=both"],
},
},
- version_script: "libjnigraphics.map.txt",
+ host_supported: true,
+ target: {
+ android: {
+ srcs: [
+ "aassetstreamadaptor.cpp",
+ "bitmap.cpp",
+ ],
+ shared_libs: [
+ "libandroid",
+ ],
+ version_script: "libjnigraphics.map.txt",
+ },
+ host: {
+ header_libs: [
+ "libnativewindow_headers",
+ ],
+ },
+ },
}
// The headers module is in frameworks/native/Android.bp.
@@ -71,6 +86,17 @@
static_libs: ["libarect"],
fuzz_config: {
cc: ["scroggo@google.com"],
+ asan_options: [
+ "detect_odr_violation=1",
+ ],
+ hwasan_options: [
+ // Image decoders may attempt to allocate a large amount of memory
+ // (especially if the encoded image is large). This doesn't
+ // necessarily mean there is a bug. Set allocator_may_return_null=1
+ // for hwasan so the fuzzer can continue running.
+ "allocator_may_return_null = 1",
+ ],
},
corpus: ["corpus/*"],
+ host_supported: true,
}
diff --git a/native/graphics/jni/corpus/webp-color-profile-lossless.webp b/native/graphics/jni/corpus/webp-color-profile-lossless.webp
new file mode 100644
index 0000000..4fd63d5
--- /dev/null
+++ b/native/graphics/jni/corpus/webp-color-profile-lossless.webp
Binary files differ
diff --git a/native/graphics/jni/fuzz_imagedecoder.cpp b/native/graphics/jni/fuzz_imagedecoder.cpp
index f2cd1a8..015aca7 100644
--- a/native/graphics/jni/fuzz_imagedecoder.cpp
+++ b/native/graphics/jni/fuzz_imagedecoder.cpp
@@ -73,6 +73,12 @@
return 0;
}
- AImageDecoder_decodeImage(decoder.get(), pixels.get(), stride, pixelSize);
+ while (true) {
+ int result = AImageDecoder_decodeImage(decoder.get(), pixels.get(), stride, pixelSize);
+ if (result != ANDROID_IMAGE_DECODER_SUCCESS) break;
+
+ result = AImageDecoder_advanceFrame(decoder.get());
+ if (result != ANDROID_IMAGE_DECODER_SUCCESS) break;
+ }
return 0;
}
diff --git a/native/graphics/jni/imagedecoder.cpp b/native/graphics/jni/imagedecoder.cpp
index 5973790..eab5f41 100644
--- a/native/graphics/jni/imagedecoder.cpp
+++ b/native/graphics/jni/imagedecoder.cpp
@@ -121,8 +121,12 @@
}
*outDecoder = nullptr;
+#ifdef __ANDROID__
auto stream = std::make_unique<AAssetStreamAdaptor>(asset);
return createFromStream(std::move(stream), outDecoder);
+#else
+ return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
+#endif
}
static bool isSeekable(int descriptor) {
diff --git a/packages/CompanionDeviceManager/res/values-af/strings.xml b/packages/CompanionDeviceManager/res/values-af/strings.xml
index 8fc3531..d366a0b 100644
--- a/packages/CompanionDeviceManager/res/values-af/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-af/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Metgeseltoestel-bestuurder"</string>
<string name="chooser_title" msgid="2262294130493605839">"Kies \'n <xliff:g id="PROFILE_NAME">%1$s</xliff:g> om deur <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> bestuur te word"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"toestel"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Stel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> om jou <xliff:g id="PROFILE_NAME">%2$s</xliff:g> te bestuur – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Jy het <xliff:g id="APP_NAME_0">%1$s</xliff:g> nodig om jou <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> te bestuur. <xliff:g id="APP_NAME2">%3$s</xliff:g> sal toegang hê tot <xliff:g id="PERMISSIONS">%4$s</xliff:g> terwyl die <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> gekoppel is."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Ja"</string>
<string name="consent_no" msgid="1335543792857823917">"Nee, dankie"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-am/strings.xml b/packages/CompanionDeviceManager/res/values-am/strings.xml
index ff31454..68e816a 100644
--- a/packages/CompanionDeviceManager/res/values-am/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-am/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"አጃቢ የመሣሪያ አስተዳዳሪ"</string>
<string name="chooser_title" msgid="2262294130493605839">"በ<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> የሚተዳደር <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ይምረጡ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"መሣሪያ"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> የእርስዎን <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> እንዲያስተዳድር ያቀናብሩት"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> የእርስዎን <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> ለማስተዳደር ያስፈልጋል። <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> ተገናኝቶ ሳለ <xliff:g id="APP_NAME2">%3$s</xliff:g> የ<xliff:g id="PERMISSIONS">%4$s</xliff:g> መዳረሻን ያገኛል።"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"አዎ"</string>
<string name="consent_no" msgid="1335543792857823917">"አይ፣ አመሰግናለሁ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml
index aedf0f3..184837f 100644
--- a/packages/CompanionDeviceManager/res/values-ar/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"تطبيق \"مدير الجهاز المصاحب\""</string>
<string name="chooser_title" msgid="2262294130493605839">"اختَر <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ليديره تطبيق <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"جهاز"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"اضبط <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> لإدارة <xliff:g id="PROFILE_NAME">%2$s</xliff:g> على <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"يجب توفّر تطبيق <xliff:g id="APP_NAME_0">%1$s</xliff:g> لإدارة <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. سيتمكن تطبيق <xliff:g id="APP_NAME2">%3$s</xliff:g> من الوصول إلى <xliff:g id="PERMISSIONS">%4$s</xliff:g> عندما يكون <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> مرتبطًا."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"نعم"</string>
<string name="consent_no" msgid="1335543792857823917">"لا، شكرًا"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml
index f0c3ee8..116d63b 100644
--- a/packages/CompanionDeviceManager/res/values-as/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-as/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"কম্পেনিয়ন ডিভাইচ মেনেজাৰ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>এ পৰিচালনা কৰিব লগা এটা <xliff:g id="PROFILE_NAME">%1$s</xliff:g> বাছনি কৰক"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইচ"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"আপোনাৰ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> পৰিচালনা কৰিবলৈ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ছেট কৰক - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"আপোনাৰ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> পৰিচালনা কৰিবলৈ <xliff:g id="APP_NAME_0">%1$s</xliff:g>ৰ আৱশ্যক। <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>ৰ সৈতে সংযোগ কৰিলে <xliff:g id="APP_NAME2">%3$s</xliff:g>এ <xliff:g id="PERMISSIONS">%4$s</xliff:g>লৈ এক্সেছ পাব।"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"হয়"</string>
<string name="consent_no" msgid="1335543792857823917">"নালাগে, ধন্যবাদ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml
index 64bea4d..bc719a3 100644
--- a/packages/CompanionDeviceManager/res/values-az/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-az/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Kompanyon Cihaz Meneceri"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> tərəfindən idarə ediləcək <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g> profilinizin <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tərəfindən idarə olunmasını ayarlayın - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> profilinizi idarə etmək üçün <xliff:g id="APP_NAME_0">%1$s</xliff:g> tələb olunur. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> qoşulu olduqda <xliff:g id="APP_NAME2">%3$s</xliff:g> <xliff:g id="PERMISSIONS">%4$s</xliff:g> bölməsinə giriş əldə edəcək."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Bəli"</string>
<string name="consent_no" msgid="1335543792857823917">"Xeyr, çox sağolun"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
index 3f06722..a0e5298 100644
--- a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Menadžer pridruženog uređaja"</string>
<string name="chooser_title" msgid="2262294130493605839">"Odaberite profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Podesite aplikaciju <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da upravlja profilom <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> je neophodna za upravljanje profilom <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> će dobiti pristup dozvolama za <xliff:g id="PERMISSIONS">%4$s</xliff:g> dok je <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> povezan."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Da"</string>
<string name="consent_no" msgid="1335543792857823917">"Ne, hvala"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml
index 25e235c..96a513d 100644
--- a/packages/CompanionDeviceManager/res/values-be/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-be/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Менеджар спадарожнай прылады"</string>
<string name="chooser_title" msgid="2262294130493605839">"Выберыце прыладу (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), якой будзе кіраваць праграма <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"прылада"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> кіраваць прыладай \"<xliff:g id="PROFILE_NAME">%2$s</xliff:g>\" – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Для кіравання прыладай \"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>\" патрабуецца праграма \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\". Калі прылада \"<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>\" будзе падключана, <xliff:g id="APP_NAME2">%3$s</xliff:g> атрымае наступныя дазволы: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Так"</string>
<string name="consent_no" msgid="1335543792857823917">"Не, дзякуй"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml
index 264ce27..3775dbe 100644
--- a/packages/CompanionDeviceManager/res/values-bg/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Изберете устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), което да се управлява от <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Задайте <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да управлява устройството ви (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>) – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"За управление на <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> се изисква <xliff:g id="APP_NAME_0">%1$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> ще получи достъп до <xliff:g id="PERMISSIONS">%4$s</xliff:g>, докато устройството (<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>) е свързано."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Да"</string>
<string name="consent_no" msgid="1335543792857823917">"Не, благодаря"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml
index 65f92c9..1e8fd0b 100644
--- a/packages/CompanionDeviceManager/res/values-bn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bn/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> বেছে নিন যেটি <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ম্যানেজ করবে"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইস"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"আপনার <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ম্যানেজ করার জন্য <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> সেট করুন"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>-কে আপনার <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>.ম্যানেজ করতে দিতে হবে। <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> কানেক্ট করা হলে <xliff:g id="APP_NAME2">%3$s</xliff:g> <xliff:g id="PERMISSIONS">%4$s</xliff:g> অ্যাক্সেস করতে পারবে।"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"হ্যাঁ"</string>
<string name="consent_no" msgid="1335543792857823917">"না থাক"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml
index f8e24b7..133aea3 100644
--- a/packages/CompanionDeviceManager/res/values-bs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Prateći upravitelj uređaja"</string>
<string name="chooser_title" msgid="2262294130493605839">"Odaberite uređaj <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Postavite aplikaciju <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da upravlja vašim uređajem <xliff:g id="PROFILE_NAME">%2$s</xliff:g> — <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Potrebna je aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> za upravljanje uređajem <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME2">%3$s</xliff:g> će dobiti pristup uslugama <xliff:g id="PERMISSIONS">%4$s</xliff:g> dok je uređaj <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> povezan."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Da"</string>
<string name="consent_no" msgid="1335543792857823917">"Ne, hvala"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml
index ae8ca9f..cf26b08 100644
--- a/packages/CompanionDeviceManager/res/values-ca/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Gestor de dispositius complementaris"</string>
<string name="chooser_title" msgid="2262294130493605839">"Tria un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> perquè el gestioni <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositiu"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Defineix que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gestioni el teu <xliff:g id="PROFILE_NAME">%2$s</xliff:g> (<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>)"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Cal <xliff:g id="APP_NAME_0">%1$s</xliff:g> per gestionar el teu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> tindrà accés als permisos <xliff:g id="PERMISSIONS">%4$s</xliff:g> mentre el <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> estigui connectat."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Sí"</string>
<string name="consent_no" msgid="1335543792857823917">"No, gràcies"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml
index 675bd29..389ccd0 100644
--- a/packages/CompanionDeviceManager/res/values-cs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Správce doprovodných zařízení"</string>
<string name="chooser_title" msgid="2262294130493605839">"Vyberte zařízení <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, které chcete spravovat pomocí aplikace <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"zařízení"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"hodinky"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Nastavit aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ke správě tohoto zařízení: <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Ke správě zařízení <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> je potřeba aplikace <xliff:g id="APP_NAME_0">%1$s</xliff:g>. Dokud bude zařízení <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> připojeno, bude mít aplikace <xliff:g id="APP_NAME2">%3$s</xliff:g> přístup k těmto oprávněním: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Ke správě profilu <xliff:g id="PROFILE_NAME">%2$s</xliff:g> je potřeba aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Ano"</string>
<string name="consent_no" msgid="1335543792857823917">"Ne, díky"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml
index a6720fc..30a331a 100644
--- a/packages/CompanionDeviceManager/res/values-da/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-da/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Medfølgende enhedshåndtering"</string>
<string name="chooser_title" msgid="2262294130493605839">"Vælg den enhed (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), som skal administreres af <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"enhed"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Angiv <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> til administration af: <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> er nødvendig for at administrere: <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> får adgang til <xliff:g id="PERMISSIONS">%4$s</xliff:g>, mens <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> er forbundet."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Ja"</string>
<string name="consent_no" msgid="1335543792857823917">"Nej tak"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml
index eb2631f..ead68e3 100644
--- a/packages/CompanionDeviceManager/res/values-de/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-de/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Begleitgerät-Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Gerät (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) auswählen, das von <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> verwaltet werden soll"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"Gerät"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> zum Verwalten deines Geräts (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>) festlegen – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ist erforderlich, um dein Gerät (<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>) zu verwalten. <xliff:g id="APP_NAME2">%3$s</xliff:g> erhält Zugriff auf <xliff:g id="PERMISSIONS">%4$s</xliff:g>, während eine Verbindung mit <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> besteht."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Ja"</string>
<string name="consent_no" msgid="1335543792857823917">"Nein danke"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-el/strings.xml b/packages/CompanionDeviceManager/res/values-el/strings.xml
index cb31866..4867a8e 100644
--- a/packages/CompanionDeviceManager/res/values-el/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-el/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Διαχείριση συνοδευτικής εφαρμογής"</string>
<string name="chooser_title" msgid="2262294130493605839">"Επιλέξτε ένα προφίλ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> για διαχείριση από την εφαρμογή <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"συσκευή"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Ορίστε μια εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> για διαχείριση του προφίλ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Η εφαρμογή <xliff:g id="APP_NAME_0">%1$s</xliff:g> απαιτείται για τη διαχείριση του προφίλ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. Η εφαρμογή <xliff:g id="APP_NAME2">%3$s</xliff:g> θα έχει πρόσβαση στις άδειες <xliff:g id="PERMISSIONS">%4$s</xliff:g> ενώ είναι συνδεδεμένο το προφίλ <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Ναι"</string>
<string name="consent_no" msgid="1335543792857823917">"Όχι, ευχαριστώ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
index a30c199..a0e5091 100644
--- a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Set <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> will get access to <xliff:g id="PERMISSIONS">%4$s</xliff:g> while the <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> is connected."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Yes"</string>
<string name="consent_no" msgid="1335543792857823917">"No, thanks"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
index a30c199..a0e5091 100644
--- a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Set <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> will get access to <xliff:g id="PERMISSIONS">%4$s</xliff:g> while the <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> is connected."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Yes"</string>
<string name="consent_no" msgid="1335543792857823917">"No, thanks"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
index a30c199..a0e5091 100644
--- a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Set <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> will get access to <xliff:g id="PERMISSIONS">%4$s</xliff:g> while the <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> is connected."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Yes"</string>
<string name="consent_no" msgid="1335543792857823917">"No, thanks"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
index a30c199..a0e5091 100644
--- a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Set <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> will get access to <xliff:g id="PERMISSIONS">%4$s</xliff:g> while the <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> is connected."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Yes"</string>
<string name="consent_no" msgid="1335543792857823917">"No, thanks"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
index ea39d0a..f3c4b1d 100644
--- a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Set <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> will get access to <xliff:g id="PERMISSIONS">%4$s</xliff:g> while the <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> is connected."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Yes"</string>
<string name="consent_no" msgid="1335543792857823917">"No thanks"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
index 63097dc..5780fb4 100644
--- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Administrador de dispositivo complementario"</string>
<string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para que <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> lo administre"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Configura <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> para administrar <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Se requiere <xliff:g id="APP_NAME_0">%1$s</xliff:g> para administrar tu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> accederá a <xliff:g id="PERMISSIONS">%4$s</xliff:g> mientras tu <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> esté conectado."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Sí"</string>
<string name="consent_no" msgid="1335543792857823917">"No, gracias"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml
index 784c30d..78cfa5a 100644
--- a/packages/CompanionDeviceManager/res/values-es/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Gestor de dispositivos complementario"</string>
<string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para gestionarlo con <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Haz que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gestione tu <xliff:g id="PROFILE_NAME">%2$s</xliff:g> <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Se necesita <xliff:g id="APP_NAME_0">%1$s</xliff:g> para gestionar tu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. Mientras tu <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> esté conectado, <xliff:g id="APP_NAME2">%3$s</xliff:g> tendrá acceso a lo siguiente: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Sí"</string>
<string name="consent_no" msgid="1335543792857823917">"No, gracias"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml
index b505870..3f29da0 100644
--- a/packages/CompanionDeviceManager/res/values-et/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-et/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Kaasseadme haldur"</string>
<string name="chooser_title" msgid="2262294130493605839">"Valige seade <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, mida haldab rakendus <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"seade"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Määrake rakendus <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> haldama teie seadet <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> on vajalik teie seadme <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> haldamiseks. <xliff:g id="APP_NAME2">%3$s</xliff:g> saab juurdepääsuload (<xliff:g id="PERMISSIONS">%4$s</xliff:g>), kui seade <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> on ühendatud."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Jah"</string>
<string name="consent_no" msgid="1335543792857823917">"Tänan, ei"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml
index 826556d..30907a2 100644
--- a/packages/CompanionDeviceManager/res/values-eu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Gailu osagarriaren kudeatzailea"</string>
<string name="chooser_title" msgid="2262294130493605839">"Aukeratu <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> aplikazioak kudeatu beharreko <xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"gailua"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Konfiguratu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> <xliff:g id="PROFILE_NAME">%2$s</xliff:g> (<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>) kudea dezan"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> erabili behar duzu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> kudeatzeko. <xliff:g id="APP_NAME2">%3$s</xliff:g> aplikazioak <xliff:g id="PERMISSIONS">%4$s</xliff:g> atzitu ahalko ditu <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> konektatuta dagoen bitartean."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Bai"</string>
<string name="consent_no" msgid="1335543792857823917">"Ez"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
index 66eafc3..9e1ecb1 100644
--- a/packages/CompanionDeviceManager/res/values-fa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"مدیر دستگاه مرتبط"</string>
<string name="chooser_title" msgid="2262294130493605839">"انتخاب <xliff:g id="PROFILE_NAME">%1$s</xliff:g> برای مدیریت کردن با <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"دستگاه"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"تنظیم <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> برای مدیریت کردن <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"برای مدیریت کردن <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> به <xliff:g id="APP_NAME_0">%1$s</xliff:g> نیاز دارید. وقتی <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> متصل باشد، <xliff:g id="APP_NAME2">%3$s</xliff:g> به <xliff:g id="PERMISSIONS">%4$s</xliff:g> دسترسی پیدا خواهد کرد."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"بله"</string>
<string name="consent_no" msgid="1335543792857823917">"نه متشکرم"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fi/strings.xml b/packages/CompanionDeviceManager/res/values-fi/strings.xml
index d4a20d9..4a1f13f 100644
--- a/packages/CompanionDeviceManager/res/values-fi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fi/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Valitse <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, jota <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> hallinnoi"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"laite"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Aseta <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> profiilin (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>) hallinnoijaksi – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> tarvitaan profiilin (<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>) hallinnointiin. <xliff:g id="APP_NAME2">%3$s</xliff:g> saa käyttöluvat (<xliff:g id="PERMISSIONS">%4$s</xliff:g>), kun <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> on yhdistetty."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Kyllä"</string>
<string name="consent_no" msgid="1335543792857823917">"Ei kiitos"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
index e91ccf4..ce5e262 100644
--- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Gestionnaire d\'appareil compagnon"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choisissez un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Utiliser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pour gérer votre <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"L\'application <xliff:g id="APP_NAME_0">%1$s</xliff:g> est requise pour gérer votre <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> aura accès à <xliff:g id="PERMISSIONS">%4$s</xliff:g> lorsque <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> est connecté."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Oui"</string>
<string name="consent_no" msgid="1335543792857823917">"Non merci"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml
index 756727a..e15639b 100644
--- a/packages/CompanionDeviceManager/res/values-fr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Gestionnaire d\'appareils associés"</string>
<string name="chooser_title" msgid="2262294130493605839">"Sélectionner le/la <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Définir <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pour la gestion de votre <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> est requis pour gérer votre <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> aura accès aux <xliff:g id="PERMISSIONS">%4$s</xliff:g> lorsque le/la <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> sera connecté(e)."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Oui"</string>
<string name="consent_no" msgid="1335543792857823917">"Non, merci"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml
index 7849e42..1205e46 100644
--- a/packages/CompanionDeviceManager/res/values-gl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gl/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Xestor de dispositivos complementarios"</string>
<string name="chooser_title" msgid="2262294130493605839">"Escolle un perfil (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) para que o xestione a aplicación <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Define a aplicación <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> para a xestión do teu perfil (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>): <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Necesítase a aplicación <xliff:g id="APP_NAME_0">%1$s</xliff:g> para xestionar o teu perfil (<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>). <xliff:g id="APP_NAME2">%3$s</xliff:g> terá acceso a varios permisos (<xliff:g id="PERMISSIONS">%4$s</xliff:g>) mentres o perfil (<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>) estea conectado."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Si"</string>
<string name="consent_no" msgid="1335543792857823917">"Non, grazas"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-gu/strings.xml b/packages/CompanionDeviceManager/res/values-gu/strings.xml
index 1f1edd1..e99a3cd 100644
--- a/packages/CompanionDeviceManager/res/values-gu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gu/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"કમ્પેનિયન ડિવાઇસ મેનેજર"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> દ્વારા મેનેજ કરવા માટે કોઈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> પસંદ કરો"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ડિવાઇસ"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"તમારા <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>ને મેનેજ કરવા માટે <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> સેટ કરો"</string>
- <string name="profile_summary" msgid="3167701603666642104">"તમારા <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>ને મેનેજ કરવા માટે <xliff:g id="APP_NAME_0">%1$s</xliff:g> જરૂરી છે. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> જ્યારે કનેક્ટેડ હોય ત્યારે <xliff:g id="APP_NAME2">%3$s</xliff:g>ને <xliff:g id="PERMISSIONS">%4$s</xliff:g>નો ઍક્સેસ મળશે."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"હા"</string>
<string name="consent_no" msgid="1335543792857823917">"ના, આભાર"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
index 6e280b5..80c0d95 100644
--- a/packages/CompanionDeviceManager/res/values-hi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"सहयोगी डिवाइस मैनेजर"</string>
<string name="chooser_title" msgid="2262294130493605839">"कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें, ताकि उसे <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> की मदद से प्रबंधित किया जा सके"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"डिवाइस"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"अपने <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> को प्रबंधित करने के लिए, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को सेट करें"</string>
- <string name="profile_summary" msgid="3167701603666642104">"आपके <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> को प्रबंधित करने के लिए, <xliff:g id="APP_NAME_0">%1$s</xliff:g> की ज़रूरत है. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> के कनेक्ट होने पर, <xliff:g id="APP_NAME2">%3$s</xliff:g> को <xliff:g id="PERMISSIONS">%4$s</xliff:g> का ऐक्सेस मिल जाएगा."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"हां"</string>
<string name="consent_no" msgid="1335543792857823917">"नहीं, रहने दें"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml
index beacbfd..b574ff6 100644
--- a/packages/CompanionDeviceManager/res/values-hr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hr/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Odaberite profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Postavite aplikaciju <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da upravlja vašim profilom <xliff:g id="PROFILE_NAME">%2$s</xliff:g> –- <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Potrebna je <xliff:g id="APP_NAME_0">%1$s</xliff:g> za upravljanje vašim profilom <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME2">%3$s</xliff:g> dobit će pristup dopuštenju za <xliff:g id="PERMISSIONS">%4$s</xliff:g> dok je povezan profil <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Da"</string>
<string name="consent_no" msgid="1335543792857823917">"Ne, hvala"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml
index cd29006..b271b12 100644
--- a/packages/CompanionDeviceManager/res/values-hu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Társeszközök kezelője"</string>
<string name="chooser_title" msgid="2262294130493605839">"A(z) <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> alkalmazással kezelni kívánt <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiválasztása"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"eszköz"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"A(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> alkalmazás beállítása a(z) <xliff:g id="PROFILE_NAME">%2$s</xliff:g> (<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>) kezelésére"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Szükség van a(z) <xliff:g id="APP_NAME_0">%1$s</xliff:g> alkalmazásra a(z) <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> kezeléséhez. Amíg csatlakoztatva van a(z) <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>, a(z) <xliff:g id="APP_NAME2">%3$s</xliff:g> hozzáférést kap a következőkhöz: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Igen"</string>
<string name="consent_no" msgid="1335543792857823917">"Nem"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml
index b0037aa..e865690 100644
--- a/packages/CompanionDeviceManager/res/values-hy/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Ընտրեք <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ը, որը պետք է կառավարվի <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> հավելվածի կողմից"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"սարք"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Ընտրեք <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածը որպես <xliff:g id="PROFILE_NAME">%2$s</xliff:g>ի կառավարիչ․ <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Ձեր <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>ը կառավարելու համար անհրաժեշտ է <xliff:g id="APP_NAME_0">%1$s</xliff:g> հավելվածը։ Երբ <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>ը միացված լինի, <xliff:g id="APP_NAME2">%3$s</xliff:g> հավելվածին հասանելի կլինեն՝ <xliff:g id="PERMISSIONS">%4$s</xliff:g>։"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Այո"</string>
<string name="consent_no" msgid="1335543792857823917">"Ոչ, շնորհակալություն"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml
index cc05490..2d4fd4a 100644
--- a/packages/CompanionDeviceManager/res/values-in/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-in/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Pengelola Perangkat Pendamping"</string>
<string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk dikelola oleh <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"perangkat"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Tetapkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk mengelola <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> diperlukan untuk mengelola <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> akan mendapatkan akses ke <xliff:g id="PERMISSIONS">%4$s</xliff:g> saat <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> terhubung."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Ya"</string>
<string name="consent_no" msgid="1335543792857823917">"Tidak"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml
index d3ada74..8698bfb 100644
--- a/packages/CompanionDeviceManager/res/values-is/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-is/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Stjórnun fylgdartækja"</string>
<string name="chooser_title" msgid="2262294130493605839">"Velja <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sem <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> á að stjórna"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"tæki"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Veita <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> stjórn á <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> er krafist til að stjórna <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> fær aðgang að <xliff:g id="PERMISSIONS">%4$s</xliff:g> þegar <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> er tengt."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Já"</string>
<string name="consent_no" msgid="1335543792857823917">"Nei, takk"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml
index 2632509..beb1482 100644
--- a/packages/CompanionDeviceManager/res/values-it/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-it/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Gestione dispositivi companion"</string>
<string name="chooser_title" msgid="2262294130493605839">"Scegli un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> che sia gestito da <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Configura <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> per gestire il tuo <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"È richiesta l\'app <xliff:g id="APP_NAME_0">%1$s</xliff:g> per gestire il tuo <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> avrà accesso a <xliff:g id="PERMISSIONS">%4$s</xliff:g> quando <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> è connesso."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Sì"</string>
<string name="consent_no" msgid="1335543792857823917">"No, grazie"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml
index ae9d6f4..33950eb 100644
--- a/packages/CompanionDeviceManager/res/values-iw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"ניהול מכשיר מותאם"</string>
<string name="chooser_title" msgid="2262294130493605839">"בחירה של <xliff:g id="PROFILE_NAME">%1$s</xliff:g> לניהול באמצעות <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"מכשיר"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"הגדרה של <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> לניהול <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"האפליקציה <xliff:g id="APP_NAME_0">%1$s</xliff:g> נדרשת לניהול של <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. האפליקציה <xliff:g id="APP_NAME2">%3$s</xliff:g> תקבל גישה אל <xliff:g id="PERMISSIONS">%4$s</xliff:g> כאשר <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> מחובר."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"כן"</string>
<string name="consent_no" msgid="1335543792857823917">"לא תודה"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml
index 3fb0140..b50c56a 100644
--- a/packages/CompanionDeviceManager/res/values-ja/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ja/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"コンパニオン デバイス マネージャ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> の管理対象となる <xliff:g id="PROFILE_NAME">%1$s</xliff:g> の選択"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"デバイス"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> で <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> を管理するよう設定する"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> を管理するために <xliff:g id="APP_NAME_0">%1$s</xliff:g> が必要です。<xliff:g id="PROFILE_NAME2">%5$s</xliff:g> の接続中に、<xliff:g id="APP_NAME2">%3$s</xliff:g> が <xliff:g id="PERMISSIONS">%4$s</xliff:g> にアクセスします。"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"はい"</string>
<string name="consent_no" msgid="1335543792857823917">"いいえ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ka/strings.xml b/packages/CompanionDeviceManager/res/values-ka/strings.xml
index 5b36106..4ab0abd 100644
--- a/packages/CompanionDeviceManager/res/values-ka/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ka/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"კომპანიონი მოწყობილობების მენეჯერი"</string>
<string name="chooser_title" msgid="2262294130493605839">"აირჩიეთ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, რომელიც უნდა მართოს <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>-მა"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"მოწყობილობა"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"დააყენეთ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>, რომ მართოს თქვენი <xliff:g id="PROFILE_NAME">%2$s</xliff:g> — <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"თქვენი <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>-ის სამართავად საჭიროა <xliff:g id="APP_NAME_0">%1$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> მიიღებს წვდომას <xliff:g id="PERMISSIONS">%4$s</xliff:g>-ზე, სანამ <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> დაკავშირებული იქნება."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"დიახ"</string>
<string name="consent_no" msgid="1335543792857823917">"არა, გმადლობთ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml
index 6ff3f83..fcfe030 100644
--- a/packages/CompanionDeviceManager/res/values-kk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kk/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> арқылы басқарылатын <xliff:g id="PROFILE_NAME">%1$s</xliff:g> құрылғысын таңдаңыз"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"құрылғы"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>) құрылғысын басқаруға рұқсат беру"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> құрылғысын басқару үшін <xliff:g id="APP_NAME_0">%1$s</xliff:g> қолданбасы керек. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> құрылғысы жалғанған кезде<xliff:g id="APP_NAME2">%3$s</xliff:g> қолданбасы мына параметрлерді пайдалана алады: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Иә"</string>
<string name="consent_no" msgid="1335543792857823917">"Жоқ, рақмет"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml
index cdcebad..e708004 100644
--- a/packages/CompanionDeviceManager/res/values-km/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-km/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"កម្មវិធីគ្រប់គ្រងឧបករណ៍ដៃគូ"</string>
<string name="chooser_title" msgid="2262294130493605839">"ជ្រើសរើស <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ដើម្បីឱ្យស្ថិតក្រោមការគ្រប់គ្រងរបស់ <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ឧបករណ៍"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"កំណត់ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ដើម្បីគ្រប់គ្រង <xliff:g id="PROFILE_NAME">%2$s</xliff:g> របស់អ្នក - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"ចាំបាច់ត្រូវមាន <xliff:g id="APP_NAME_0">%1$s</xliff:g> ដើម្បីគ្រប់គ្រង <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> របស់អ្នក។ <xliff:g id="APP_NAME2">%3$s</xliff:g> នឹងអាចចូលប្រើ <xliff:g id="PERMISSIONS">%4$s</xliff:g> នៅពេលភ្ជាប់ <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>។"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"បាទ/ចាស"</string>
<string name="consent_no" msgid="1335543792857823917">"ទេ អរគុណ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml
index 47cf76c..f4ae18f 100644
--- a/packages/CompanionDeviceManager/res/values-kn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"ಕಂಪ್ಯಾನಿಯನ್ ಸಾಧನ ನಿರ್ವಾಹಕರು"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ಮೂಲಕ ನಿರ್ವಹಿಸಬೇಕಾದ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ಸಾಧನ"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"ನಿಮ್ಮ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ಅನ್ನು ನಿರ್ವಹಿಸಲು, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಅನ್ನು ನಿರ್ವಹಿಸಿ"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು, <xliff:g id="APP_NAME_0">%1$s</xliff:g> ಅಗತ್ಯವಿದೆ. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> ಕನೆಕ್ಟ್ ಆದಾಗ, <xliff:g id="PERMISSIONS">%4$s</xliff:g> ಗೆ <xliff:g id="APP_NAME2">%3$s</xliff:g> ಪ್ರವೇಶವನ್ನು ಪಡೆಯುತ್ತದೆ."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"ಹೌದು"</string>
<string name="consent_no" msgid="1335543792857823917">"ಬೇಡ, ಧನ್ಯವಾದಗಳು"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
index f2904138..299d586 100644
--- a/packages/CompanionDeviceManager/res/values-ko/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"부속 기기 관리자"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>에서 관리할 <xliff:g id="PROFILE_NAME">%1$s</xliff:g>을(를) 선택"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"기기"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>에서 <xliff:g id="PROFILE_NAME">%2$s</xliff:g>(<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>)을(를) 관리하도록 설정"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>을(를) 관리하려면 <xliff:g id="APP_NAME_0">%1$s</xliff:g> 앱이 필요합니다. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>이(가) 연결되어 있는 동안 <xliff:g id="APP_NAME2">%3$s</xliff:g> 앱이 <xliff:g id="PERMISSIONS">%4$s</xliff:g>에 액세스할 수 있습니다."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"예"</string>
<string name="consent_no" msgid="1335543792857823917">"취소"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
index 9cce298..35ee34d 100644
--- a/packages/CompanionDeviceManager/res/values-ky/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> тарабынан башкарылсын"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"түзмөк"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> түзмөгүңүздү башкарсын"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> профилиңизди башкаруу үчүн <xliff:g id="APP_NAME_0">%1$s</xliff:g> керек. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> туташып турганда <xliff:g id="APP_NAME2">%3$s</xliff:g> колдонмосунун төмөнкүлөргө уруксаты болот: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Ооба"</string>
<string name="consent_no" msgid="1335543792857823917">"Жок, рахмат"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lo/strings.xml b/packages/CompanionDeviceManager/res/values-lo/strings.xml
index 5fcbf7df..a27bc15 100644
--- a/packages/CompanionDeviceManager/res/values-lo/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lo/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"ຕົວຈັດການອຸປະກອນປະກອບ"</string>
<string name="chooser_title" msgid="2262294130493605839">"ເລືອກ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ເພື່ອໃຫ້ຖືກຈັດການໂດຍ <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ອຸປະກອນ"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"ຕັ້ງ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ເພື່ອຈັດການ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ຂອງທ່ານ"</string>
- <string name="profile_summary" msgid="3167701603666642104">"ຕ້ອງໃຊ້ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ເພື່ອຈັດການ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> ຂອງທ່ານ. <xliff:g id="APP_NAME2">%3$s</xliff:g> ຈະໄດ້ຮັບສິດເຂົ້າເຖິງ <xliff:g id="PERMISSIONS">%4$s</xliff:g> ໃນເວລາເຊື່ອມຕໍ່ <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"ແມ່ນແລ້ວ"</string>
<string name="consent_no" msgid="1335543792857823917">"ບໍ່, ຂອບໃຈ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lt/strings.xml b/packages/CompanionDeviceManager/res/values-lt/strings.xml
index 56930d3..11510ac 100644
--- a/packages/CompanionDeviceManager/res/values-lt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lt/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Jūsų <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, kurį valdys <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> (pasirinkite)"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"įrenginys"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Nustatyti, kad <xliff:g id="PROFILE_NAME">%2$s</xliff:g> <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> būtų valdomas programos <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Tam, kad būtų valdomas jūsų <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>, reikalinga programa „<xliff:g id="APP_NAME_0">%1$s</xliff:g>“. Kol prijungtas <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>, „<xliff:g id="APP_NAME2">%3$s</xliff:g>“ gaus prieigą prie šių elementų: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Taip"</string>
<string name="consent_no" msgid="1335543792857823917">"Ne, ačiū"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml
index a9d2151..6a85c83 100644
--- a/packages/CompanionDeviceManager/res/values-lv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lv/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Palīgierīču pārzinis"</string>
<string name="chooser_title" msgid="2262294130493605839">"Profila (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) izvēle, ko pārvaldīt lietotnē <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ierīce"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Lietotnes <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> iestatīšana profila (<xliff:g id="PROFILE_NAME">%2$s</xliff:g> — <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>) pārvaldībai"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Lai pārvaldītu profilu (<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>), nepieciešama lietotne <xliff:g id="APP_NAME_0">%1$s</xliff:g>. Kamēr profils (<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>) būs pievienots, lietotnei <xliff:g id="APP_NAME2">%3$s</xliff:g> tiks piešķirta piekļuve šādām atļaujām: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Jā"</string>
<string name="consent_no" msgid="1335543792857823917">"Nē, paldies"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml
index 5cc18c5..6fed96b 100644
--- a/packages/CompanionDeviceManager/res/values-mk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Изберете <xliff:g id="PROFILE_NAME">%1$s</xliff:g> со којшто ќе управува <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"уред"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Поставете ја <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да управува со <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> е потребна за да управува со <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> ќе добие пристап до <xliff:g id="PERMISSIONS">%4$s</xliff:g> додека <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> е поврзан."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Да"</string>
<string name="consent_no" msgid="1335543792857823917">"Не, фала"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ml/strings.xml b/packages/CompanionDeviceManager/res/values-ml/strings.xml
index b6734e8..6b071cd 100644
--- a/packages/CompanionDeviceManager/res/values-ml/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ml/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"കമ്പാനിയൻ ഉപകരണ മാനേജർ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ഉപയോഗിച്ച് മാനേജ് ചെയ്യുന്നതിന് ഒരു <xliff:g id="PROFILE_NAME">%1$s</xliff:g> തിരഞ്ഞെടുക്കുക"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ഉപകരണം"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"നിങ്ങളുടെ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> മാനേജ് ചെയ്യുന്നതിന് <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> സജ്ജീകരിക്കുക - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> എന്ന ആപ്പിന് നിങ്ങളുടെ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> മാനേജ് ചെയ്യേണ്ടതുണ്ട്. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> കണക്റ്റ് ചെയ്തിരിക്കുമ്പോൾ <xliff:g id="APP_NAME2">%3$s</xliff:g> എന്ന ആപ്പിന് <xliff:g id="PERMISSIONS">%4$s</xliff:g> എന്നിവയിലേക്ക് ആക്സസ് ലഭിക്കും."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"വേണം"</string>
<string name="consent_no" msgid="1335543792857823917">"വേണ്ട"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml
index cd4fdbf..4d048cb 100644
--- a/packages/CompanionDeviceManager/res/values-mn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>-н удирдах<xliff:g id="PROFILE_NAME">%1$s</xliff:g>-г сонгоно уу"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"төхөөрөмж"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g>-аа удирдахын тулд <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-г тохируулна уу - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Таны <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>-г удирдахын тулд <xliff:g id="APP_NAME_0">%1$s</xliff:g> шаардлагатай. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> холбогдсон үед <xliff:g id="APP_NAME2">%3$s</xliff:g> нь <xliff:g id="PERMISSIONS">%4$s</xliff:g>-д хандах эрхтэй болно."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Тийм"</string>
<string name="consent_no" msgid="1335543792857823917">"Үгүй, баярлалаа"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml
index 65bf262..68f9109 100644
--- a/packages/CompanionDeviceManager/res/values-mr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mr/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"सहयोगी डिव्हाइस व्यवस्थापक"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> द्वारे व्यवस्थापित करण्यासाठी <xliff:g id="PROFILE_NAME">%1$s</xliff:g> निवडा"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"डिव्हाइस"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"तुमची <xliff:g id="PROFILE_NAME">%2$s</xliff:g> व्यवस्थापित करण्यासाठी <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> सेट करा - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"तुमची <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> व्यवस्थापित करण्यासाठी <xliff:g id="APP_NAME_0">%1$s</xliff:g> आवश्यक आहे. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> कनेक्ट केलेली असताना <xliff:g id="APP_NAME2">%3$s</xliff:g> ला <xliff:g id="PERMISSIONS">%4$s</xliff:g> चा अॅक्सेस मिळेल."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"होय"</string>
<string name="consent_no" msgid="1335543792857823917">"नाही, नको"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ms/strings.xml b/packages/CompanionDeviceManager/res/values-ms/strings.xml
index d17041f..1188922 100644
--- a/packages/CompanionDeviceManager/res/values-ms/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ms/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Pengurus Peranti Rakan"</string>
<string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk diurus oleh <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"peranti"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Tetapkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk mengurus <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> anda"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> diperlukan untuk mengurus <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> anda. <xliff:g id="APP_NAME2">%3$s</xliff:g> akan mendapat akses kepada <xliff:g id="PERMISSIONS">%4$s</xliff:g> semasa <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> disambungkan."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Ya"</string>
<string name="consent_no" msgid="1335543792857823917">"Tidak perlu"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-my/strings.xml b/packages/CompanionDeviceManager/res/values-my/strings.xml
index 23f165a..b16869d 100644
--- a/packages/CompanionDeviceManager/res/values-my/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-my/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"တွဲဖက်ကိရိယာ မန်နေဂျာ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> က စီမံခန့်ခွဲရန် <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ကို ရွေးချယ်ပါ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"စက်"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"သင်၏ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ကို စီမံခန့်ခွဲရန် <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ကို သတ်မှတ်ပါ"</string>
- <string name="profile_summary" msgid="3167701603666642104">"သင်၏ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> ကို စီမံခန့်ခွဲရန် <xliff:g id="APP_NAME_0">%1$s</xliff:g> ကို လိုအပ်ပါသည်။ <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> ကို ချိတ်ဆက်ထားစဉ် <xliff:g id="APP_NAME2">%3$s</xliff:g> သည် <xliff:g id="PERMISSIONS">%4$s</xliff:g> ကို ဝင်သုံးခွင့်ရပါမည်။"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Yes"</string>
<string name="consent_no" msgid="1335543792857823917">"မလိုပါ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml
index 090f2a2..cac087f 100644
--- a/packages/CompanionDeviceManager/res/values-nb/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Velg <xliff:g id="PROFILE_NAME">%1$s</xliff:g> som skal administreres av <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Angi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> for å administrere <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> kreves for å administrere <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> får tilgang til <xliff:g id="PERMISSIONS">%4$s</xliff:g> når <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> er tilkoblet."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Ja"</string>
<string name="consent_no" msgid="1335543792857823917">"Nei takk"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ne/strings.xml b/packages/CompanionDeviceManager/res/values-ne/strings.xml
index e885674..e390161 100644
--- a/packages/CompanionDeviceManager/res/values-ne/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ne/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"सहयोगी यन्त्रको प्रबन्धक"</string>
<string name="chooser_title" msgid="2262294130493605839">"आफूले <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> प्रयोग गरी व्यवस्थापन गर्न चाहेको <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चयन गर्नुहोस्"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"यन्त्र"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"आफ्नो <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> व्यवस्थापन गर्न <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> तोक्नुहोस्"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> व्यवस्थापन गर्न <xliff:g id="APP_NAME_0">%1$s</xliff:g> इन्स्टल गर्नु पर्ने हुन्छ। <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> कनेक्ट भएका बेला <xliff:g id="APP_NAME2">%3$s</xliff:g> ले <xliff:g id="PERMISSIONS">%4$s</xliff:g> प्रयोग गर्ने अनुमति प्राप्त गर्ने छ।"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"अँ"</string>
<string name="consent_no" msgid="1335543792857823917">"सहमत छुइनँ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-nl/strings.xml b/packages/CompanionDeviceManager/res/values-nl/strings.xml
index 5a7fb3a..2153770 100644
--- a/packages/CompanionDeviceManager/res/values-nl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nl/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Een <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiezen om te beheren met <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"apparaat"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> instellen om je <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> te beheren"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Je hebt <xliff:g id="APP_NAME_0">%1$s</xliff:g> nodig om je <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> te beheren. <xliff:g id="APP_NAME2">%3$s</xliff:g> krijgt toegang tot <xliff:g id="PERMISSIONS">%4$s</xliff:g> terwijl je <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> is verbonden."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Ja"</string>
<string name="consent_no" msgid="1335543792857823917">"Nee, bedankt"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml
index 03fae5c..d1aa50b 100644
--- a/packages/CompanionDeviceManager/res/values-or/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-or/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"ସହଯୋଗୀ ଡିଭାଇସ୍ ପରିଚାଳକ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ଦ୍ୱାରା ପରିଚାଳିତ ହେବା ପାଇଁ ଏକ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>କୁ ବାଛନ୍ତୁ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ଡିଭାଇସ୍"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"ଆପଣଙ୍କ <xliff:g id="PROFILE_NAME">%2$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ ସେଟ୍ କରନ୍ତୁ - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"ଆପଣଙ୍କ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ <xliff:g id="APP_NAME_0">%1$s</xliff:g>ର ଆବଶ୍ୟକତା ଅଛି। <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> ସଂଯୁକ୍ତ ହୋଇଥିବା ସମୟରେ <xliff:g id="APP_NAME2">%3$s</xliff:g> <xliff:g id="PERMISSIONS">%4$s</xliff:g>କୁ ଆକ୍ସେସ୍ ପାଇବ।"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"ହଁ"</string>
<string name="consent_no" msgid="1335543792857823917">"ନା, ଧନ୍ୟବାଦ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml
index 33135b2..ff211f2 100644
--- a/packages/CompanionDeviceManager/res/values-pa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"ਸੰਬੰਧੀ ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਕ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤੇ ਜਾਣ ਲਈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ਚੁਣੋ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ਡੀਵਾਈਸ"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ ਤੁਹਾਡਾ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਸੈੱਟ ਕਰੋ"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡਾ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਦੀ ਲੋੜ ਹੈ। <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> ਕਨੈਕਟ ਕੀਤੇ ਹੋਣ \'ਤੇ <xliff:g id="APP_NAME2">%3$s</xliff:g> ਨੂੰ <xliff:g id="PERMISSIONS">%4$s</xliff:g> ਤੱਕ ਪਹੁੰਚ ਪ੍ਰਾਪਤ ਹੋ ਜਾਵੇਗੀ।"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"ਹਾਂ"</string>
<string name="consent_no" msgid="1335543792857823917">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml
index a828370..b16d045 100644
--- a/packages/CompanionDeviceManager/res/values-pl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Menedżer urządzeń towarzyszących"</string>
<string name="chooser_title" msgid="2262294130493605839">"Wybierz profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, którym ma zarządzać aplikacja <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"urządzenie"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Ustaw aplikację <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> do zarządzania profilem <xliff:g id="PROFILE_NAME">%2$s</xliff:g> na urządzeniu <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Aplikacja <xliff:g id="APP_NAME_0">%1$s</xliff:g> jest wymagana do zarządzania profilem <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. Kiedy profil <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> będzie połączony, <xliff:g id="APP_NAME2">%3$s</xliff:g> będzie mieć te uprawnienia: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Tak"</string>
<string name="consent_no" msgid="1335543792857823917">"Nie, dziękuję"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
index 4258e70..40f9d2d 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Gerenciador de dispositivos complementar"</string>
<string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerenciado pelo app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Defina o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> como gerenciador do seu <xliff:g id="PROFILE_NAME">%2$s</xliff:g> (<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>)"</string>
- <string name="profile_summary" msgid="3167701603666642104">"O app <xliff:g id="APP_NAME_0">%1$s</xliff:g> é necessário para gerenciar seu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> terá acesso a <xliff:g id="PERMISSIONS">%4$s</xliff:g> enquanto o <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> estiver conectado."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Sim"</string>
<string name="consent_no" msgid="1335543792857823917">"Agora não"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
index 45b03d6..745d163 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Gestor de dispositivos associados"</string>
<string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerido pela app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"relógio"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Defina a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> para gerir o seu <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"A app <xliff:g id="APP_NAME_0">%1$s</xliff:g> é necessária para gerir o seu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. A app <xliff:g id="APP_NAME2">%3$s</xliff:g> terá acesso a <xliff:g id="PERMISSIONS">%4$s</xliff:g> enquanto o <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> estiver associado."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> é necessária para gerir o seu <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Sim"</string>
<string name="consent_no" msgid="1335543792857823917">"Não, obrigado"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml
index 4258e70..40f9d2d 100644
--- a/packages/CompanionDeviceManager/res/values-pt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Gerenciador de dispositivos complementar"</string>
<string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerenciado pelo app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Defina o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> como gerenciador do seu <xliff:g id="PROFILE_NAME">%2$s</xliff:g> (<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>)"</string>
- <string name="profile_summary" msgid="3167701603666642104">"O app <xliff:g id="APP_NAME_0">%1$s</xliff:g> é necessário para gerenciar seu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> terá acesso a <xliff:g id="PERMISSIONS">%4$s</xliff:g> enquanto o <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> estiver conectado."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Sim"</string>
<string name="consent_no" msgid="1335543792857823917">"Agora não"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml
index 060e996..6040adf 100644
--- a/packages/CompanionDeviceManager/res/values-ro/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ro/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Manager de dispozitiv Companion"</string>
<string name="chooser_title" msgid="2262294130493605839">"Alegeți un profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> pe care să îl gestioneze <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispozitiv"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Setați <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pentru a vă gestiona profilul <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> este necesară pentru a vă gestiona profilul <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> va primi acces la <xliff:g id="PERMISSIONS">%4$s</xliff:g> în timp ce profilul <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> este conectat."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Da"</string>
<string name="consent_no" msgid="1335543792857823917">"Nu, mulțumesc"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml
index 7982507..9939a82 100644
--- a/packages/CompanionDeviceManager/res/values-ru/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Управление подключенными устройствами"</string>
<string name="chooser_title" msgid="2262294130493605839">"Выберите устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), которым будет управлять приложение <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Разрешите приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> управлять устройством <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>)"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Приложение \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" необходимо для управления устройством (<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>). При подключении к устройству (<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>) приложение \"<xliff:g id="APP_NAME2">%3$s</xliff:g>\" получит доступ к следующему: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Да"</string>
<string name="consent_no" msgid="1335543792857823917">"Нет"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml
index 8bbc1a6..6e6b029 100644
--- a/packages/CompanionDeviceManager/res/values-si/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-si/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"සහායක උපාංග කළමනාකරු"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> මගින් කළමනාකරණය කරනු ලැබීමට <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ක් තෝරන්න"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"උපාංගය"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ඔබගේ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> කළමනාකරණය කිරීමට සකසන්න - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ඔබගේ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> කළමනාකරණය කිරීමට අවශ්යයි. <xliff:g id="APP_NAME2">%3$s</xliff:g> හට <xliff:g id="PERMISSIONS">%4$s</xliff:g> වෙත ප්රවේශය <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> සම්බන්ධිත අතරතුර ලැබෙනු ඇත."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"ඔව්"</string>
<string name="consent_no" msgid="1335543792857823917">"එපා, ස්තුතියි"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml
index 1037a96..520aa09 100644
--- a/packages/CompanionDeviceManager/res/values-sk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Správca sprievodných zariadení"</string>
<string name="chooser_title" msgid="2262294130493605839">"Vyberte profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, ktorý bude spravovať aplikácia <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"zariadenie"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Nastavte aplikáciu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>, aby spravovala profil <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Na správu profilu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> je potrebná aplikácia <xliff:g id="APP_NAME_0">%1$s</xliff:g>. Kým bude profil <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> pripojený, <xliff:g id="APP_NAME2">%3$s</xliff:g> získa prístup k povoleniam <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Áno"</string>
<string name="consent_no" msgid="1335543792857823917">"Nie, vďaka"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml
index f2d4c6f..f60cab8 100644
--- a/packages/CompanionDeviceManager/res/values-sl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Upravitelj spremljevalnih naprav"</string>
<string name="chooser_title" msgid="2262294130493605839">"Izbira naprave <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, ki jo bo upravljala aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"naprava"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Nastavitev aplikacije <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>, ki bo upravljala napravo <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Za upravljanje naprave <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> potrebujete aplikacijo <xliff:g id="APP_NAME_0">%1$s</xliff:g>. Ko je naprava <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> povezana, bo aplikaciji <xliff:g id="APP_NAME2">%3$s</xliff:g> omogočen dostop do teh dovoljenj: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Da"</string>
<string name="consent_no" msgid="1335543792857823917">"Ne, hvala"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml
index c9336b3..4c308e8 100644
--- a/packages/CompanionDeviceManager/res/values-sq/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Menaxheri i pajisjes shoqëruese"</string>
<string name="chooser_title" msgid="2262294130493605839">"Zgjidh një profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> që do të menaxhohet nga <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"pajisja"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Cakto <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> që të menaxhojë profilin tënd <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Nevojitet <xliff:g id="APP_NAME_0">%1$s</xliff:g> për të menaxhuar profilin tënd <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> do të marrë qasje në <xliff:g id="PERMISSIONS">%4$s</xliff:g> ndërkohë që është lidhur profili <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Po"</string>
<string name="consent_no" msgid="1335543792857823917">"Jo, faleminderit"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml
index 5298194..da08d87 100644
--- a/packages/CompanionDeviceManager/res/values-sr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sr/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Менаџер придруженог уређаја"</string>
<string name="chooser_title" msgid="2262294130493605839">"Одаберите профил <xliff:g id="PROFILE_NAME">%1$s</xliff:g> којим ће управљати апликација <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"уређај"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Подесите апликацију <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да управља профилом <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Апликација <xliff:g id="APP_NAME_0">%1$s</xliff:g> је неопходна за управљање профилом <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> ће добити приступ дозволама за <xliff:g id="PERMISSIONS">%4$s</xliff:g> док је <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> повезан."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Да"</string>
<string name="consent_no" msgid="1335543792857823917">"Не, хвала"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml
index caacba0..a73cbfa 100644
--- a/packages/CompanionDeviceManager/res/values-sv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sv/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Välj en <xliff:g id="PROFILE_NAME">%1$s</xliff:g> för hantering av <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Konfigurera <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> för att hantera din <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> krävs för att hantera din <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> får åtkomst till <xliff:g id="PERMISSIONS">%4$s</xliff:g> medan <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> är ansluten."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Ja"</string>
<string name="consent_no" msgid="1335543792857823917">"Nej tack"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sw/strings.xml b/packages/CompanionDeviceManager/res/values-sw/strings.xml
index ae8ade7..5865ec9 100644
--- a/packages/CompanionDeviceManager/res/values-sw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sw/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Kidhibiti cha Vifaa Visaidizi"</string>
<string name="chooser_title" msgid="2262294130493605839">"Chagua <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ili idhibitiwe na <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"kifaa"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Weka <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ili udhibiti <xliff:g id="PROFILE_NAME">%2$s</xliff:g> yako - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> linahitajika ili kudhibiti <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> wako. <xliff:g id="APP_NAME2">%3$s</xliff:g> itapata uwezo wa kufikia <xliff:g id="PERMISSIONS">%4$s</xliff:g> wakati <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> imeunganishwa."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Ndiyo"</string>
<string name="consent_no" msgid="1335543792857823917">"Hapana"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ta/strings.xml b/packages/CompanionDeviceManager/res/values-ta/strings.xml
index 373ed45..f9d6401 100644
--- a/packages/CompanionDeviceManager/res/values-ta/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ta/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"கம்பேனியன் சாதன நிர்வாகி"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ஆப்ஸ் நிர்வகிக்கக்கூடிய <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ஐத் தேர்ந்தெடுங்கள்"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"சாதனம்"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ஐ நிர்வகிக்க <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அமையுங்கள்"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> ஐ நிர்வகிக்க <xliff:g id="APP_NAME_0">%1$s</xliff:g> ஆப்ஸ் வேண்டும். <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> இணைக்கப்பட்டதும் <xliff:g id="PERMISSIONS">%4$s</xliff:g> ஆகியவற்றுக்கான அணுகலை <xliff:g id="APP_NAME2">%3$s</xliff:g> ஆப்ஸ் பெறும்."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"ஆம்"</string>
<string name="consent_no" msgid="1335543792857823917">"வேண்டாம்"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml
index f73e713..82616cc 100644
--- a/packages/CompanionDeviceManager/res/values-te/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-te/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"సహచర పరికర మేనేజర్"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ద్వారా మేనేజ్ చేయబడటానికి ఒక <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ను ఎంచుకోండి"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"పరికరం"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"మీ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>ను మేనేజ్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను సెటప్ చేయండి"</string>
- <string name="profile_summary" msgid="3167701603666642104">"మీ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>ను మేనేజ్ చేయడానికి <xliff:g id="APP_NAME_0">%1$s</xliff:g> అవసరం ఉంది. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> కనెక్ట్ అయినప్పుడు <xliff:g id="APP_NAME2">%3$s</xliff:g>, <xliff:g id="PERMISSIONS">%4$s</xliff:g>కు యాక్సెస్ను పొందుతుంది."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"అవును"</string>
<string name="consent_no" msgid="1335543792857823917">"వద్దు, ధన్యవాదాలు"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml
index 8c1848a..77a9fff 100644
--- a/packages/CompanionDeviceManager/res/values-th/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-th/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"เลือก<xliff:g id="PROFILE_NAME">%1$s</xliff:g>ที่จะให้มีการจัดการโดย <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"อุปกรณ์"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"ตั้งค่า <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ให้จัดการ<xliff:g id="PROFILE_NAME">%2$s</xliff:g>ของคุณ - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"ต้องใช้ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ในการจัดการ<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> <xliff:g id="APP_NAME2">%3$s</xliff:g> จะได้รับสิทธิ์เข้าถึง<xliff:g id="PERMISSIONS">%4$s</xliff:g>ในขณะที่มีการเชื่อมต่อ<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"ใช่"</string>
<string name="consent_no" msgid="1335543792857823917">"ไม่เป็นไร"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml
index 8fcc3d2..6d62642 100644
--- a/packages/CompanionDeviceManager/res/values-tl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tl/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Kasamang Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Pumili ng <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para pamahalaan ng <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Itakda ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> para pamahalaan ang iyong <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Kailangan ang <xliff:g id="APP_NAME_0">%1$s</xliff:g> para pamahalaan ang iyong <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. Magkakaroon ng access ang <xliff:g id="APP_NAME2">%3$s</xliff:g> sa <xliff:g id="PERMISSIONS">%4$s</xliff:g> habang nakakonekta ang <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Oo"</string>
<string name="consent_no" msgid="1335543792857823917">"Huwag na lang"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
index 255eca5..2c30ea7 100644
--- a/packages/CompanionDeviceManager/res/values-tr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> tarafından yönetilecek bir <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasını, <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> cihazınızı yönetecek şekilde ayarlayın"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>, <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> yönetimi için gereklidir. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> bağlıyken <xliff:g id="APP_NAME2">%3$s</xliff:g>, şunlara erişebilecek: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Evet"</string>
<string name="consent_no" msgid="1335543792857823917">"Hayır, teşekkürler"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-uk/strings.xml b/packages/CompanionDeviceManager/res/values-uk/strings.xml
index b5827f2..f68fd92 100644
--- a/packages/CompanionDeviceManager/res/values-uk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uk/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Диспетчер супутніх пристроїв"</string>
<string name="chooser_title" msgid="2262294130493605839">"Виберіть <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, яким керуватиме додаток <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"пристрій"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Налаштуйте додаток <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>, щоб керувати своїм пристроєм <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>)"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Щоб керувати своїм пристроєм (<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>), вам потрібен додаток <xliff:g id="APP_NAME_0">%1$s</xliff:g>. Коли <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> буде підключено, додаток <xliff:g id="APP_NAME2">%3$s</xliff:g> отримає такі дозволи на доступ: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Так"</string>
<string name="consent_no" msgid="1335543792857823917">"Ні, дякую"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
index 2bbffdc..967b7f9 100644
--- a/packages/CompanionDeviceManager/res/values-ur/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"ساتھی آلہ مینیجر"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> کے ذریعے نظم کئے جانے کیلئے <xliff:g id="PROFILE_NAME">%1$s</xliff:g> کو منتخب کریں"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"آلہ"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"اپنے <xliff:g id="PROFILE_NAME">%2$s</xliff:g> کا نظم کرنے کے لیے <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو سیٹ کریں - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"آپ کے <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> کا نظم کرنے کے لیے <xliff:g id="APP_NAME_0">%1$s</xliff:g> کی ضرورت ہے۔ <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> کے منسلک ہونے پر <xliff:g id="APP_NAME2">%3$s</xliff:g> <xliff:g id="PERMISSIONS">%4$s</xliff:g> تک رسائی حاصل کرے گا۔"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"ہاں"</string>
<string name="consent_no" msgid="1335543792857823917">"نہیں شکریہ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-uz/strings.xml b/packages/CompanionDeviceManager/res/values-uz/strings.xml
index 96c49f2..c8c4b22 100644
--- a/packages/CompanionDeviceManager/res/values-uz/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uz/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> boshqaradigan <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qurilmasini tanlang"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"qurilma"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> qurilmalarini boshqarish uchun <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasini sozlang"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ilovasi <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> qurilmasini boshqarish uchun kerak. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> qurilmasiga <xliff:g id="APP_NAME2">%3$s</xliff:g> ilovasi ulansa, u quyidagi ruxsatlarni oladi: <xliff:g id="PERMISSIONS">%4$s</xliff:g>"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Ha"</string>
<string name="consent_no" msgid="1335543792857823917">"Kerak emas"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml
index d67db41..f0234a4 100644
--- a/packages/CompanionDeviceManager/res/values-vi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-vi/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Chọn một <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sẽ do <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> quản lý"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"thiết bị"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Đặt <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> để quản lý <xliff:g id="PROFILE_NAME">%2$s</xliff:g> của bạn – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Cần có <xliff:g id="APP_NAME_0">%1$s</xliff:g> để quản lý <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> của bạn. <xliff:g id="APP_NAME2">%3$s</xliff:g> sẽ có quyền truy cập vào <xliff:g id="PERMISSIONS">%4$s</xliff:g> trong khi <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> được kết nối."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Có"</string>
<string name="consent_no" msgid="1335543792857823917">"Không, cảm ơn"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
index a1abd98..caf2321 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"配套设备管理器"</string>
<string name="chooser_title" msgid="2262294130493605839">"选择要由<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"设备"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"设为由<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>管理您的<xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"若要管理<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>,您需要使用<xliff:g id="APP_NAME_0">%1$s</xliff:g>。在已连接<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>的情况下,<xliff:g id="APP_NAME2">%3$s</xliff:g>将能够访问<xliff:g id="PERMISSIONS">%4$s</xliff:g>。"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"好"</string>
<string name="consent_no" msgid="1335543792857823917">"不用了"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
index 57d2173..5ec64a5 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"隨附裝置管理員"</string>
<string name="chooser_title" msgid="2262294130493605839">"選擇由 <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> 管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"設定 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 來管理您的 <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"必須使用 <xliff:g id="APP_NAME_0">%1$s</xliff:g> 來管理您的<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>。連結<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>後,<xliff:g id="APP_NAME2">%3$s</xliff:g> 將可以存取<xliff:g id="PERMISSIONS">%4$s</xliff:g>。"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"是"</string>
<string name="consent_no" msgid="1335543792857823917">"不用了,謝謝"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
index c9a2fd8..b8c2ed0 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"隨附裝置管理員"</string>
<string name="chooser_title" msgid="2262294130493605839">"選擇要讓「<xliff:g id="APP_NAME">%2$s</xliff:g>」<strong></strong>管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"授權讓「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>管理你的<xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"如要管理你的<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>,必須使用「<xliff:g id="APP_NAME_0">%1$s</xliff:g>」。與<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>連線時,「<xliff:g id="APP_NAME2">%3$s</xliff:g>」將有權存取你的<xliff:g id="PERMISSIONS">%4$s</xliff:g>。"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"是"</string>
<string name="consent_no" msgid="1335543792857823917">"不用了,謝謝"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zu/strings.xml b/packages/CompanionDeviceManager/res/values-zu/strings.xml
index c811037..7df0869 100644
--- a/packages/CompanionDeviceManager/res/values-zu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zu/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Isiphathi sedivayisi esihambisanayo"</string>
<string name="chooser_title" msgid="2262294130493605839">"Khetha i-<xliff:g id="PROFILE_NAME">%1$s</xliff:g> ezophathwa yi-<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"idivayisi"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Setha i-<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukuba iphathe i-<xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"I-<xliff:g id="APP_NAME_0">%1$s</xliff:g> iyadingeka ukuphatha i-<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> yakho. I-<xliff:g id="APP_NAME2">%3$s</xliff:g> izothola ukufinyelela ku-<xliff:g id="PERMISSIONS">%4$s</xliff:g> kuyilapho i-<xliff:g id="PROFILE_NAME2">%5$s</xliff:g> ixhunyiwe."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Yebo"</string>
<string name="consent_no" msgid="1335543792857823917">"Cha ngiyabonga"</string>
</resources>
diff --git a/packages/InputDevices/res/values-eu/strings.xml b/packages/InputDevices/res/values-eu/strings.xml
index 77d252d..eb95466 100644
--- a/packages/InputDevices/res/values-eu/strings.xml
+++ b/packages/InputDevices/res/values-eu/strings.xml
@@ -48,6 +48,6 @@
<string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"Azerbaijandarra"</string>
<string name="keyboard_layout_polish" msgid="1121588624094925325">"Poloniarra"</string>
<string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorrusiera"</string>
- <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongoliera"</string>
+ <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongoliarra"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiera"</string>
</resources>
diff --git a/packages/SettingsLib/AdaptiveIcon/src/com/android/settingslib/widget/AdaptiveIcon.java b/packages/SettingsLib/AdaptiveIcon/src/com/android/settingslib/widget/AdaptiveIcon.java
index fc93650..723caf2 100644
--- a/packages/SettingsLib/AdaptiveIcon/src/com/android/settingslib/widget/AdaptiveIcon.java
+++ b/packages/SettingsLib/AdaptiveIcon/src/com/android/settingslib/widget/AdaptiveIcon.java
@@ -45,12 +45,15 @@
private AdaptiveConstantState mAdaptiveConstantState;
public AdaptiveIcon(Context context, Drawable foreground) {
+ this(context, foreground, R.dimen.dashboard_tile_foreground_image_inset);
+ }
+
+ public AdaptiveIcon(Context context, Drawable foreground, int insetResId) {
super(new Drawable[]{
new AdaptiveIconShapeDrawable(context.getResources()),
foreground
});
- final int insetPx = context.getResources()
- .getDimensionPixelSize(R.dimen.dashboard_tile_foreground_image_inset);
+ final int insetPx = context.getResources().getDimensionPixelSize(insetResId);
setLayerInset(1 /* index */, insetPx, insetPx, insetPx, insetPx);
mAdaptiveConstantState = new AdaptiveConstantState(context, foreground);
}
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
index b1553e9..7e3ce9d 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
@@ -35,6 +35,7 @@
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
+ android:paddingRight="54dp"
android:layout_gravity="center_vertical"
android:maxLines="2"
android:ellipsize="end"
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index defbf54..6f4f72a 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF (diensverskaffer-wi-fi)"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiele data is af"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nie gestel om data te gebruik nie"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Geen foon nie."</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 1326c51..3f5df34 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"የተንቀሳቃሽ ስልክ ውሂብ ጠፍቷል"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ውሂብን ለመጠቀም አልተቀናበረም"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ምንም ስልክ የለም።"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 702a419..0351d94 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -580,8 +580,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"شبكة الجيل الرابع أو أحدث"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"تم إيقاف بيانات الجوال"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"لم يتم الضبط على استخدام البيانات"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ليست هناك إشارة بالهاتف."</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index c5dbda9..0f7db8f 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"এলটিই"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"এলটিই+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"ম’বাইল ডেটা অফ অৱস্থাত আছে"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ডেটা ব্যৱহাৰ কৰিবলৈ ছেট কৰা নাই"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ফ\'নত ছিগনেল নাই৷"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index b18b1c4..0855d17e 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobil data deaktivdir"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Data istifadə etmək üçün ayarlanmayıb"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Telefon yoxdur."</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index d92f171..3386fe86 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -577,8 +577,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"WiFi mobilnog operatera"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilni podaci su isključeni"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nije podešeno za korišćenje podataka"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nema telefona."</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 57d9a55..6ac2172 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -578,8 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мабільная перадача даных выключана"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Не зададзена для выкарыстання даных"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Няма тэлефона."</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 4d4b392..19ed5bd 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилните данни са изключени"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Не е зададено да използва данни"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Няма телефон."</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 88fb83f..b0e9342 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"মোবাইল ডেটা বন্ধ করা হয়েছে"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ডেটা ব্যবহার করার জন্য সেট করা নেই"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"কোনো ফোনের সংকেত নেই৷"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 6925d04..9377624 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -577,8 +577,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Prijenos podataka na mobilnoj mreži je isključen"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nije postavljeno za korištenje podataka"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nema telefonskog signala."</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index dd3a811..a2a7770 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"S\'han desactivat les dades mòbils"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"No s\'ha definit per utilitzar dades"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"No hi ha senyal de telèfon."</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 6b8914d..4db4d5c 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -578,8 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Wi-Fi operátora"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilní data jsou vypnuta"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nenastaveno k využití dat"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Žádná telefonní síť."</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index c8b4e2b..b76afa5c 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobildata er deaktiveret"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Ikke indstillet til at anvende data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ingen telefon."</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index eb87a58..c608a62 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Τα δεδομένα κινητής τηλεφωνίας απενεργοποιήθηκαν"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Δεν ρυθμίστηκε ώστε να χρησιμοποιεί δεδομένα"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Δεν υπάρχει τηλέφωνο."</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index ad16c89..e67c3d1 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 4515908..b0830fc 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index ad16c89..e67c3d1 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index ad16c89..e67c3d1 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index f8903bb..4c0af75 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 26cffd2..9ae7781 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Datos móviles desactivados"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"No se configuró para usar datos"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Sin teléfono"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 5a58a20..203726a 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Datos desactiv."</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"No está establecido para usar los datos"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Sin teléfono"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 2d5d0b5..379ed6c 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiilne andmeside on väljas"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Ei ole andmeside kasutamiseks seadistatud"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Telefonisignaal puudub"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index c7b376a..2582854 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Desaktibatuta dago datu-konexioa"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Ez dago ezarrita datuak erabiltzeko"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ez dago telefono-zenbakirik."</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index ae99c01..cb598e5 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"داده تلفن همراه خاموش است"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"برای استفاده از داده تنظیم نشده است"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"بدون تلفن."</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 6dd3a21d..31dfe18 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Operaattorin Wi-Fi"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiilidata poistettu käytöstä"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Ei käytä dataa"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ei puhelinverkkoyhteyttä."</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 58ea795..ed536b4 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Désactivées"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Non configuré pour l\'utilisation des données cellulaires"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Aucun signal"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index cf8ec40..46bd71b 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"મોબાઇલ ડેટા બંધ છે"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ડેટાનો ઉપયોગ કરવાનું સેટ કર્યું નથી"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"કોઈ ફોન નથી."</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index ddcfc58..9cae311 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"एलटीई"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"मोबाइल डेटा बंद है"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"डेटा इस्तेमाल करने के लिए सेट नहीं किया गया है"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"कोई फ़ोन नहीं."</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index f7d2bec..83bb2d1 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -577,8 +577,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G i više"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilni su podaci isključeni"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nije postavljeno za upotrebu podataka"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nema telefona."</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 883e2a4..9f184c7 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Szolgáltatói Wi-Fi"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiladatok kikapcsolva"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nincs beállítva az adathasználat"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nincs telefon."</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index de9e4dd..cd6cbf3 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Բջջային ինտերնետն անջատված է"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Բջջային ինտերնետն ըստ կանխադրման չի օգտագործվում"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Հեռախոս չկա:"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index e4f56e6..3b80918 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Kuota nonaktif"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Tidak disetel untuk menggunakan data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Tidak dapat melakukan panggilan."</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index d5d8289..ce9e665 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Wi-Fi símafyrirtækis (CWF)"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Slökkt á farsímagögnum"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Ekki stillt á að nota gögn"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ekkert símasamband."</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 55c03b6..93b24a0 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Wi-Fi operatore"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Dati mobili disattivati"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Non impostato per l\'utilizzo dei dati"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nessun telefono."</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 6bbfa16..ab67809 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -578,8 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"+4G"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"+LTE"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Wi-Fi של הספק"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"חבילת הגלישה כבויה"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"לא מוגדרת לשימוש בנתונים"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"אין טלפון."</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index d97926b..0813305 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"მობილური ინტერნეტი გამორთულია"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"არ არის დაყენებული მონაცემების გამოყენებისთვის"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ტელეფონი არ არის."</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 6cceef6..16ee9c0 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -359,7 +359,7 @@
<string name="enable_gpu_debug_layers" msgid="4986675516188740397">"GPU жөндеу қабаттарын қосу"</string>
<string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"GPU жөндеу қабаттарының жүктелуіне рұқсат ету"</string>
<string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Жеткізушілерді журналға тіркеу"</string>
- <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Қате туралы есепте қызмет көрсетушінің құрылғыға қатысты қосымша ақпаратын қамту. Мұнда жеке ақпарат көрсетілуі, батарея шығыны артуы және/немесе қосымша жад пайдаланылуы мүмкін."</string>
+ <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Қате туралы есепте жеткізушінің құрылғыға қатысты қосымша ақпараты қамтылады. Мұнда жеке ақпарат көрсетілуі, батарея шығыны артуы және/немесе қосымша жад пайдаланылуы мүмкін."</string>
<string name="window_animation_scale_title" msgid="5236381298376812508">"Терезе анимациясының өлшемі"</string>
<string name="transition_animation_scale_title" msgid="1278477690695439337">"Ауысу анимациясының өлшемі"</string>
<string name="animator_duration_scale_title" msgid="7082913931326085176">"Аниматор ұзақтығы"</string>
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобильдік деректер өшірулі"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Деректерді пайдалануға реттелмеген."</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Телефон жоқ."</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index f069d15..5b47381 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"ទិន្នន័យទូរសព្ទចល័តបានបិទ"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"មិនបានកំណត់ឱ្យប្រើទិន្នន័យទេ"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"គ្មានទូរស័ព្ទ។"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 3841e3b..fd63dcb 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"ಮೊಬೈಲ್ ಡೇಟಾ ಆಫ್"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ಡೇಟಾ ಬಳಸಲು ಹೊಂದಿಸಲಾಗಿಲ್ಲ"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ಯಾವುದೇ ಫೋನ್ ಇಲ್ಲ."</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 75b731b..a9c3f31 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G 이상"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"모바일 데이터 꺼짐"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"데이터를 사용하도록 설정되지 않음"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"휴대전화의 신호가 없습니다."</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 1159376..bc3656f 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилдик Интернет өчүрүлгөн"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Дайындарды колдонуу үчүн жөндөлгөн эмес"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Телефон сигналы жок."</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 3e3f317..8408c93 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"ປິດອິນເຕີເນັດມືຖືແລ້ວ"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ບໍ່ໄດ້ຕັ້ງໃຫ້ໃຊ້ອິນເຕີເນັດ"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ບໍ່ມີໂທລະສັບ."</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 279980b..1dcfcf7 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -578,8 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiliojo ryšio duomenys išjungti"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nenustatyta naudoti duomenis"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nėra telefono."</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index f36adc6..3d9b78a 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -577,8 +577,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilie dati izslēgti"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nav iestatīts datu lietošanai"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nav tālruņa."</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 31e5b7c..0674f11 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Wi-Fi на операторот"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилниот интернет е исклучен"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Не е поставен да користи интернет"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Нема сигнал."</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 485a228..1455669 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"മൊബൈൽ ഡാറ്റ ഓഫാണ്"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ഡാറ്റ ഉപയോഗിക്കുന്നതിന് സജ്ജീകരിച്ചിട്ടില്ല"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ഫോൺ സിഗ്നൽ ഒന്നുമില്ല."</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 6ce0a7d..f13cb0b 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобайл дата унтраалттай байна"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Дата ашиглахаар тохируулаагүй"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Утас байхгүй."</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index c1a246f..f5be76e 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -168,7 +168,7 @@
<string name="tts_play_example_summary" msgid="634044730710636383">"उच्चार संश्लेषणाचे एक छोटेसे प्रात्यक्षिक प्ले करा"</string>
<string name="tts_install_data_title" msgid="1829942496472751703">"व्हॉइस डेटा इंस्टॉल करा"</string>
<string name="tts_install_data_summary" msgid="3608874324992243851">"उच्चार संश्लेषणासाठी आवश्यक आवाज डेटा इंस्टॉल करा"</string>
- <string name="tts_engine_security_warning" msgid="3372432853837988146">"हे उच्चार संश्लेषण इंजिन पासवर्ड आणि क्रेडिट कार्ड नंबर यासारख्या वैयक्तिक मजकुरासह, बोलला जाणारा सर्व मजकूर संकलित करण्यात सक्षम होऊ शकते. हे <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> इंजिनवरून येते. या उच्चार संश्लेषण इंजिनचा वापर सक्षम करायचा?"</string>
+ <string name="tts_engine_security_warning" msgid="3372432853837988146">"हे उच्चार संश्लेषण इंजीन पासवर्ड आणि क्रेडिट कार्ड नंबर यासारख्या वैयक्तिक मजकुरासह, बोलला जाणारा सर्व मजकूर संकलित करण्यात सक्षम होऊ शकते. हे <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> इंजीनवरून येते. या उच्चार संश्लेषण इंजीनचा वापर सक्षम करायचा?"</string>
<string name="tts_engine_network_required" msgid="8722087649733906851">"या भाषेस टेक्स्ट टू स्पीचसाठी एका नेटवर्क कनेक्शनची आवश्यकता आहे."</string>
<string name="tts_default_sample_string" msgid="6388016028292967973">"हे उच्चार संश्लेषणाचे एक उदाहरण आहे"</string>
<string name="tts_status_title" msgid="8190784181389278640">"डीफॉल्ट भाषा स्थिती"</string>
@@ -177,8 +177,8 @@
<string name="tts_status_not_supported" msgid="2702997696245523743">"<xliff:g id="LOCALE">%1$s</xliff:g> समर्थित नाही"</string>
<string name="tts_status_checking" msgid="8026559918948285013">"तपासत आहे..."</string>
<string name="tts_engine_settings_title" msgid="7849477533103566291">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> साठी सेटिंग्ज"</string>
- <string name="tts_engine_settings_button" msgid="477155276199968948">"इंजिन सेटिंग्ज लाँच करा"</string>
- <string name="tts_engine_preference_section_title" msgid="3861562305498624904">"प्राधान्य इंजिन"</string>
+ <string name="tts_engine_settings_button" msgid="477155276199968948">"इंजीन सेटिंग्ज लाँच करा"</string>
+ <string name="tts_engine_preference_section_title" msgid="3861562305498624904">"प्राधान्य इंजीन"</string>
<string name="tts_general_section_title" msgid="8919671529502364567">"सामान्य"</string>
<string name="tts_reset_speech_pitch_title" msgid="7149398585468413246">"उच्चार पिच रीसेट करा"</string>
<string name="tts_reset_speech_pitch_summary" msgid="6822904157021406449">"डीफॉल्टवर मजकूर ज्या पिचवर बोलला जातो तो रीसेट करा."</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 1ba076d..9527793 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Data mudah alih dimatikan"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Tidak ditetapkan untuk menggunakan data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Tiada telefon."</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 61374e8..1dcb3cf 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"မိုဘိုင်းဒေတာ ပိတ်ထားသည်"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ဒေတာအသုံးပြုရန် သတ်မှတ်မထားပါ"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ဖုန်းလိုင်းမရှိပါ။"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index fe6204b..13f69c1 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobildata er slått av"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Ikke konfigurert til å bruke data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ingen telefon."</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index c0e9fe5..5795cc9 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"मोबाइल डेटा निष्क्रिय छ"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"डेटा प्रयोग गर्ने गरी सेट गरिएन"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"फोन छैन्।"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index b7ea8a0..718ce5d 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiele data uit"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Gebruik van gegevens is niet ingesteld"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Geen telefoonsignaal."</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index ac1ccb6..41e84f9 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"ମୋବାଇଲ୍ ଡାଟା ବନ୍ଦ ଅଛି"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ବ୍ୟବହୃତ ଡାଟା ପାଇଁ ସେଟ୍ ହୋଇନାହିଁ"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"କୌଣସି ଫୋନ୍ ନାହିଁ।"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index fc26f59..f24b52b 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Dados móveis desativados"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Sem configuração para uso de dados"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Sem telefone."</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 7ff1ba4..42ad0fe 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"WFO"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Dados móveis desativados"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Não definido para utilizar dados"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Sem telefone."</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index fc26f59..f24b52b 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Dados móveis desativados"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Sem configuração para uso de dados"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Sem telefone."</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index be0193c..0743fe9 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -577,8 +577,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Rețeaua Wi‑Fi a operatorului"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Date mobile dezactivate"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nu este setat pentru a folosi datele"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nu există semnal pentru telefon."</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index fad3591..d19438a 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -578,8 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобильный Интернет отключен"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Мобильный Интернет по умолчанию не используется."</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Сигнал телефонной сети отсутствует."</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 69a918a..15fe8c8 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"ජංගම දත්ත ක්රියාවිරහිතයි"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"දත්ත භාවිත කිරීමට සකසා නැත"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"දුරකථනයක් නැත."</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index f98237c2..ee53b7c 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -578,8 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Wi‑Fi operátora"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilné dáta sú vypnuté"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nie je nastavené na používanie dát"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Žiadna telefónna sieť."</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 710fbdb..66d33a7 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -578,8 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Omrežje Wi‑Fi operaterja"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Prenos podatkov v mobilnem omrežju je izklopljen"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Ni nastavljeno za uporabo prenosa podatkov"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ni telefona."</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index b4e5db9..d5c0231 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Të dhënat celulare janë joaktive"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nuk është caktuar të përdorë të dhënat"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nuk ka telefon."</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index d134f8a..ce74b84 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -577,8 +577,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"WiFi мобилног оператера"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилни подаци су искључени"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Није подешено за коришћење података"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Нема телефона."</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index e90a915..eacb7a8 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Operatörens Wi-Fi"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobildata har inaktiverats"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Inte inställd på mobildata"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ingen telefon."</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 653beef..e7045a7 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Umezima data ya mtandao wa simu"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Haijawekewa mipangilio ya kutumia data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Hakuna simu"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index b75818a..06c7ccb 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"மொபைல் டேட்டா ஆஃப் செய்யப்பட்டது"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"தரவை உபயோகிக்க அமைக்கப்படவில்லை"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"சிக்னல் இல்லை."</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index a010c10..6316452 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"เน็ตมือถือปิดอยู่"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ไม่ได้ตั้งค่าให้ใช้อินเทอร์เน็ตมือถือ"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ไม่มีสัญญาณโทรศัพท์"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 4485384..0aabbe5 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Naka-off ang mobile data"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Hindi nakatakdang gumamit ng data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Walang telepono."</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 081a115..44c8f13 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobil veri kapalı"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Veri kullanmak üzere ayarlanmadı"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Telefon sinyali yok."</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index b4e533d..7851111 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -578,8 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Мережа Wi-Fi оператора"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобільне передавання даних вимкнено"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Не вибрано для використання даних"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Немає сигналу телефону."</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 4787aeb..c2a96c6 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobil internet yoqilmagan"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Maʼlumotlardan foydalanish uchun sozlanmagan"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Signal yo‘q."</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index df975b3..2596424 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Đã tắt dữ liệu di động"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Chưa được đặt để sử dụng dữ liệu"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Không có điện thoại nào."</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index e1b6047..60afd6d 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"移动数据网络已关闭"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"未设置为使用移动数据"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"没有手机信号。"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index e095afd..925f738 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"流動網絡供應商 Wi-Fi"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"流動數據已關閉"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"未設定至可使用資料"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"沒有電話訊號。"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index a1dc7f1..e40d351 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"行動數據已關閉"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"並未設為使用行動數據"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"沒有電話訊號。"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index a04f47c..c304c14 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -576,8 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"I-LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"I-LTE+"</string>
- <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
- <skip />
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"I-CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Idatha yeselula ivaliwe"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Akusethiwe ukuze kusetshenziswe idatha"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ayikho ifoni."</string>
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index c63cf06..2b5e9cd 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -291,7 +291,7 @@
<item>256K</item>
<item>1M</item>
<item>4M</item>
- <item>16M</item>
+ <item>8M</item>
</string-array>
<!-- Titles for logd limit size lowram selection preference. [CHAR LIMIT=14] -->
@@ -309,7 +309,7 @@
<item>262144</item>
<item>1048576</item>
<item>4194304</item>
- <item>16777216</item>
+ <item>8388608</item>
</string-array>
<!-- Summaries for logd limit size selection preference. [CHAR LIMIT=50]-->
@@ -319,7 +319,7 @@
<item>256K per log buffer</item>
<item>1M per log buffer</item>
<item>4M per log buffer</item>
- <item>16M per log buffer</item>
+ <item>8M per log buffer</item>
</string-array>
<!-- Values for logpersist state selection preference. -->
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 53e67e1..fbc71f1 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -264,7 +264,6 @@
VALIDATORS.put(Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.EMERGENCY_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.EMERGENCY_GESTURE_SOUND_ENABLED, BOOLEAN_VALIDATOR);
- VALIDATORS.put(Secure.EMERGENCY_GESTURE_CALL_NUMBER, NONE_NEGATIVE_LONG_VALIDATOR);
VALIDATORS.put(Secure.ADAPTIVE_CONNECTIVITY_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(
Secure.ASSIST_HANDLES_LEARNING_TIME_ELAPSED_MILLIS, NONE_NEGATIVE_LONG_VALIDATOR);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index e22f264..07a5a44 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -742,7 +742,6 @@
Settings.Secure.SKIP_GESTURE,
Settings.Secure.SILENCE_GESTURE,
Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
- Settings.Secure.EMERGENCY_GESTURE_CALL_NUMBER,
Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
Settings.Secure.FACE_UNLOCK_RE_ENROLL,
Settings.Secure.TAP_GESTURE,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index a1bb66e..41cc835 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -157,6 +157,7 @@
<uses-permission android:name="android.permission.MANAGE_CONTENT_SUGGESTIONS" />
<uses-permission android:name="android.permission.MANAGE_APP_PREDICTIONS" />
<uses-permission android:name="android.permission.MANAGE_SEARCH_UI" />
+ <uses-permission android:name="android.permission.MANAGE_SMARTSPACE" />
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.SET_TIME" />
@@ -383,6 +384,9 @@
<!-- Permission required for CTS tests to enable/disable rate limiting toasts. -->
<uses-permission android:name="android.permission.MANAGE_TOAST_RATE_LIMITING" />
+ <!-- Permission required for CTS to test sensor privacy behavior -->
+ <uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SimAppDialog/res/values-mn/strings.xml b/packages/SimAppDialog/res/values-mn/strings.xml
index f21b80b..51298bb 100644
--- a/packages/SimAppDialog/res/values-mn/strings.xml
+++ b/packages/SimAppDialog/res/values-mn/strings.xml
@@ -19,8 +19,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="8898068901680117589">"Sim аппын харилцах цонх"</string>
<string name="install_carrier_app_title" msgid="334729104862562585">"Мобайл үйлчилгээг идэвхжүүлэх"</string>
- <string name="install_carrier_app_description" msgid="4014303558674923797">"Та шинэ СИМ-ээ зөв ажиллуулахын тулд <xliff:g id="ID_1">%1$s</xliff:g> аппыг суулгах хэрэгтэй болно"</string>
- <string name="install_carrier_app_description_default" msgid="7356830245205847840">"Та шинэ СИМ-ээ зөв ажиллуулахын тулд оператор компанийхаа аппыг суулгах хэрэгтэй болно"</string>
+ <string name="install_carrier_app_description" msgid="4014303558674923797">"Та шинэ SIM-ээ зөв ажиллуулахын тулд <xliff:g id="ID_1">%1$s</xliff:g> аппыг суулгах хэрэгтэй болно"</string>
+ <string name="install_carrier_app_description_default" msgid="7356830245205847840">"Та шинэ SIM-ээ зөв ажиллуулахын тулд оператор компанийхаа аппыг суулгах хэрэгтэй болно"</string>
<string name="install_carrier_app_defer_action" msgid="2558576736886876209">"Одоо биш"</string>
<string name="install_carrier_app_download_action" msgid="7859229305958538064">"Апп татах"</string>
</resources>
diff --git a/packages/SystemUI/res/drawable/ic_camera_blocked.xml b/packages/SystemUI/res/drawable/ic_camera_blocked.xml
new file mode 100644
index 0000000..0161bcb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_camera_blocked.xml
@@ -0,0 +1,29 @@
+<!--
+ ~ 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.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="m18,12c-2.75,0 -5,2.25 -5,5 0,2.75 2.25,5 5,5 2.75,0 5,-2.25 5,-5 0,-2.75 -2.1667,-5 -5,-5zM15.5,17.8333h5v-1.6666h-5z"
+ android:fillColor="#30302a"
+ android:fillType="evenOdd"/>
+ <path
+ android:pathData="m16.4,5.5004h-2.536l-1.464,-1.6H7.6l-1.464,1.6H3.6c-0.88,0 -1.6,0.72 -1.6,1.6v9.6c0,0.88 0.72,1.6 1.6,1.6h8.5413C12.0488,17.8817 12,17.4465 12,17c0,-0.1005 0.0025,-0.2004 0.0073,-0.2996H3.6V7.1004H16.4V11.2157C16.9094,11.0751 17.4459,11 18,11V7.1004c0,-0.88 -0.72,-1.6 -1.6,-1.6zM6.8,11.9004c0,-1.768 1.432,-3.2 3.2,-3.2 1.768,0 3.2,1.432 3.2,3.2 0,1.768 -1.432,3.2 -3.2,3.2 -1.768,0 -3.2,-1.432 -3.2,-3.2z"
+ android:fillColor="#30302a"
+ android:fillType="evenOdd"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_mic_blocked.xml b/packages/SystemUI/res/drawable/ic_mic_blocked.xml
new file mode 100644
index 0000000..0ce7a58
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_mic_blocked.xml
@@ -0,0 +1,29 @@
+<!--
+ ~ 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.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="m17,12c-2.75,0 -5,2.25 -5,5 0,2.75 2.25,5 5,5 2.75,0 5,-2.25 5,-5 0,-2.75 -2.1667,-5 -5,-5zM14.5,17.8333h5v-1.6666h-5z"
+ android:fillColor="#30302a"
+ android:fillType="evenOdd"/>
+ <path
+ android:pathData="m12,12c0,1.66 -1.34,3 -3,3C7.34,15 6,13.66 6,12L6,6C6,4.34 7.34,3 9,3c1.66,0 3,1.34 3,3zM9,5C8.45,5 8,5.45 8,6v6c0,0.55 0.45,1 1,1 0.55,0 1,-0.45 1,-1L10,6C10,5.45 9.55,5 9,5ZM11.0147,16.577C10.3983,16.849 9.7167,17 9,17 6.24,17 4,14.76 4,12L2,12c0,3.53 2.61,6.43 6,6.92L8,22h2v-3.08c0.4212,-0.0609 0.8303,-0.1589 1.2238,-0.2908C11.078,18.1111 11,17.5647 11,17c0,-0.1422 0.0049,-0.2832 0.0147,-0.423z"
+ android:fillColor="#30302a"
+ android:fillType="evenOdd"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_no_calling_sms.xml b/packages/SystemUI/res/drawable/ic_qs_no_calling_sms.xml
new file mode 100644
index 0000000..3d6ca7a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_no_calling_sms.xml
@@ -0,0 +1,28 @@
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10c0.34,0 0.68,-0.02 1.01,-0.05V20h-1v-0.04c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96H13v-2H9.66c-0.09,-0.66 -0.16,-1.32 -0.16,-2s0.07,-1.35 0.16,-2H21.8C20.87,5.44 16.83,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56C16.43,5.07 17.96,6.35 18.92,8zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82C10.52,6.57 11.17,5.24 12,4.04zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2s0.06,1.34 0.14,2H4.26zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56C7.57,18.93 6.04,17.66 5.08,16zM8.03,8H5.08c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8z"
+ android:fillAlpha="0.3"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M22,19.3v-0.9l-3.37,-2.25v-2.47C18.63,13.3 18.35,13 18,13s-0.63,0.3 -0.63,0.68v2.47L14,18.4v0.9l3.37,-1.12v2.48l-0.84,0.68V22L18,21.55L19.47,22v-0.67l-0.84,-0.68v-2.48L22,19.3z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 0beb286..317e0e8 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nuwe gebruiker"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nie gekoppel nie"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Geen netwerk nie"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi af"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index f56e84a..b7b24db 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"አዲስ ተጠቃሚ"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"በይነመረብ"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"አልተገናኘም"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ምንም አውታረ መረብ የለም"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi ጠፍቷል"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index aaaf778..ca823ed 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -358,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"مستخدم جديد"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"الإنترنت"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ليست متصلة"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"لا تتوفر شبكة"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"إيقاف Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 7e3e3cb..8e6fd51 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -353,7 +353,12 @@
<string name="quick_settings_user_title" msgid="8673045967216204537">"ব্যৱহাৰকাৰী"</string>
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"নতুন ব্যৱহাৰকাৰী"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"ৱাই-ফাই"</string>
- <!-- no translation found for quick_settings_internet_label (6603068555872455463) -->
+ <string name="quick_settings_internet_label" msgid="6603068555872455463">"ইণ্টাৰনেট"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
<skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"সংযোগ হৈ থকা নাই"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"নেটৱৰ্ক নাই"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 6c22cc3..d9a2ae1 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Yeni istifadəçi"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"İnternet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Bağlantı yoxdur"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Şəbəkə yoxdur"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi sönülüdür"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 2f3d6d2..ef3a1cf 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -355,6 +355,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Novi korisnik"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"WiFi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Veza nije uspostavljena"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nema mreže"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"WiFi je isključen"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 925e86a..a1804d1 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -356,6 +356,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Новы карыстальнік"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Інтэрнэт"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Няма падключэння"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Няма сеткi"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi адключаны"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 6a683c7..6b59b24 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Нов потребител"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Интернет"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Няма връзка"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Няма мрежа"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi е изключен"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 953ec00..a6344d0 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"নতুন ব্যবহারকারী"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"ওয়াই-ফাই"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"ইন্টারনেট"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"সংযুক্ত নয়"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"কোনো নেটওয়ার্ক নেই"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"ওয়াই-ফাই বন্ধ"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 6bf1852..0dc97fa 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -355,6 +355,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Novi korisnik"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"WiFi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nije povezano"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nema mreže"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"WiFi je isključen"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 71105cc..bd5815a6 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Usuari nou"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Desconnectat"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"No hi ha cap xarxa"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi desconnectada"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 65e6767..41a33ef 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -356,6 +356,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nový uživatel"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nepřipojeno"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Žádná síť"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi vypnuta"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index e50aa57..3d8b027 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Ny bruger"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Ikke forbundet"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Intet netværk"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi slået fra"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 3cdebf9..a0e535f 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Neuer Nutzer"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"WLAN"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nicht verbunden"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Kein Netz"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"WLAN aus"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index c6ae7f4..13dafa0 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Νέος χρήστης"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Διαδίκτυο"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Μη συνδεδεμένο"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Κανένα δίκτυο"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi ανενεργό"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index ea25ec6..dcee89d 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"New user"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Not Connected"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"No Network"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Off"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index a373a5c..3217d1c 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"New user"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Not Connected"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"No Network"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Off"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index ea25ec6..dcee89d 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"New user"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Not Connected"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"No Network"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Off"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index ea25ec6..dcee89d 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"New user"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Not Connected"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"No Network"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Off"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 101d112..00fa584 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"New user"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Not Connected"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"No Network"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Off"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 1fc1609..a552c76 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Usuario nuevo"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Sin conexión"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Sin red"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi desactivada"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index dd36a64..4277c63 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nuevo usuario"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"No conectado"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"No hay red."</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi desactivado"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index fb27be9..6429931 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Uus kasutaja"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"WiFi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Ühendus puudub"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Võrku pole"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"WiFi-ühendus on väljas"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index d8b21c6..664ae98 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Erabiltzaile berria"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wifia"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Konektatu gabe"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ez dago sarerik"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi konexioa desaktibatuta"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index df306f8..578fe88 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"کاربر جدید"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"اینترنت"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"متصل نیست"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"شبکهای موجود نیست"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi خاموش است"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4e0af37..d73b2eb 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Uusi käyttäjä"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Ei yhteyttä"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ei verkkoa"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi-yhteys pois käytöstä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 8c944a4..df0e36c 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nouvel utilisateur"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Non connecté"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Aucun réseau"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi désactivé"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7ad239d..64a2328 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nouvel utilisateur"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Non connecté"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Aucun réseau"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi désactivé"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 145b3c0..75db845 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Novo usuario"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wifi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Non conectada"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Non hai rede"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wifi desactivada"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index ea7af17..c0d2557 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"નવો વપરાશકર્તા"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"વાઇ-ફાઇ"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"ઇન્ટરનેટ"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"કનેક્ટ થયેલ નથી"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"કોઈ નેટવર્ક નથી"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"વાઇ-ફાઇ બંધ"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index a8bed5b..0bfa5ae 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -356,6 +356,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"नया उपयोगकर्ता"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"वाई-फ़ाई"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"इंटरनेट"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"कनेक्ट नहीं है"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"कोई नेटवर्क नहीं"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"वाई-फ़ाई बंद"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 4ffa5b2..33d0534 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -355,6 +355,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Novi korisnik"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nije povezano"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nema mreže"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi isključen"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index cff5b0d..22b8fde 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Új felhasználó"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nincs kapcsolat"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nincs hálózat"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi kikapcsolva"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 91ffe73..5e51c62 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Նոր օգտատեր"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Ինտերնետ"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Միացված չէ"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ցանց չկա"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi-ը անջատված է"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index f9e7397..9a217ce 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Pengguna baru"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Tidak Terhubung"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Tidak Ada Jaringan"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Mati"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index db5dac43..3f8e8fb 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nýr notandi"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Engin tenging"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ekkert net"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Slökkt á Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 86e65bb..72cc5aa 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nuovo utente"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Non connessa"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nessuna rete"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi disattivato"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 8548dae..d8c148a 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -356,6 +356,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"משתמש חדש"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"אינטרנט"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"אין חיבור"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"אין רשת"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi כבוי"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 6cd5608..40a9323 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"新しいユーザー"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"インターネット"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"接続されていません"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ネットワークなし"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi OFF"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 52d9f0e..6ab5510 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"ახალი მომხმარებელი"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"ინტერნეტი"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"არ არის დაკავშირებული."</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ქსელი არ არის"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi გამორთულია"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index fcf8743..bda2f1a 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Жаңа пайдаланушы"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Интернет"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Жалғанбаған"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Желі жоқ"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi өшірулі"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index e92bf9b..275a73a 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"អ្នកប្រើថ្មី"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"អ៊ីនធឺណិត"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"មិនបានតភ្ជាប់"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"គ្មានបណ្ដាញ"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"វ៉ាយហ្វាយបានបិទ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index d7a0adc..778ccca 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"ಹೊಸ ಬಳಕೆದಾರರು"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"ವೈ-ಫೈ"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"ಇಂಟರ್ನೆಟ್"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ಸಂಪರ್ಕಗೊಂಡಿಲ್ಲ"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ನೆಟ್ವರ್ಕ್ ಇಲ್ಲ"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"ವೈ-ಫೈ ಆಫ್"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 54bcfb9..e602ede 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"신규 사용자"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"인터넷"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"연결되어 있지 않음"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"네트워크가 연결되지 않음"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi 꺼짐"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index d513380..0a2e8ae 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -356,6 +356,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Жаңы колдонуучу"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Интернет"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Байланышкан жок"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Желе жок"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi өчүк"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 7e595cd..0f320a5 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"ຜູ່ໃຊ້ໃໝ່"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"ອິນເຕີເນັດ"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ບໍ່ໄດ້ເຊື່ອມຕໍ່"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ບໍ່ມີເຄືອຂ່າຍ"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi ປິດ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index e0c27a9..29f615e 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -356,6 +356,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Naujas naudotojas"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internetas"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Neprisijungta"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Tinklo nėra"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"„Wi-Fi“ išjungta"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index ff36f51..f209ba8 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -355,6 +355,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Jauns lietotājs"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internets"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nav izveidots savienojums"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nav tīkla"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi ir izslēgts"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 203d8b9..001e6a0 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Нов корисник"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Интернет"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Не е поврзано"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Нема мрежа"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi е исклучено"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 77925ae..e2ca3bb 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"പുതിയ ഉപയോക്താവ്"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"വൈഫൈ"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"ഇന്റർനെറ്റ്"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"കണക്റ്റ് ചെയ്തിട്ടില്ല"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"നെറ്റ്വർക്ക് ഒന്നുമില്ല"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"വൈഫൈ ഓഫുചെയ്യുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index c772294..0b1a1ff 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Шинэ хэрэглэгч"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Интернэт"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Холбогдоогүй"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Сүлжээгүй"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi унтарсан"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 965b895..9ed6bb3 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -353,7 +353,12 @@
<string name="quick_settings_user_title" msgid="8673045967216204537">"वापरकर्ता"</string>
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"नवीन वापरकर्ता"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"वाय-फाय"</string>
- <!-- no translation found for quick_settings_internet_label (6603068555872455463) -->
+ <string name="quick_settings_internet_label" msgid="6603068555872455463">"इंटरनेट"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
<skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"कनेक्ट केले नाही"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"नेटवर्क नाही"</string>
@@ -456,11 +461,9 @@
<string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"प्रोफाईल दर्शवा"</string>
<string name="user_add_user" msgid="4336657383006913022">"वापरकर्ता जोडा"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"नवीन वापरकर्ता"</string>
- <!-- no translation found for guest_exit_guest_dialog_title (2034481024623462357) -->
- <skip />
+ <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"अतिथी सत्र संपायचे का?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"या सत्रातील सर्व अॅप्स आणि डेटा हटवला जाईल."</string>
- <!-- no translation found for guest_exit_guest_dialog_remove (8533184512885775423) -->
- <skip />
+ <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"सत्र संपवा"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"अतिथी, तुमचे पुन्हा स्वागत आहे!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"तुम्ही तुमचे सत्र सुरू ठेवू इच्छिता?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"येथून सुरू करा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index d3e3601..81c15b0 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Pengguna baharu"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Tidak Disambungkan"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Tiada Rangkaian"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Dimatikan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 0c1f9cb..6bccb33 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"အသုံးပြုသူ အသစ်"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"အင်တာနက်"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ချိတ်ဆက်မထားပါ"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ကွန်ရက်မရှိပါ"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"ဝိုင်ဖိုင်ပိတ်ရန်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 565e7fe..90defaa 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Ny bruker"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internett"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Ikke tilkoblet"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ingen nettverk"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi er av"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 9d95cf0..0e86b94 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"नयाँ प्रयोगकर्ता"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"इन्टरनेट"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"जोडिएको छैन"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"नेटवर्क छैन"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi बन्द"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index f598fa3..a216c49 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nieuwe gebruiker"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wifi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Niet verbonden"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Geen netwerk"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wifi uit"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 1e07dd4..ed38d14 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -353,7 +353,12 @@
<string name="quick_settings_user_title" msgid="8673045967216204537">"ୟୁଜର୍"</string>
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"ନୂଆ ଉପଯୋଗକର୍ତ୍ତା"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"ୱାଇ-ଫାଇ"</string>
- <!-- no translation found for quick_settings_internet_label (6603068555872455463) -->
+ <string name="quick_settings_internet_label" msgid="6603068555872455463">"ଇଣ୍ଟରନେଟ୍"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
<skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ସଂଯୁକ୍ତ ହୋଇନାହିଁ"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ନେଟ୍ୱର୍କ ନାହିଁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 7d5bc96..3026a18 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -353,7 +353,12 @@
<string name="quick_settings_user_title" msgid="8673045967216204537">"ਵਰਤੋਂਕਾਰ"</string>
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"ਵਾਈ-ਫਾਈ"</string>
- <!-- no translation found for quick_settings_internet_label (6603068555872455463) -->
+ <string name="quick_settings_internet_label" msgid="6603068555872455463">"ਇੰਟਰਨੈੱਟ"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
<skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ਕੋਈ ਨੈੱਟਵਰਕ ਨਹੀਂ"</string>
@@ -456,11 +461,9 @@
<string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"ਪ੍ਰੋਫਾਈਲ ਦਿਖਾਓ"</string>
<string name="user_add_user" msgid="4336657383006913022">"ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ"</string>
- <!-- no translation found for guest_exit_guest_dialog_title (2034481024623462357) -->
- <skip />
+ <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"ਕੀ ਮਹਿਮਾਨ ਸੈਸ਼ਨ ਸਮਾਪਤ ਕਰਨਾ ਹੈ?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ਇਸ ਸੈਸ਼ਨ ਵਿੱਚ ਸਾਰੀਆਂ ਐਪਾਂ ਅਤੇ ਡਾਟਾ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਏਗਾ।"</string>
- <!-- no translation found for guest_exit_guest_dialog_remove (8533184512885775423) -->
- <skip />
+ <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"ਸੈਸ਼ਨ ਸਮਾਪਤ ਕਰੋ"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ਮਹਿਮਾਨ, ਫਿਰ ਤੁਹਾਡਾ ਸੁਆਗਤ ਹੈ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ਕੀ ਤੁਸੀਂ ਆਪਣਾ ਸੈਸ਼ਨ ਜਾਰੀ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ਸ਼ੁਰੂ ਕਰੋ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 561e70d..12422e9 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -356,6 +356,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nowy użytkownik"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Brak połączenia"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Brak sieci"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi wyłączone"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 7fe53d3..0d65c01 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Novo usuário"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Não conectado"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Sem rede"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi desligado"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index dd154e8..0932a96 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Novo utilizador"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Não Ligado"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Sem Rede"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Desligado"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 7fe53d3..0d65c01 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Novo usuário"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Não conectado"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Sem rede"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi desligado"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 317fc09..e181945 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -355,6 +355,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Utilizator nou"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Neconectată"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nicio rețea"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi deconectat"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index bbb014e..5d08e3a 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -356,6 +356,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Новый пользователь"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Интернет"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Нет соединения"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Нет сети"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi выкл."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index a7a2bb7..7230a06 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"නව පරිශීලකයා"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"අන්තර්ජාලය"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"සම්බන්ධ වී නොමැත"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ජාලයක් නැත"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi අක්රියයි"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 7eb5297..1454884 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -356,6 +356,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nový používateľ"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi‑Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nepripojené"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Žiadna sieť"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Sieť Wi‑Fi je vypnutá"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 6d23f26..2cecff7 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -356,6 +356,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nov uporabnik"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Povezava ni vzpostavljena"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ni omrežja"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi izklopljen"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 7e89b93..3179e99 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Përdorues i ri"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nuk është i lidhur"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nuk ka rrjet"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi është i çaktivizuar"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index af5175c..ea862bc 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -355,6 +355,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Нови корисник"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"WiFi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Интернет"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Веза није успостављена"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Нема мреже"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"WiFi је искључен"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 41bca7c..66685e9 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Ny användare"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Ej ansluten"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Inget nätverk"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi av"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index f122013..1563c76 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Mtumiaji mpya"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Intaneti"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Haijaunganishwa"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Hakuna Mtandao"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Imezimwa"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index c076a03..a54b1a2 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"புதியவர்"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"வைஃபை"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"இணையம்"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"இணைக்கப்படவில்லை"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"நெட்வொர்க் இல்லை"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"வைஃபையை முடக்கு"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index fca5107..01c3d7d1 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"కొత్త వినియోగదారు"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"ఇంటర్నెట్"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"కనెక్ట్ చేయబడలేదు"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"నెట్వర్క్ లేదు"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi ఆఫ్లో ఉంది"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index c909d37..e51c308 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"ผู้ใช้ใหม่"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"อินเทอร์เน็ต"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ไม่ได้เชื่อมต่อ"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ไม่มีเครือข่าย"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"ปิด WiFi"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 2e75fa3..7b8070b 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Bagong user"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Hindi Nakakonekta"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Walang Network"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Naka-off ang Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 98552b1..f9e78c7 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Yeni kullanıcı"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Kablosuz"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"İnternet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Bağlı Değil"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ağ yok"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Kablosuz Kapalı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index b70d36a..72046e1 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -356,6 +356,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Новий користувач"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Інтернет"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Не під’єднано."</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Немає мережі"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi вимкнено"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index bbadf6a..9ccc133 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"نیا صارف"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"انٹرنیٹ"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"مربوط نہیں ہے"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"کوئی نیٹ ورک نہیں ہے"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi آف ہے"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index a20676d..67d801b4 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Yangi foydalanuvchi"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Ulanmagan"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Tarmoq mavjud emas"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi o‘chiq"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 5de7df6a..1d836e8 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Người dùng mới"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Chưa được kết nối"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Không có mạng nào"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Tắt Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7f3f394..fa6a510 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -63,9 +63,9 @@
<string name="usb_debugging_allow" msgid="1722643858015321328">"允许"</string>
<string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"不允许使用 USB 调试功能"</string>
<string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"目前已登录此设备的用户无法开启 USB 调试功能。要使用此功能,请切换为主要用户的帐号。"</string>
- <string name="wifi_debugging_title" msgid="7300007687492186076">"要允许在此网络上进行无线调试吗?"</string>
+ <string name="wifi_debugging_title" msgid="7300007687492186076">"要允许通过此网络上进行无线调试吗?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"网络名称 (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWLAN 地址 (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
- <string name="wifi_debugging_always" msgid="2968383799517975155">"在此网络上始终允许"</string>
+ <string name="wifi_debugging_always" msgid="2968383799517975155">"始终允许通过此网络进行调试"</string>
<string name="wifi_debugging_allow" msgid="4573224609684957886">"允许"</string>
<string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"不允许使用无线调试功能"</string>
<string name="wifi_debugging_secondary_user_message" msgid="4492383073970079751">"目前已登录此设备的用户无法开启无线调试功能。要使用此功能,请切换为主要用户的帐号。"</string>
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"新用户"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"WLAN"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"互联网"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"未连接"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"无网络"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"WLAN:关闭"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 485f1cf..b69d097 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"新使用者"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"互聯網"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"未連線"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"沒有網絡"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi 關閉"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 1edeacd..2fb0b86 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"新使用者"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"網際網路"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"未連線"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"沒有網路"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi 已關閉"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 58baebc..e9e1a75 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -354,6 +354,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Umsebenzisi omusha"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"I-Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"I-inthanethi"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Akuxhunyiwe"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ayikho inethiwekhi"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"I-Wi-Fi icimile"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 101124e..93d2f75 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -107,7 +107,7 @@
<!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
<string name="quick_settings_tiles_stock" translatable="false">
- wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night,screenrecord,reverse,reduce_brightness
+ wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night,screenrecord,reverse,reduce_brightness,cameratoggle,mictoggle
</string>
<!-- The tiles to display in QuickSettings -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 72dd724..ae55d95 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -619,7 +619,7 @@
<dimen name="z_distance_between_notifications">0.5dp</dimen>
<!-- The height of the divider between the individual notifications. -->
- <dimen name="notification_divider_height">4dp</dimen>
+ <dimen name="notification_divider_height">2dp</dimen>
<!-- The corner radius of the shadow behind the notification. -->
<dimen name="notification_shadow_radius">0dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7cdd8b1..ac2e342 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -821,6 +821,10 @@
<string name="quick_settings_location_label">Location</string>
<!-- QuickSettings: Location (Off) [CHAR LIMIT=NONE] -->
<string name="quick_settings_location_off_label">Location Off</string>
+ <!-- QuickSettings: Camera [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_camera_label">Block Camera</string>
+ <!-- QuickSettings: Microphone [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_mic_label">Mute Microphone</string>
<!-- QuickSettings: Media device [CHAR LIMIT=NONE] -->
<string name="quick_settings_media_device_label">Media device</string>
<!-- QuickSettings: RSSI [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 6eec5dc..902de23 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -50,6 +50,10 @@
android:key="bluetooth"
android:title="@string/quick_settings_bluetooth_label" />
+ <com.android.systemui.tuner.StatusBarSwitch
+ android:key="cameratoggle"
+ android:title="@string/quick_settings_camera_label" />
+
<!-- nfc -->
<!-- tty -->
<!-- speakerphone -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index 3644032..937c1df 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -92,6 +92,8 @@
public static final int SYSUI_STATE_ONE_HANDED_ACTIVE = 1 << 16;
// Allow system gesture no matter the system bar(s) is visible or not
public static final int SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY = 1 << 17;
+ // The IME is showing
+ public static final int SYSUI_STATE_IME_SHOWING = 1 << 18;
@Retention(RetentionPolicy.SOURCE)
@IntDef({SYSUI_STATE_SCREEN_PINNING,
@@ -111,7 +113,8 @@
SYSUI_STATE_BUBBLES_EXPANDED,
SYSUI_STATE_GLOBAL_ACTIONS_SHOWING,
SYSUI_STATE_ONE_HANDED_ACTIVE,
- SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY
+ SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY,
+ SYSUI_STATE_IME_SHOWING
})
public @interface SystemUiStateFlags {}
@@ -138,6 +141,7 @@
str.add((flags & SYSUI_STATE_ONE_HANDED_ACTIVE) != 0 ? "one_handed_active" : "");
str.add((flags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0
? "allow_gesture" : "");
+ str.add((flags & SYSUI_STATE_IME_SHOWING) != 0 ? "ime_visible" : "");
return str.toString();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index 302a262..59e81cf 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
@@ -85,8 +85,8 @@
}
private void initColors() {
- mLockScreenColors[0] = Utils.getColorAttr(getContext(),
- android.R.attr.textColorPrimary).getDefaultColor();
+ mLockScreenColors[0] = Utils.getColorAttrDefaultColor(getContext(),
+ com.android.systemui.R.attr.wallpaperTextColor);
mLockScreenColors[1] = mLockScreenColors[0]; // same color
mView.setColors(mDozingColors, mLockScreenColors);
mView.animateDoze(mIsDozing, false);
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index e6ad1cb..13da2b0 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -16,7 +16,7 @@
package com.android.systemui.accessibility;
-import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_GLOBAL_ACTIONS;
+import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_ACCESSIBILITY_ACTIONS;
import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME;
@@ -349,7 +349,7 @@
private void handleTakeScreenshot() {
ScreenshotHelper screenshotHelper = new ScreenshotHelper(mContext);
screenshotHelper.takeScreenshot(WindowManager.TAKE_SCREENSHOT_FULLSCREEN, true, true,
- SCREENSHOT_GLOBAL_ACTIONS, new Handler(Looper.getMainLooper()), null);
+ SCREENSHOT_ACCESSIBILITY_ACTIONS, new Handler(Looper.getMainLooper()), null);
}
private void handleAccessibilityButton() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index dcb6ea3..1cafb4c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -342,8 +342,8 @@
Log.v(TAG, "showUdfpsOverlay | adding window");
mView.setShowReason(reason);
mWindowManager.addView(mView, computeLayoutParams());
- mIsOverlayShowing = true;
mView.setOnTouchListener(mOnTouchListener);
+ mIsOverlayShowing = true;
} catch (RuntimeException e) {
Log.e(TAG, "showUdfpsOverlay | failed to add window", e);
}
@@ -434,19 +434,21 @@
}
private void onFingerDown(int x, int y, float minor, float major) {
- mView.setScrimAlpha(computeScrimOpacity());
- mView.showScrimAndDot();
- try {
- if (mHbmSupported) {
+ if (mHbmSupported) {
+ try {
FileWriter fw = new FileWriter(mHbmPath);
fw.write(mHbmEnableCommand);
fw.close();
+ } catch (IOException e) {
+ mView.hideScrimAndDot();
+ Log.e(TAG, "onFingerDown | failed to enable HBM: " + e.getMessage());
}
- mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major);
- } catch (IOException e) {
- mView.hideScrimAndDot();
- Log.e(TAG, "onFingerDown | failed to enable HBM: " + e.getMessage());
}
+ mView.setScrimAlpha(computeScrimOpacity());
+ mView.setRunAfterShowingScrimAndDot(() -> {
+ mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major);
+ });
+ mView.showScrimAndDot();
}
private void onFingerUp() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
index a42ab58..c2f80d4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
@@ -89,6 +89,10 @@
private boolean mIsHbmSupported;
@Nullable private String mDebugMessage;
+ // Runnable that will be run after the illumination dot and scrim are shown.
+ // The runnable is reset to null after it's executed once.
+ @Nullable private Runnable mRunAfterShowingScrimAndDot;
+
public UdfpsView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -279,6 +283,11 @@
}
canvas.restore();
+
+ if (mShowScrimAndDot && mRunAfterShowingScrimAndDot != null) {
+ post(mRunAfterShowingScrimAndDot);
+ mRunAfterShowingScrimAndDot = null;
+ }
}
RectF getSensorRect() {
@@ -294,6 +303,10 @@
postInvalidate();
}
+ void setRunAfterShowingScrimAndDot(Runnable runnable) {
+ mRunAfterShowingScrimAndDot = runnable;
+ }
+
boolean isValidTouch(float x, float y, float pressure) {
// The X and Y coordinates of the sensor's center.
final float cx = mSensorRect.centerX();
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index 7ca8e63..239a77e 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -20,6 +20,7 @@
import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
import android.content.Context;
+import android.hardware.SensorPrivacyManager;
import android.os.Handler;
import android.os.PowerManager;
@@ -62,6 +63,10 @@
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyControllerImpl;
+import com.android.systemui.statusbar.policy.SensorPrivacyController;
+import com.android.systemui.statusbar.policy.SensorPrivacyControllerImpl;
import javax.inject.Named;
@@ -116,6 +121,25 @@
return bC;
}
+ @Provides
+ @SysUISingleton
+ static SensorPrivacyController provideSensorPrivacyController(
+ SensorPrivacyManager sensorPrivacyManager) {
+ SensorPrivacyController spC = new SensorPrivacyControllerImpl(sensorPrivacyManager);
+ spC.init();
+ return spC;
+ }
+
+ @Provides
+ @SysUISingleton
+ static IndividualSensorPrivacyController provideIndividualSensorPrivacyController(
+ SensorPrivacyManager sensorPrivacyManager) {
+ IndividualSensorPrivacyController spC = new IndividualSensorPrivacyControllerImpl(
+ sensorPrivacyManager);
+ spC.init();
+ return spC;
+ }
+
@Binds
@SysUISingleton
public abstract QSFactory bindQSFactory(QSFactoryImpl qsFactoryImpl);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 5d184ef..a23b07c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -37,6 +37,7 @@
import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
@@ -817,6 +818,7 @@
mNavigationBarView.setNavigationIconHints(hints);
}
checkBarModes();
+ updateSystemUiStateFlags(-1);
}
@Override
@@ -1315,6 +1317,8 @@
mSysUiFlagsContainer.setFlag(SYSUI_STATE_A11Y_BUTTON_CLICKABLE, clickable)
.setFlag(SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE, longClickable)
.setFlag(SYSUI_STATE_NAV_BAR_HIDDEN, !isNavBarWindowVisible())
+ .setFlag(SYSUI_STATE_IME_SHOWING,
+ (mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0)
.commitUpdate(mDisplayId);
registerAction(clickable, SystemActions.SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON);
registerAction(longClickable, SystemActions.SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON_CHOOSER);
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index 065920c..a8761a6 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -80,6 +80,7 @@
INVALID_APPWIDGET_ID);
mShowSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
+ setResult(RESULT_CANCELED);
// Finish the configuration activity immediately if a widget is added for multiple
// conversations. If the mAppWidgetId is INVALID, then the activity wasn't launched as a
// widget configuration activity.
@@ -151,10 +152,14 @@
private void finishActivity() {
if (PeopleSpaceUtils.DEBUG) Log.d(TAG, "Widget added!");
mUiEventLogger.log(PeopleSpaceUtils.PeopleSpaceWidgetEvent.PEOPLE_SPACE_WIDGET_ADDED);
+ setActivityResult(RESULT_OK);
+ finish();
+ }
+
+ private void setActivityResult(int result) {
Intent resultValue = new Intent();
resultValue.putExtra(EXTRA_APPWIDGET_ID, mAppWidgetId);
- setResult(RESULT_OK, resultValue);
- finish();
+ setResult(result, resultValue);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
index 1d2e747..eec69f98 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
@@ -28,7 +28,7 @@
appsAndTypes = itemsList.groupBy({ it.application }, { it.privacyType })
.toList()
.sortedWith(compareBy({ -it.second.size }, // Sort by number of AppOps
- { it.second.min() })) // Sort by "smallest" AppOpp (Location is largest)
+ { it.second.minOrNull() })) // Sort by "smallest" AppOpp (Location is largest)
types = itemsList.map { it.privacyType }.distinct().sorted()
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index e9207f1..bba8579 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -29,6 +29,7 @@
import com.android.systemui.qs.TouchAnimator.Builder;
import com.android.systemui.qs.TouchAnimator.Listener;
import com.android.systemui.qs.dagger.QSScope;
+import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -49,7 +50,9 @@
private static final String MOVE_FULL_ROWS = "sysui_qs_move_whole_rows";
public static final float EXPANDED_TILE_DELAY = .86f;
-
+ private static final long QQS_FADE_IN_DURATION = 200L;
+ // Fade out faster than fade in to finish before QQS hides.
+ private static final long QQS_FADE_OUT_DURATION = 50L;
private final ArrayList<View> mAllViews = new ArrayList<>();
/**
@@ -77,6 +80,7 @@
private TouchAnimator mBrightnessAnimator;
private boolean mNeedsAnimatorUpdate = false;
+ private boolean mToShowing;
private boolean mOnKeyguard;
private boolean mAllowFancy;
@@ -133,6 +137,18 @@
}
}
+ void startAlphaAnimation(boolean show) {
+ if (show == mToShowing) {
+ return;
+ }
+ mToShowing = show;
+ if (show) {
+ CrossFadeHelper.fadeIn(mQs.getView(), QQS_FADE_IN_DURATION, 0 /* delay */);
+ } else {
+ CrossFadeHelper.fadeOut(mQs.getView(), QQS_FADE_OUT_DURATION, 0 /* delay */,
+ null /* endRunnable */);
+ }
+ }
/**
* Sets whether or not the keyguard is currently being shown with a collapsed header.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 16e9590..562ac64 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -91,6 +91,11 @@
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
}
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
void onMediaVisibilityChanged(boolean qsVisible) {
mAnimateBottomOnNextLayout = qsVisible;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index dbdd04a..9a0827d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -186,7 +186,7 @@
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
boolean sizeChanged = (oldTop - oldBottom) != (top - bottom);
if (sizeChanged) {
- setQsExpansion(mLastQSExpansion, mLastQSExpansion);
+ setQsExpansion(mLastQSExpansion, mLastHeaderTranslation);
}
});
}
@@ -391,6 +391,9 @@
@Override
public void setQsExpansion(float expansion, float headerTranslation) {
if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + headerTranslation);
+ if (mQSAnimator != null) {
+ mQSAnimator.startAlphaAnimation(headerTranslation == 0 /* show */);
+ }
mContainer.setExpansion(expansion);
final float translationScaleY = expansion - 1;
boolean onKeyguardAndExpanded = isKeyguardShowing() && !mShowCollapsedOnKeyguard;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index ba71fa6..9b3775e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -30,6 +30,7 @@
import com.android.systemui.qs.tiles.AirplaneModeTile;
import com.android.systemui.qs.tiles.BatterySaverTile;
import com.android.systemui.qs.tiles.BluetoothTile;
+import com.android.systemui.qs.tiles.CameraToggleTile;
import com.android.systemui.qs.tiles.CastTile;
import com.android.systemui.qs.tiles.CellularTile;
import com.android.systemui.qs.tiles.ColorInversionTile;
@@ -39,6 +40,7 @@
import com.android.systemui.qs.tiles.HotspotTile;
import com.android.systemui.qs.tiles.InternetTile;
import com.android.systemui.qs.tiles.LocationTile;
+import com.android.systemui.qs.tiles.MicrophoneToggleTile;
import com.android.systemui.qs.tiles.NfcTile;
import com.android.systemui.qs.tiles.NightDisplayTile;
import com.android.systemui.qs.tiles.ReduceBrightColorsTile;
@@ -83,6 +85,8 @@
private final Provider<UiModeNightTile> mUiModeNightTileProvider;
private final Provider<ScreenRecordTile> mScreenRecordTileProvider;
private final Provider<ReduceBrightColorsTile> mReduceBrightColorsTileProvider;
+ private final Provider<CameraToggleTile> mCameraToggleTileProvider;
+ private final Provider<MicrophoneToggleTile> mMicrophoneToggleTileProvider;
private final Lazy<QSHost> mQsHostLazy;
private final Provider<CustomTile.Builder> mCustomTileBuilderProvider;
@@ -115,7 +119,9 @@
Provider<GarbageMonitor.MemoryTile> memoryTileProvider,
Provider<UiModeNightTile> uiModeNightTileProvider,
Provider<ScreenRecordTile> screenRecordTileProvider,
- Provider<ReduceBrightColorsTile> reduceBrightColorsTileProvider) {
+ Provider<ReduceBrightColorsTile> reduceBrightColorsTileProvider,
+ Provider<CameraToggleTile> cameraToggleTileProvider,
+ Provider<MicrophoneToggleTile> microphoneToggleTileProvider) {
mQsHostLazy = qsHostLazy;
mCustomTileBuilderProvider = customTileBuilderProvider;
@@ -143,6 +149,8 @@
mUiModeNightTileProvider = uiModeNightTileProvider;
mScreenRecordTileProvider = screenRecordTileProvider;
mReduceBrightColorsTileProvider = reduceBrightColorsTileProvider;
+ mCameraToggleTileProvider = cameraToggleTileProvider;
+ mMicrophoneToggleTileProvider = microphoneToggleTileProvider;
}
public QSTile createTile(String tileSpec) {
@@ -198,6 +206,10 @@
return mScreenRecordTileProvider.get();
case "reduce_brightness":
return mReduceBrightColorsTileProvider.get();
+ case "cameratoggle":
+ return mCameraToggleTileProvider.get();
+ case "mictoggle":
+ return mMicrophoneToggleTileProvider.get();
}
// Custom tiles
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
new file mode 100644
index 0000000..98740a2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import static android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA;
+
+import static com.android.systemui.DejankUtils.whitelistIpcs;
+
+import android.annotation.StringRes;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.DeviceConfig;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
+
+import javax.inject.Inject;
+
+public class CameraToggleTile extends SensorPrivacyToggleTile {
+
+ @Inject
+ protected CameraToggleTile(QSHost host,
+ @Background Looper backgroundLooper,
+ @Main Handler mainHandler,
+ MetricsLogger metricsLogger,
+ StatusBarStateController statusBarStateController,
+ ActivityStarter activityStarter,
+ QSLogger qsLogger,
+ IndividualSensorPrivacyController sensorPrivacyController) {
+ super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController,
+ activityStarter, qsLogger, sensorPrivacyController);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return /*getHost().getContext().getPackageManager().hasSystemFeature(FEATURE_CAMERA_TOGGLE)
+ && */whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ "camera_toggle_enabled",
+ false));
+ }
+
+ @Override
+ public @DrawableRes int getIconRes() {
+ return R.drawable.ic_camera_blocked;
+ }
+
+ @Override
+ public @NonNull CharSequence getTileLabel() {
+ return mContext.getString(R.string.quick_settings_camera_label);
+ }
+
+ @Override
+ public int getSensorId() {
+ return CAMERA;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
new file mode 100644
index 0000000..8cc0d7b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import static android.service.SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
+
+import static com.android.systemui.DejankUtils.whitelistIpcs;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.DeviceConfig;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
+
+import javax.inject.Inject;
+
+public class MicrophoneToggleTile extends SensorPrivacyToggleTile {
+
+ @Inject
+ protected MicrophoneToggleTile(QSHost host,
+ @Background Looper backgroundLooper,
+ @Main Handler mainHandler,
+ MetricsLogger metricsLogger,
+ StatusBarStateController statusBarStateController,
+ ActivityStarter activityStarter,
+ QSLogger qsLogger,
+ IndividualSensorPrivacyController sensorPrivacyController) {
+ super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController,
+ activityStarter, qsLogger, sensorPrivacyController);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ "mic_toggle_enabled",
+ false));
+ }
+
+ @Override
+ public @DrawableRes int getIconRes() {
+ return R.drawable.ic_mic_blocked;
+ }
+
+ @Override
+ public @NonNull CharSequence getTileLabel() {
+ return mContext.getString(R.string.quick_settings_mic_label);
+ }
+
+ @Override
+ public int getSensorId() {
+ return MICROPHONE;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
new file mode 100644
index 0000000..12205d6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.Intent;
+import android.hardware.SensorPrivacyManager.IndividualSensor;
+import android.os.Handler;
+import android.os.Looper;
+import android.service.quicksettings.Tile;
+import android.widget.Switch;
+
+import androidx.annotation.DrawableRes;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
+
+/**
+ * Superclass to toggle individual sensor privacy via quick settings tiles
+ */
+public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanState> implements
+ IndividualSensorPrivacyController.Callback {
+
+ private IndividualSensorPrivacyController mSensorPrivacyController;
+
+ /**
+ * @return Id of the sensor that will be toggled
+ */
+ public abstract @IndividualSensor int getSensorId();
+
+ /**
+ * @return icon for the QS tile
+ */
+ public abstract @DrawableRes int getIconRes();
+
+ protected SensorPrivacyToggleTile(QSHost host,
+ @Background Looper backgroundLooper,
+ @Main Handler mainHandler,
+ MetricsLogger metricsLogger,
+ StatusBarStateController statusBarStateController,
+ ActivityStarter activityStarter,
+ QSLogger qsLogger,
+ IndividualSensorPrivacyController sensorPrivacyController) {
+ super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController,
+ activityStarter, qsLogger);
+ mSensorPrivacyController = sensorPrivacyController;
+ mSensorPrivacyController.observe(getLifecycle(), this);
+ }
+
+ @Override
+ public BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ protected void handleClick() {
+ mSensorPrivacyController.setSensorBlocked(getSensorId(),
+ !mSensorPrivacyController.isSensorBlocked(getSensorId()));
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ boolean isBlocked = arg == null ? mSensorPrivacyController.isSensorBlocked(getSensorId())
+ : (boolean) arg;
+
+ state.icon = ResourceIcon.get(getIconRes());
+ state.state = isBlocked ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+ state.value = isBlocked;
+ state.label = getTileLabel();
+ state.handlesLongClick = false;
+ state.contentDescription = state.label;
+ state.expandedAccessibilityClassName = Switch.class.getName();
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return 0;
+ }
+
+ @Override
+ public Intent getLongClickIntent() {
+ return null;
+ }
+
+ @Override
+ public void onSensorBlockedChanged(int sensor, boolean blocked) {
+ if (sensor == getSensorId()) {
+ refreshState(blocked);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index 357702a..41c2098 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -63,6 +63,7 @@
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
+import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
@@ -117,6 +118,7 @@
private final DisplayMetrics mDisplayMetrics;
private final float mCornerSizeX;
private final float mDismissDeltaY;
+ private final AccessibilityManager mAccessibilityManager;
private int mNavMode;
private int mLeftInset;
@@ -178,6 +180,8 @@
mDisplayMetrics = new DisplayMetrics();
mContext.getDisplay().getRealMetrics(mDisplayMetrics);
+
+ mAccessibilityManager = AccessibilityManager.getInstance(mContext);
}
/**
@@ -331,8 +335,10 @@
mScreenshotPreview.setScaleX(currentScale);
mScreenshotPreview.setScaleY(currentScale);
- mDismissButton.setAlpha(0);
- mDismissButton.setVisibility(View.VISIBLE);
+ if (mAccessibilityManager.isEnabled()) {
+ mDismissButton.setAlpha(0);
+ mDismissButton.setVisibility(View.VISIBLE);
+ }
AnimatorSet dropInAnimation = new AnimatorSet();
ValueAnimator flashInAnimator = ValueAnimator.ofFloat(0, 1);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index f0efed3..00acd7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -43,6 +43,7 @@
import com.android.systemui.statusbar.StatusBarWifiView;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
+import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.NoCallingIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import java.util.List;
@@ -62,6 +63,10 @@
public void setIcon(String slot, StatusBarIcon icon);
public void setSignalIcon(String slot, WifiIconState state);
public void setMobileIcons(String slot, List<MobileIconState> states);
+ /**
+ * Display the no calling & SMS icons.
+ */
+ void setNoCallingIcons(String slot, List<NoCallingIconState> states);
public void setIconVisibility(String slot, boolean b);
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 2870152..5e8d590 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -35,6 +35,7 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
+import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.NoCallingIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -216,6 +217,29 @@
}
}
+ /**
+ * Accept a list of NoCallingIconStates, and show them in the same slot
+ * @param slot StatusBar slot
+ * @param states All of the no Calling & SMS icon states
+ */
+ @Override
+ public void setNoCallingIcons(String slot, List<NoCallingIconState> states) {
+ Slot noCallingSlot = getSlot(slot);
+ int slotIndex = getSlotIndex(slot);
+
+ for (NoCallingIconState state : states) {
+ StatusBarIconHolder holder = noCallingSlot.getHolderForTag(state.subId);
+ if (holder == null) {
+ holder = StatusBarIconHolder.fromNoCallingState(mContext, state);
+ holder.setVisible(state.visible);
+ setIcon(slotIndex, holder);
+ } else {
+ holder.setVisible(state.visible);
+ setIcon(slotIndex, holder);
+ }
+ }
+ }
+
@Override
public void setExternalIcon(String slot) {
int viewIndex = getViewIndex(getSlotIndex(slot), 0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
index 88d0035..36a0e63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
@@ -23,6 +23,7 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
+import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.NoCallingIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
/**
@@ -70,6 +71,18 @@
return holder;
}
+ /**
+ * Creates a new StatusBarIconHolder from a NoCallingIconState.
+ */
+ public static StatusBarIconHolder fromNoCallingState(
+ Context context, NoCallingIconState state) {
+ StatusBarIconHolder holder = new StatusBarIconHolder();
+ holder.mIcon = new StatusBarIcon(UserHandle.SYSTEM, context.getPackageName(),
+ Icon.createWithResource(context, state.resId), 0, 0, null);
+ holder.mTag = state.subId;
+ return holder;
+ }
+
public int getType() {
return mType;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 1fdd816..d11e864 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -46,6 +46,7 @@
private final String mSlotWifi;
private final String mSlotEthernet;
private final String mSlotVpn;
+ private final String mSlotNoCalling;
private final Context mContext;
private final StatusBarIconController mIconController;
@@ -66,6 +67,7 @@
private boolean mWifiVisible = false;
private ArrayList<MobileIconState> mMobileStates = new ArrayList<MobileIconState>();
+ private ArrayList<NoCallingIconState> mNoCallingStates = new ArrayList<NoCallingIconState>();
private WifiIconState mWifiIconState = new WifiIconState();
public StatusBarSignalPolicy(Context context, StatusBarIconController iconController) {
@@ -76,6 +78,7 @@
mSlotWifi = mContext.getString(com.android.internal.R.string.status_bar_wifi);
mSlotEthernet = mContext.getString(com.android.internal.R.string.status_bar_ethernet);
mSlotVpn = mContext.getString(com.android.internal.R.string.status_bar_vpn);
+ mSlotNoCalling = mContext.getString(com.android.internal.R.string.status_bar_no_calling);
mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity);
mIconController = iconController;
@@ -198,6 +201,22 @@
}
@Override
+ public void setNoCallingStatus(boolean noCalling, int subId) {
+ if (DEBUG) {
+ Log.d(TAG, "setNoCallingStatus: "
+ + "noCalling = " + noCalling + ","
+ + "subId = " + subId);
+ }
+ NoCallingIconState state = getNoCallingState(subId);
+ if (state == null) {
+ return;
+ }
+ state.visible = noCalling;
+ mIconController.setNoCallingIcons(
+ mSlotNoCalling, NoCallingIconState.copyStates(mNoCallingStates));
+ }
+
+ @Override
public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
int qsType, boolean activityIn, boolean activityOut,
CharSequence typeContentDescription,
@@ -252,6 +271,16 @@
}
}
+ private NoCallingIconState getNoCallingState(int subId) {
+ for (NoCallingIconState state : mNoCallingStates) {
+ if (state.subId == subId) {
+ return state;
+ }
+ }
+ Log.e(TAG, "Unexpected subscription " + subId);
+ return null;
+ }
+
private MobileIconState getState(int subId) {
for (MobileIconState state : mMobileStates) {
if (state.subId == subId) {
@@ -285,9 +314,11 @@
mIconController.removeAllIconsForSlot(mSlotMobile);
mMobileStates.clear();
+ mNoCallingStates.clear();
final int n = subs.size();
for (int i = 0; i < n; i++) {
mMobileStates.add(new MobileIconState(subs.get(i).getSubscriptionId()));
+ mNoCallingStates.add(new NoCallingIconState(subs.get(i).getSubscriptionId()));
}
}
@@ -377,6 +408,53 @@
// Don't care.
}
+ /**
+ * Stores the StatusBar state for no Calling & SMS.
+ */
+ public static class NoCallingIconState {
+ public boolean visible;
+ public int resId;
+ public int subId;
+
+ private NoCallingIconState(int subId) {
+ this.subId = subId;
+ this.resId = R.drawable.ic_qs_no_calling_sms;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ // Skipping reference equality bc this should be more of a value type
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ NoCallingIconState that = (NoCallingIconState) o;
+ return visible == that.visible
+ && resId == that.resId
+ && subId == that.subId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(visible, resId, subId);
+ }
+
+ private void copyTo(NoCallingIconState other) {
+ other.visible = visible;
+ other.resId = resId;
+ other.subId = subId;
+ }
+
+ private static List<NoCallingIconState> copyStates(List<NoCallingIconState> inStates) {
+ ArrayList<NoCallingIconState> outStates = new ArrayList<>();
+ for (NoCallingIconState state : inStates) {
+ NoCallingIconState copy = new NoCallingIconState(state.subId);
+ state.copyTo(copy);
+ outStates.add(copy);
+ }
+ return outStates;
+ }
+ }
+
private static abstract class SignalIconState {
public boolean visible;
public boolean activityOut;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index 1cc312a..5e88cd5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -146,6 +146,15 @@
}
@Override
+ public void setNoCallingStatus(boolean noCalling, int subId) {
+ post(() -> {
+ for (SignalCallback signalCluster : mSignalCallbacks) {
+ signalCluster.setNoCallingStatus(noCalling, subId);
+ }
+ });
+ }
+
+ @Override
public void setSubs(List<SubscriptionInfo> subs) {
obtainMessage(MSG_SUBS_CHANGED, subs).sendToTarget();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
new file mode 100644
index 0000000..a76d08a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.hardware.SensorPrivacyManager.IndividualSensor;
+
+public interface IndividualSensorPrivacyController extends
+ CallbackController<IndividualSensorPrivacyController.Callback> {
+ void init();
+
+ boolean isSensorBlocked(@IndividualSensor int sensor);
+
+ void setSensorBlocked(@IndividualSensor int sensor, boolean blocked);
+
+ interface Callback {
+ void onSensorBlockedChanged(@IndividualSensor int sensor, boolean blocked);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
new file mode 100644
index 0000000..231fe08
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import static android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA;
+import static android.service.SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
+
+import android.hardware.SensorPrivacyManager;
+import android.hardware.SensorPrivacyManager.IndividualSensor;
+import android.util.ArraySet;
+import android.util.SparseBooleanArray;
+
+import androidx.annotation.NonNull;
+
+import java.util.Set;
+
+public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPrivacyController {
+
+ private static final int[] SENSORS = new int[] {CAMERA, MICROPHONE};
+
+ private final @NonNull SensorPrivacyManager mSensorPrivacyManager;
+ private final SparseBooleanArray mState = new SparseBooleanArray();
+ private final Set<Callback> mCallbacks = new ArraySet<>();
+
+ public IndividualSensorPrivacyControllerImpl(
+ @NonNull SensorPrivacyManager sensorPrivacyManager) {
+ mSensorPrivacyManager = sensorPrivacyManager;
+ }
+
+ @Override
+ public void init() {
+ for (int sensor : SENSORS) {
+ mSensorPrivacyManager.addSensorPrivacyListener(sensor,
+ (enabled) -> onSensorPrivacyChanged(sensor, enabled));
+
+ mState.put(sensor, mSensorPrivacyManager.isIndividualSensorPrivacyEnabled(sensor));
+ }
+ }
+
+ @Override
+ public boolean isSensorBlocked(@IndividualSensor int sensor) {
+ return mState.get(sensor, false);
+ }
+
+ @Override
+ public void setSensorBlocked(@IndividualSensor int sensor, boolean blocked) {
+ mSensorPrivacyManager.setIndividualSensorPrivacyForProfileGroup(sensor, blocked);
+ }
+
+ @Override
+ public void addCallback(@NonNull Callback listener) {
+ mCallbacks.add(listener);
+ }
+
+ @Override
+ public void removeCallback(@NonNull Callback listener) {
+ mCallbacks.remove(listener);
+ }
+
+ private void onSensorPrivacyChanged(@IndividualSensor int sensor, boolean blocked) {
+ mState.put(sensor, blocked);
+
+ for (Callback callback : mCallbacks) {
+ callback.onSensorBlockedChanged(sensor, blocked);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 101e3c6..24b8206 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -458,9 +458,23 @@
mCurrentState.dataSim = mobileStatus.dataSim;
mCurrentState.carrierNetworkChangeMode = mobileStatus.carrierNetworkChangeMode;
mDataState = mobileStatus.dataState;
- mServiceState = mobileStatus.serviceState;
mSignalStrength = mobileStatus.signalStrength;
mTelephonyDisplayInfo = mobileStatus.telephonyDisplayInfo;
+ int lastVoiceState = mServiceState != null ? mServiceState.getState() : -1;
+ mServiceState = mobileStatus.serviceState;
+ int currentVoiceState = mServiceState != null ? mServiceState.getState() : -1;
+ // Only update the no calling Status in the below scenarios
+ // 1. The first valid voice state has been received
+ // 2. The voice state has been changed and either the last or current state is
+ // ServiceState.STATE_IN_SERVICE
+ if (lastVoiceState != currentVoiceState
+ && (lastVoiceState == -1
+ || (lastVoiceState == ServiceState.STATE_IN_SERVICE
+ || currentVoiceState == ServiceState.STATE_IN_SERVICE))) {
+ notifyNoCallingStatusChange(
+ currentVoiceState != ServiceState.STATE_IN_SERVICE,
+ mSubscriptionInfo.getSubscriptionId());
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index a9c6016..f2b0d76 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -92,6 +92,13 @@
*/
default void setConnectivityStatus(boolean noDefaultNetwork, boolean noValidatedNetwork,
boolean noNetworksAvailable) {}
+
+ /**
+ * Callback for listeners to be able to update the no calling & SMS status
+ * @param noCalling whether the calling and SMS is not working.
+ * @param subId subscription ID for which to update the UI
+ */
+ default void setNoCallingStatus(boolean noCalling, int subId) {}
}
public interface EmergencyListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 1d77841..4f4a504 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -33,7 +33,6 @@
import android.net.ConnectivityManager.NetworkCallback;
import android.net.IConnectivityManager;
import android.net.Network;
-import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Handler;
import android.os.RemoteException;
@@ -75,12 +74,8 @@
private static final String TAG = "SecurityController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final NetworkRequest REQUEST = new NetworkRequest.Builder()
- .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
- .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
- .setUids(null)
- .build();
+ private static final NetworkRequest REQUEST =
+ new NetworkRequest.Builder().clearCapabilities().build();
private static final int NO_NETWORK = -1;
private static final String VPN_BRANDED_META_DATA = "com.android.systemui.IS_BRANDED";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java
index 6d5ce60..4a09234 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java
@@ -23,6 +23,11 @@
CallbackController<SensorPrivacyController.OnSensorPrivacyChangedListener> {
/**
+ * Initialize the controller. Needs to be called after constructing the object
+ */
+ void init();
+
+ /**
* Returns whether sensor privacy is enabled.
*/
boolean isSensorPrivacyEnabled();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java
index 20cc46f..a2334f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java
@@ -35,20 +35,21 @@
public class SensorPrivacyControllerImpl implements SensorPrivacyController,
SensorPrivacyManager.OnSensorPrivacyChangedListener {
private SensorPrivacyManager mSensorPrivacyManager;
- private final List<OnSensorPrivacyChangedListener> mListeners;
+ private final List<OnSensorPrivacyChangedListener> mListeners = new ArrayList<>(1);
private Object mLock = new Object();
private boolean mSensorPrivacyEnabled;
/**
* Public constructor.
*/
- @Inject
- public SensorPrivacyControllerImpl(Context context) {
- mSensorPrivacyManager = (SensorPrivacyManager) context.getSystemService(
- Context.SENSOR_PRIVACY_SERVICE);
+ public SensorPrivacyControllerImpl(@NonNull SensorPrivacyManager sensorPrivacyManager) {
+ mSensorPrivacyManager = sensorPrivacyManager;
+ }
+
+ @Override
+ public void init() {
mSensorPrivacyEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled();
mSensorPrivacyManager.addSensorPrivacyListener(this);
- mListeners = new ArrayList<>(1);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index a05fe1f..554145e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -167,6 +167,10 @@
}
}
+ protected final void notifyNoCallingStatusChange(boolean noCalling, int subId) {
+ mCallbackHandler.setNoCallingStatus(noCalling, subId);
+ }
+
/**
* Returns the resource if resId is not 0, and an empty string otherwise.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
index 069b405..7a4b912 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
@@ -107,11 +107,6 @@
/** */
@Binds
- SensorPrivacyController provideSensorPrivacyControllerImpl(
- SensorPrivacyControllerImpl controllerImpl);
-
- /** */
- @Binds
UserInfoController provideUserInfoContrller(UserInfoControllerImpl controllerImpl);
/** */
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
index 56a4c203..df889f2 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -20,6 +20,7 @@
import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
import android.content.Context;
+import android.hardware.SensorPrivacyManager;
import android.os.Handler;
import android.os.PowerManager;
@@ -63,6 +64,10 @@
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyControllerImpl;
+import com.android.systemui.statusbar.policy.SensorPrivacyController;
+import com.android.systemui.statusbar.policy.SensorPrivacyControllerImpl;
import com.android.systemui.statusbar.tv.notifications.TvNotificationHandler;
import javax.inject.Named;
@@ -109,6 +114,25 @@
return bC;
}
+ @Provides
+ @SysUISingleton
+ static SensorPrivacyController provideSensorPrivacyController(
+ SensorPrivacyManager sensorPrivacyManager) {
+ SensorPrivacyController spC = new SensorPrivacyControllerImpl(sensorPrivacyManager);
+ spC.init();
+ return spC;
+ }
+
+ @Provides
+ @SysUISingleton
+ static IndividualSensorPrivacyController provideIndividualSensorPrivacyController(
+ SensorPrivacyManager sensorPrivacyManager) {
+ IndividualSensorPrivacyController spC = new IndividualSensorPrivacyControllerImpl(
+ sensorPrivacyManager);
+ spC.init();
+ return spC;
+ }
+
@Binds
@SysUISingleton
abstract QSFactory bindQSFactory(QSFactoryImpl qsFactoryImpl);
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
index 08cd6e3..8d77c4a 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
@@ -33,7 +33,7 @@
static final String REASON_WRAP = "wrap";
/**
- * Default wake-lock timeout, to avoid battery regressions.
+ * Default wake-lock timeout in milliseconds, to avoid battery regressions.
*/
long DEFAULT_MAX_TIMEOUT = 20000;
@@ -104,6 +104,7 @@
if (count == null) {
Log.wtf(TAG, "Releasing WakeLock with invalid reason: " + why,
new Throwable());
+ return;
} else if (count == 1) {
mActiveClients.remove(why);
} else {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index b24f4ab..c052563 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -106,6 +106,7 @@
@Captor private ArgumentCaptor<IUdfpsOverlayController> mOverlayCaptor;
private IUdfpsOverlayController mOverlayController;
@Captor private ArgumentCaptor<UdfpsView.OnTouchListener> mTouchListenerCaptor;
+ @Captor private ArgumentCaptor<Runnable> mRunAfterShowingScrimAndDotCaptor;
@Before
public void setUp() {
@@ -190,11 +191,14 @@
MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event);
event.recycle();
- // THEN the event is passed to the FingerprintManager
+ // THEN the scrim and dot is shown
+ verify(mUdfpsView).showScrimAndDot();
+ // AND a runnable that passes the event to FingerprintManager is set on the view
+ verify(mUdfpsView).setRunAfterShowingScrimAndDot(
+ mRunAfterShowingScrimAndDotCaptor.capture());
+ mRunAfterShowingScrimAndDotCaptor.getValue().run();
verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mSensorProps.sensorId), eq(0),
eq(0), eq(0f), eq(0f));
- // AND the scrim and dot is shown
- verify(mUdfpsView).showScrimAndDot();
}
@Test
@@ -205,11 +209,14 @@
mFgExecutor.runAllReady();
// WHEN fingerprint is requested because of AOD interrupt
mUdfpsController.onAodInterrupt(0, 0, 2f, 3f);
- // THEN the event is passed to the FingerprintManager
+ // THEN the scrim and dot is shown
+ verify(mUdfpsView).showScrimAndDot();
+ // AND a runnable that passes the event to FingerprintManager is set on the view
+ verify(mUdfpsView).setRunAfterShowingScrimAndDot(
+ mRunAfterShowingScrimAndDotCaptor.capture());
+ mRunAfterShowingScrimAndDotCaptor.getValue().run();
verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mSensorProps.sensorId), eq(0),
eq(0), eq(3f) /* minor */, eq(2f) /* major */);
- // AND the scrim and dot is shown
- verify(mUdfpsView).showScrimAndDot();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
index 2e874a6..c0af15b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
@@ -20,6 +20,7 @@
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
+import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.NoCallingIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import java.util.List;
@@ -65,6 +66,10 @@
}
@Override
+ public void setNoCallingIcons(String slot, List<NoCallingIconState> states) {
+ }
+
+ @Override
public void setIconVisibility(String slotTty, boolean b) {
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index 446d3f2..8b86403 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -120,4 +120,4 @@
verify(mConfigurationController).addCallback(
any(ConfigurationController.ConfigurationListener.class));
}
-}
\ No newline at end of file
+}
diff --git a/packages/services/CameraExtensionsProxy/OWNERS b/packages/services/CameraExtensionsProxy/OWNERS
new file mode 100644
index 0000000..f48a95c
--- /dev/null
+++ b/packages/services/CameraExtensionsProxy/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/av:/camera/OWNERS
diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java
index 9ba71dc..e99bb24 100644
--- a/services/core/java/com/android/server/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/SensorPrivacyService.java
@@ -283,11 +283,16 @@
mIndividualEnabled.put(userId, userIndividualEnabled);
if (!enable) {
- // Remove any notifications prompting the user to disable sensory privacy
- NotificationManager notificationManager =
- mContext.getSystemService(NotificationManager.class);
+ long token = Binder.clearCallingIdentity();
+ try {
+ // Remove any notifications prompting the user to disable sensory privacy
+ NotificationManager notificationManager =
+ mContext.getSystemService(NotificationManager.class);
- notificationManager.cancel(sensor);
+ notificationManager.cancel(sensor);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
persistSensorPrivacyState();
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index b76f3278..dde182b 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -564,8 +564,7 @@
mPreciseDataConnectionStates.add(new ArrayMap<>());
mBarringInfo.add(i, new BarringInfo());
mTelephonyDisplayInfos[i] = null;
- mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig(
- PhysicalChannelConfig.CONNECTION_UNKNOWN,0));
+ mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build());
}
}
@@ -656,8 +655,7 @@
mPreciseDataConnectionStates.add(new ArrayMap<>());
mBarringInfo.add(i, new BarringInfo());
mTelephonyDisplayInfos[i] = null;
- mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig(
- PhysicalChannelConfig.CONNECTION_UNKNOWN,0));
+ mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build());
}
mAppOps = mContext.getSystemService(AppOpsManager.class);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 25f7fb6..b587f1b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15320,10 +15320,10 @@
*/
@GuardedBy("this")
void tempWhitelistForPendingIntentLocked(int callerPid, int callerUid, int targetUid,
- long duration, String tag) {
+ long duration, int type, String tag) {
if (DEBUG_WHITELISTS) {
Slog.d(TAG, "tempWhitelistForPendingIntentLocked(" + callerPid + ", " + callerUid + ", "
- + targetUid + ", " + duration + ")");
+ + targetUid + ", " + duration + ", " + type + ")");
}
synchronized (mPidsSelfLocked) {
@@ -15335,7 +15335,11 @@
}
if (!pr.whitelistManager) {
if (checkPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST, callerPid, callerUid)
- != PackageManager.PERMISSION_GRANTED) {
+ != PackageManager.PERMISSION_GRANTED
+ && checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callerPid, callerUid)
+ != PackageManager.PERMISSION_GRANTED
+ && checkPermission(START_FOREGROUND_SERVICES_FROM_BACKGROUND, callerPid,
+ callerUid) != PackageManager.PERMISSION_GRANTED) {
if (DEBUG_WHITELISTS) {
Slog.d(TAG, "tempWhitelistForPendingIntentLocked() for target " + targetUid
+ ": pid " + callerPid + " is not allowed");
@@ -15345,8 +15349,7 @@
}
}
- tempWhitelistUidLocked(targetUid, duration, tag,
- BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED);
+ tempWhitelistUidLocked(targetUid, duration, tag, type);
}
/**
@@ -15949,9 +15952,9 @@
@Override
public void setPendingIntentWhitelistDuration(IIntentSender target, IBinder whitelistToken,
- long duration) {
+ long duration, int type) {
mPendingIntentController.setPendingIntentWhitelistDuration(target, whitelistToken,
- duration);
+ duration, type);
}
@Override
@@ -16367,10 +16370,10 @@
@Override
public void tempWhitelistForPendingIntent(int callerPid, int callerUid, int targetUid,
- long duration, String tag) {
+ long duration, int type, String tag) {
synchronized (ActivityManagerService.this) {
ActivityManagerService.this.tempWhitelistForPendingIntentLocked(
- callerPid, callerUid, targetUid, duration, tag);
+ callerPid, callerUid, targetUid, duration, type, tag);
}
}
diff --git a/services/core/java/com/android/server/am/PendingIntentController.java b/services/core/java/com/android/server/am/PendingIntentController.java
index 2ae3d35..42172bf 100644
--- a/services/core/java/com/android/server/am/PendingIntentController.java
+++ b/services/core/java/com/android/server/am/PendingIntentController.java
@@ -301,13 +301,14 @@
}
void setPendingIntentWhitelistDuration(IIntentSender target, IBinder whitelistToken,
- long duration) {
+ long duration, int type) {
if (!(target instanceof PendingIntentRecord)) {
Slog.w(TAG, "markAsSentFromNotification(): not a PendingIntentRecord: " + target);
return;
}
synchronized (mLock) {
- ((PendingIntentRecord) target).setWhitelistDurationLocked(whitelistToken, duration);
+ ((PendingIntentRecord) target).setWhitelistDurationLocked(whitelistToken, duration,
+ type);
}
}
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index fbfed34..631b632 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -24,6 +24,7 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
+import android.app.BroadcastOptions;
import android.app.PendingIntent;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
@@ -37,6 +38,7 @@
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.Pair;
import android.util.Slog;
import android.util.TimeUtils;
@@ -61,7 +63,11 @@
public final WeakReference<PendingIntentRecord> ref;
boolean sent = false;
boolean canceled = false;
- private ArrayMap<IBinder, Long> whitelistDuration;
+ /**
+ * Map IBinder to duration specified as Pair<Long, Integer>, Long is allowlist duration in
+ * milliseconds, Integer is allowlist type defined at {@link BroadcastOptions.TempAllowListType}
+ */
+ private ArrayMap<IBinder, Pair<Long, Integer>> mWhitelistDuration;
private RemoteCallbackList<IResultReceiver> mCancelCallbacks;
private ArraySet<IBinder> mAllowBgActivityStartsForActivitySender = new ArraySet<>();
private ArraySet<IBinder> mAllowBgActivityStartsForBroadcastSender = new ArraySet<>();
@@ -215,16 +221,16 @@
ref = new WeakReference<>(this);
}
- void setWhitelistDurationLocked(IBinder whitelistToken, long duration) {
+ void setWhitelistDurationLocked(IBinder whitelistToken, long duration, int type) {
if (duration > 0) {
- if (whitelistDuration == null) {
- whitelistDuration = new ArrayMap<>();
+ if (mWhitelistDuration == null) {
+ mWhitelistDuration = new ArrayMap<>();
}
- whitelistDuration.put(whitelistToken, duration);
- } else if (whitelistDuration != null) {
- whitelistDuration.remove(whitelistToken);
- if (whitelistDuration.size() <= 0) {
- whitelistDuration = null;
+ mWhitelistDuration.put(whitelistToken, new Pair(duration, type));
+ } else if (mWhitelistDuration != null) {
+ mWhitelistDuration.remove(whitelistToken);
+ if (mWhitelistDuration.size() <= 0) {
+ mWhitelistDuration = null;
}
}
@@ -292,7 +298,7 @@
if (intent != null) intent.setDefusable(true);
if (options != null) options.setDefusable(true);
- Long duration = null;
+ Pair<Long, Integer> duration = null;
Intent finalIntent = null;
Intent[] allIntents = null;
String[] allResolvedTypes = null;
@@ -341,8 +347,8 @@
mergedOptions.setCallerOptions(opts);
}
- if (whitelistDuration != null) {
- duration = whitelistDuration.get(whitelistToken);
+ if (mWhitelistDuration != null) {
+ duration = mWhitelistDuration.get(whitelistToken);
}
if (key.type == ActivityManager.INTENT_SENDER_ACTIVITY
@@ -370,24 +376,19 @@
int res = START_SUCCESS;
try {
if (duration != null) {
- int procState = controller.mAmInternal.getUidProcessState(callingUid);
- if (!ActivityManager.isProcStateBackground(procState)) {
- StringBuilder tag = new StringBuilder(64);
- tag.append("pendingintent:");
- UserHandle.formatUid(tag, callingUid);
- tag.append(":");
- if (finalIntent.getAction() != null) {
- tag.append(finalIntent.getAction());
- } else if (finalIntent.getComponent() != null) {
- finalIntent.getComponent().appendShortString(tag);
- } else if (finalIntent.getData() != null) {
- tag.append(finalIntent.getData().toSafeString());
- }
- controller.mAmInternal.tempWhitelistForPendingIntent(callingPid, callingUid,
- uid, duration, tag.toString());
- } else {
- Slog.w(TAG, "Not doing whitelist " + this + ": caller state=" + procState);
+ StringBuilder tag = new StringBuilder(64);
+ tag.append("pendingintent:");
+ UserHandle.formatUid(tag, callingUid);
+ tag.append(":");
+ if (finalIntent.getAction() != null) {
+ tag.append(finalIntent.getAction());
+ } else if (finalIntent.getComponent() != null) {
+ finalIntent.getComponent().appendShortString(tag);
+ } else if (finalIntent.getData() != null) {
+ tag.append(finalIntent.getData().toSafeString());
}
+ controller.mAmInternal.tempWhitelistForPendingIntent(callingPid, callingUid,
+ uid, duration.first, duration.second, tag.toString());
}
boolean sendFinish = finishedReceiver != null;
@@ -532,16 +533,18 @@
pw.print(prefix); pw.print("sent="); pw.print(sent);
pw.print(" canceled="); pw.println(canceled);
}
- if (whitelistDuration != null) {
+ if (mWhitelistDuration != null) {
pw.print(prefix);
pw.print("whitelistDuration=");
- for (int i = 0; i < whitelistDuration.size(); i++) {
+ for (int i = 0; i < mWhitelistDuration.size(); i++) {
if (i != 0) {
pw.print(", ");
}
- pw.print(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
+ pw.print(Integer.toHexString(System.identityHashCode(mWhitelistDuration.keyAt(i))));
pw.print(":");
- TimeUtils.formatDuration(whitelistDuration.valueAt(i), pw);
+ TimeUtils.formatDuration(mWhitelistDuration.valueAt(i).first, pw);
+ pw.print("/");
+ pw.print(mWhitelistDuration.valueAt(i).second);
}
pw.println();
}
@@ -569,15 +572,18 @@
}
sb.append(' ');
sb.append(key.typeName());
- if (whitelistDuration != null) {
+ if (mWhitelistDuration != null) {
sb.append( " (whitelist: ");
- for (int i = 0; i < whitelistDuration.size(); i++) {
+ for (int i = 0; i < mWhitelistDuration.size(); i++) {
if (i != 0) {
sb.append(",");
}
- sb.append(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
+ sb.append(Integer.toHexString(System.identityHashCode(
+ mWhitelistDuration.keyAt(i))));
sb.append(":");
- TimeUtils.formatDuration(whitelistDuration.valueAt(i), sb);
+ TimeUtils.formatDuration(mWhitelistDuration.valueAt(i).first, sb);
+ sb.append("/");
+ sb.append(mWhitelistDuration.valueAt(i).second);
}
sb.append(")");
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 08eeda2..17627fa 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -8454,28 +8454,29 @@
}
for (AudioMix mix : policyConfig.getMixes()) {
// If mix is requesting privileged capture
- if (mix.getRule().allowPrivilegedPlaybackCapture()) {
- // then it must have CAPTURE_MEDIA_OUTPUT or CAPTURE_AUDIO_OUTPUT permission
- requireCaptureAudioOrMediaOutputPerm |= true;
-
- // and its format must be low quality enough
- String error = mix.canBeUsedForPrivilegedCapture(mix.getFormat());
- if (error != null) {
- Log.e(TAG, error);
+ if (mix.getRule().allowPrivilegedMediaPlaybackCapture()) {
+ // then its format must be low quality enough
+ String privilegedMediaCaptureError =
+ mix.canBeUsedForPrivilegedMediaCapture(mix.getFormat());
+ if (privilegedMediaCaptureError != null) {
+ Log.e(TAG, privilegedMediaCaptureError);
return false;
}
+ // and it must have CAPTURE_MEDIA_OUTPUT or CAPTURE_AUDIO_OUTPUT permission
+ requireCaptureAudioOrMediaOutputPerm |= true;
- // If mix is trying to excplicitly capture USAGE_VOICE_COMMUNICATION
- if (mix.containsMatchAttributeRuleForUsage(
- AudioAttributes.USAGE_VOICE_COMMUNICATION)) {
- // then it must have CAPTURE_USAGE_VOICE_COMMUNICATION_OUTPUT permission
- // Note that for UID, USERID or EXCLDUE rules, the capture will be silenced
- // in AudioPolicyMix
- if (voiceCommunicationCaptureMixes == null) {
- voiceCommunicationCaptureMixes = new ArrayList<AudioMix>();
- }
- voiceCommunicationCaptureMixes.add(mix);
+ }
+ // If mix is trying to explicitly capture USAGE_VOICE_COMMUNICATION
+ if (mix.containsMatchAttributeRuleForUsage(
+ AudioAttributes.USAGE_VOICE_COMMUNICATION)
+ && (mix.getRouteFlags() == mix.ROUTE_FLAG_LOOP_BACK_RENDER)) {
+ // It must have CAPTURE_USAGE_VOICE_COMMUNICATION_OUTPUT permission
+ // Note that for UID, USERID or EXCLDUE rules, the capture will be silenced
+ // in AudioPolicyMix
+ if (voiceCommunicationCaptureMixes == null) {
+ voiceCommunicationCaptureMixes = new ArrayList<AudioMix>();
}
+ voiceCommunicationCaptureMixes.add(mix);
}
// If mix is RENDER|LOOPBACK, then an audio MediaProjection is enough
@@ -8498,7 +8499,7 @@
if (voiceCommunicationCaptureMixes != null && voiceCommunicationCaptureMixes.size() > 0) {
if (!callerHasPermission(
android.Manifest.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT)) {
- Log.e(TAG, "Privileged audio capture for voice communication requires "
+ Log.e(TAG, "Audio capture for voice communication requires "
+ "CAPTURE_VOICE_COMMUNICATION_OUTPUT system permission");
return false;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 8abeef6..5e7ddeb 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -483,7 +483,7 @@
@Override
public long getAuthenticatorId(int sensorId, int userId) {
- return mAuthenticatorIds.get(userId);
+ return mAuthenticatorIds.getOrDefault(userId, 0L);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index 7a12196..6cc8687 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -683,7 +683,7 @@
@Override
public long getAuthenticatorId(int sensorId, int userId) {
- return mAuthenticatorIds.get(userId);
+ return mAuthenticatorIds.getOrDefault(userId, 0L);
}
@Override
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 2a81426..40d2073 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -57,6 +57,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -466,8 +467,13 @@
streamProtos[i].firstCaptureLatencyMillis = streamStats.getStartLatencyMs();
streamProtos[i].maxHalBuffers = streamStats.getMaxHalBuffers();
streamProtos[i].maxAppBuffers = streamStats.getMaxAppBuffers();
+ streamProtos[i].histogramType = streamStats.getHistogramType();
+ streamProtos[i].histogramBins = streamStats.getHistogramBins();
+ streamProtos[i].histogramCounts = streamStats.getHistogramCounts();
if (CameraServiceProxy.DEBUG) {
+ String histogramTypeName =
+ cameraHistogramTypeToString(streamProtos[i].histogramType);
Slog.v(TAG, "Stream " + i + ": width " + streamProtos[i].width
+ ", height " + streamProtos[i].height
+ ", format " + streamProtos[i].format
@@ -478,7 +484,12 @@
+ ", firstCaptureLatencyMillis "
+ streamProtos[i].firstCaptureLatencyMillis
+ ", maxHalBuffers " + streamProtos[i].maxHalBuffers
- + ", maxAppBuffers " + streamProtos[i].maxAppBuffers);
+ + ", maxAppBuffers " + streamProtos[i].maxAppBuffers
+ + ", histogramType " + histogramTypeName
+ + ", histogramBins "
+ + Arrays.toString(streamProtos[i].histogramBins)
+ + ", histogramCounts "
+ + Arrays.toString(streamProtos[i].histogramCounts));
}
}
}
@@ -797,4 +808,14 @@
return "CAMERA_FACING_UNKNOWN";
}
+ private static String cameraHistogramTypeToString(int cameraHistogramType) {
+ switch (cameraHistogramType) {
+ case CameraStreamStats.HISTOGRAM_TYPE_CAPTURE_LATENCY:
+ return "HISTOGRAM_TYPE_CAPTURE_LATENCY";
+ default:
+ break;
+ }
+ return "HISTOGRAM_TYPE_UNKNOWN";
+ }
+
}
diff --git a/services/core/java/com/android/server/connectivity/PacProxyInstaller.java b/services/core/java/com/android/server/connectivity/PacProxyInstaller.java
index aadaf4d..5dc8c1a 100644
--- a/services/core/java/com/android/server/connectivity/PacProxyInstaller.java
+++ b/services/core/java/com/android/server/connectivity/PacProxyInstaller.java
@@ -16,6 +16,7 @@
package com.android.server.connectivity;
+import android.annotation.NonNull;
import android.annotation.WorkerThread;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -71,10 +72,6 @@
private static final int DELAY_LONG = 4;
private static final long MAX_PAC_SIZE = 20 * 1000 * 1000;
- // Return values for #setCurrentProxyScriptUrl
- public static final boolean DONT_SEND_BROADCAST = false;
- public static final boolean DO_SEND_BROADCAST = true;
-
private String mCurrentPac;
@GuardedBy("mProxyLock")
private volatile Uri mPacUrl = Uri.EMPTY;
@@ -93,7 +90,7 @@
private volatile boolean mHasSentBroadcast;
private volatile boolean mHasDownloaded;
- private Handler mConnectivityHandler;
+ private final Handler mConnectivityHandler;
private final int mProxyMessage;
/**
@@ -102,6 +99,13 @@
private final Object mProxyLock = new Object();
/**
+ * Lock ensuring consistency between the values of mHasSentBroadcast, mHasDownloaded, the
+ * last URL and port, and the broadcast message being sent with the correct arguments.
+ * TODO : this should probably protect all instances of these variables
+ */
+ private final Object mBroadcastStateLock = new Object();
+
+ /**
* Runnable to download PAC script.
* The behavior relies on the assumption it always runs on mNetThread to guarantee that the
* latest data fetched from mPacUrl is stored in mProxyService.
@@ -146,7 +150,7 @@
}
}
- public PacProxyInstaller(Context context, Handler handler, int proxyMessage) {
+ public PacProxyInstaller(@NonNull Context context, @NonNull Handler handler, int proxyMessage) {
mContext = context;
mLastPort = -1;
final HandlerThread netThread = new HandlerThread("android.pacproxyinstaller",
@@ -176,31 +180,27 @@
* PacProxyInstaller will trigger a new broadcast when it is ready.
*
* @param proxy Proxy information that is about to be broadcast.
- * @return Returns whether the broadcast should be sent : either DO_ or DONT_SEND_BROADCAST
*/
- public synchronized boolean setCurrentProxyScriptUrl(ProxyInfo proxy) {
- if (!Uri.EMPTY.equals(proxy.getPacFileUrl())) {
- if (proxy.getPacFileUrl().equals(mPacUrl) && (proxy.getPort() > 0)) {
- // Allow to send broadcast, nothing to do.
- return DO_SEND_BROADCAST;
- }
- mPacUrl = proxy.getPacFileUrl();
- mCurrentDelay = DELAY_1;
- mHasSentBroadcast = false;
- mHasDownloaded = false;
- getAlarmManager().cancel(mPacRefreshIntent);
- bind();
- return DONT_SEND_BROADCAST;
- } else {
- getAlarmManager().cancel(mPacRefreshIntent);
- synchronized (mProxyLock) {
- mPacUrl = Uri.EMPTY;
- mCurrentPac = null;
- if (mProxyService != null) {
- unbind();
+ public void setCurrentProxyScriptUrl(@NonNull ProxyInfo proxy) {
+ synchronized (mBroadcastStateLock) {
+ if (!Uri.EMPTY.equals(proxy.getPacFileUrl())) {
+ if (proxy.getPacFileUrl().equals(mPacUrl) && (proxy.getPort() > 0)) return;
+ mPacUrl = proxy.getPacFileUrl();
+ mCurrentDelay = DELAY_1;
+ mHasSentBroadcast = false;
+ mHasDownloaded = false;
+ getAlarmManager().cancel(mPacRefreshIntent);
+ bind();
+ } else {
+ getAlarmManager().cancel(mPacRefreshIntent);
+ synchronized (mProxyLock) {
+ mPacUrl = Uri.EMPTY;
+ mCurrentPac = null;
+ if (mProxyService != null) {
+ unbind();
+ }
}
}
- return DO_SEND_BROADCAST;
}
}
@@ -275,6 +275,7 @@
getAlarmManager().set(AlarmManager.ELAPSED_REALTIME, timeTillTrigger, mPacRefreshIntent);
}
+ @GuardedBy("mProxyLock")
private void setCurrentProxyScript(String script) {
if (mProxyService == null) {
Log.e(TAG, "setCurrentProxyScript: no proxy service");
@@ -347,6 +348,9 @@
public void setProxyPort(int port) {
if (mLastPort != -1) {
// Always need to send if port changed
+ // TODO: Here lacks synchronization because this write cannot
+ // guarantee that it's visible from sendProxyIfNeeded() when
+ // it's called by a Runnable which is post by mNetThread.
mHasSentBroadcast = false;
}
mLastPort = port;
@@ -386,13 +390,15 @@
mConnectivityHandler.sendMessage(mConnectivityHandler.obtainMessage(mProxyMessage, proxy));
}
- private synchronized void sendProxyIfNeeded() {
- if (!mHasDownloaded || (mLastPort == -1)) {
- return;
- }
- if (!mHasSentBroadcast) {
- sendPacBroadcast(ProxyInfo.buildPacProxy(mPacUrl, mLastPort));
- mHasSentBroadcast = true;
+ private void sendProxyIfNeeded() {
+ synchronized (mBroadcastStateLock) {
+ if (!mHasDownloaded || (mLastPort == -1)) {
+ return;
+ }
+ if (!mHasSentBroadcast) {
+ sendPacBroadcast(ProxyInfo.buildPacProxy(mPacUrl, mLastPort));
+ mHasSentBroadcast = true;
+ }
}
}
}
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java
index d83ff83..b618d2b 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java
@@ -226,9 +226,9 @@
final ProxyInfo defaultProxy = getDefaultProxy();
final ProxyInfo proxyInfo = null != defaultProxy ?
defaultProxy : ProxyInfo.buildDirectProxy("", 0, Collections.emptyList());
+ mPacProxyInstaller.setCurrentProxyScriptUrl(proxyInfo);
- if (mPacProxyInstaller.setCurrentProxyScriptUrl(proxyInfo)
- == PacProxyInstaller.DONT_SEND_BROADCAST) {
+ if (!shouldSendBroadcast(proxyInfo)) {
return;
}
if (DBG) Log.d(TAG, "sending Proxy Broadcast for " + proxyInfo);
@@ -244,6 +244,13 @@
}
}
+ private boolean shouldSendBroadcast(ProxyInfo proxy) {
+ if (Uri.EMPTY.equals(proxy.getPacFileUrl())) return false;
+ if (proxy.getPacFileUrl().equals(proxy.getPacFileUrl())
+ && (proxy.getPort() > 0)) return true;
+ return true;
+ }
+
/**
* Sets the global proxy in memory. Also writes the values to the global settings of the device.
*
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 60e4595..55103ca 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -49,6 +49,7 @@
import android.graphics.ColorSpace;
import android.graphics.Point;
import android.hardware.SensorManager;
+import android.hardware.devicestate.DeviceStateManager;
import android.hardware.display.AmbientBrightnessDayStats;
import android.hardware.display.BrightnessChangeEvent;
import android.hardware.display.BrightnessConfiguration;
@@ -71,6 +72,7 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
import android.os.Looper;
@@ -100,7 +102,6 @@
import android.view.Display;
import android.view.DisplayEventReceiver;
import android.view.DisplayInfo;
-import android.view.IDisplayFoldListener;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -114,7 +115,6 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.UiThread;
-import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.SurfaceAnimationThread;
import com.android.server.wm.WindowManagerInternal;
@@ -360,8 +360,8 @@
// Receives notifications about changes to Settings.
private SettingsObserver mSettingsObserver;
- // Received notifications of the display-fold action
- private DisplayFoldListener mDisplayFoldListener;
+ // Received notifications of the device-state action (such as "fold", "unfold")
+ private DeviceStateManager mDeviceStateManager;
private final boolean mAllowNonNativeRefreshRateOverride;
@@ -504,10 +504,11 @@
synchronized (mSyncRoot) {
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
- WindowManagerPolicy policy = LocalServices.getService(WindowManagerPolicy.class);
- mDisplayFoldListener = new DisplayFoldListener();
- policy.registerDisplayFoldListener(mDisplayFoldListener);
+ DeviceStateManager deviceStateManager =
+ mContext.getSystemService(DeviceStateManager.class);
+ deviceStateManager.registerDeviceStateListener(new DeviceStateListener(),
+ new HandlerExecutor(mHandler));
scheduleTraversalLocked(false);
}
@@ -2880,15 +2881,14 @@
}
}
- class DisplayFoldListener extends IDisplayFoldListener.Stub {
+ /**
+ * Listens to changes in device state and reports the state to LogicalDisplayMapper.
+ */
+ class DeviceStateListener implements DeviceStateManager.DeviceStateListener {
@Override
- public void onDisplayFoldChanged(int displayId, boolean folded) {
- // TODO: multi-display - IDisplayFoldListener callback only really works for the
- // Display.DEFAULT_DISPLAY.
- if (displayId == Display.DEFAULT_DISPLAY) {
- synchronized (mSyncRoot) {
- mLogicalDisplayMapper.setDeviceFoldedLocked(folded);
- }
+ public void onDeviceStateChanged(int deviceState) {
+ synchronized (mSyncRoot) {
+ mLogicalDisplayMapper.setDeviceStateLocked(deviceState);
}
}
};
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index a127858..bb2fbed 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -103,6 +103,7 @@
private final DisplayDeviceRepository mDisplayDeviceRepo;
private final Listener mListener;
+ private final int mFoldedDeviceState;
LogicalDisplayMapper(Context context, DisplayDeviceRepository repo, Listener listener) {
mDisplayDeviceRepo = repo;
@@ -110,6 +111,9 @@
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
mDisplayDeviceRepo.addListener(this);
+ mFoldedDeviceState = context.getResources().getInteger(
+ com.android.internal.R.integer.config_foldedDeviceState);
+
loadFoldedDisplayConfig(context);
}
@@ -211,6 +215,10 @@
}
}
+ void setDeviceStateLocked(int state) {
+ setDeviceFoldedLocked(state == mFoldedDeviceState);
+ }
+
void setDeviceFoldedLocked(boolean isFolded) {
mIsFolded = isFolded;
if (mIsFoldedOverride != null) {
diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
index 521ce69..633c0c4 100644
--- a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
+++ b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
@@ -20,15 +20,28 @@
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Typeface;
+import android.graphics.fonts.FontFamily;
+import android.graphics.fonts.FontFileUtil;
+import android.graphics.fonts.SystemFonts;
import android.os.SharedMemory;
import android.system.ErrnoException;
+import android.text.FontConfig;
+import android.util.Pair;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.NioUtils;
+import java.nio.channels.FileChannel;
+import java.util.HashMap;
+import java.util.Map;
/** A service for managing system fonts. */
// TODO(b/173619554): Add API to update fonts.
@@ -36,6 +49,10 @@
private static final String TAG = "FontManagerService";
+ // TODO: make this a DeviceConfig flag.
+ private static final boolean ENABLE_FONT_UPDATES = false;
+ private static final String FONT_FILES_DIR = "/data/fonts/files";
+
/** Class to manage FontManagerService's lifecycle. */
public static final class Lifecycle extends SystemService {
private final FontManagerService mService;
@@ -58,10 +75,37 @@
}
}
- @GuardedBy("this")
+ private static class OtfFontFileParser implements UpdatableFontDir.FontFileParser {
+ @Override
+ public long getVersion(File file) throws IOException {
+ ByteBuffer buffer = mmap(file);
+ try {
+ return FontFileUtil.getRevision(buffer, 0);
+ } finally {
+ NioUtils.freeDirectBuffer(buffer);
+ }
+ }
+
+ private static ByteBuffer mmap(File file) throws IOException {
+ try (FileInputStream in = new FileInputStream(file)) {
+ FileChannel fileChannel = in.getChannel();
+ return fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size());
+ }
+ }
+ }
+
+ @Nullable
+ private final UpdatableFontDir mUpdatableFontDir;
+
+ @GuardedBy("FontManagerService.this")
@Nullable
private SharedMemory mSerializedSystemFontMap = null;
+ private FontManagerService() {
+ mUpdatableFontDir = ENABLE_FONT_UPDATES
+ ? new UpdatableFontDir(new File(FONT_FILES_DIR), new OtfFontFileParser()) : null;
+ }
+
@Nullable
private SharedMemory getSerializedSystemFontMap() {
if (!Typeface.ENABLE_LAZY_TYPEFACE_INITIALIZATION) {
@@ -77,7 +121,19 @@
@Nullable
private SharedMemory createSerializedSystemFontMapLocked() {
- // TODO(b/173619554): use updated fonts.
+ if (mUpdatableFontDir != null) {
+ HashMap<String, Typeface> systemFontMap = new HashMap<>();
+ Map<String, File> fontFileMap = mUpdatableFontDir.getFontFileMap();
+ Pair<FontConfig.Alias[], Map<String, FontFamily[]>> pair =
+ SystemFonts.initializeSystemFonts(fontFileMap);
+ Typeface.initSystemDefaultTypefaces(systemFontMap, pair.second, pair.first);
+ try {
+ return Typeface.serializeFontMap(systemFontMap);
+ } catch (IOException | ErrnoException e) {
+ Slog.w(TAG, "Failed to serialize updatable font map. "
+ + "Retrying with system image fonts.", e);
+ }
+ }
try {
return Typeface.serializeFontMap(Typeface.getSystemFontMap());
} catch (IOException | ErrnoException e) {
@@ -85,4 +141,19 @@
}
return null;
}
+
+ private boolean installFontFile(String name, FileDescriptor fd) {
+ if (mUpdatableFontDir == null) return false;
+ synchronized (FontManagerService.this) {
+ try {
+ mUpdatableFontDir.installFontFile(name, fd);
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to install font file: " + name, e);
+ return false;
+ }
+ // Create updated font map in the next getSerializedSystemFontMap() call.
+ mSerializedSystemFontMap = null;
+ return true;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
new file mode 100644
index 0000000..7306471
--- /dev/null
+++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.graphics.fonts;
+
+import android.os.FileUtils;
+import android.util.Base64;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.security.SecureRandom;
+import java.util.HashMap;
+import java.util.Map;
+
+final class UpdatableFontDir {
+
+ private static final String TAG = "UpdatableFontDir";
+ private static final String RANDOM_DIR_PREFIX = "~~";
+
+ /** Interface to mock font file access in tests. */
+ interface FontFileParser {
+ long getVersion(File file) throws IOException;
+ }
+
+ /** Data class to hold font file path and version. */
+ static final class FontFileInfo {
+ final File mFile;
+ final long mVersion;
+
+ FontFileInfo(File file, long version) {
+ mFile = file;
+ mVersion = version;
+ }
+ }
+
+ /**
+ * Root directory for storing updated font files. Each font file is stored in a unique random
+ * dir. The font file path would be {@code mFilesDir/~~{randomStr}/{fontFileName}}.
+ */
+ private final File mFilesDir;
+ private final FontFileParser mParser;
+ @GuardedBy("UpdatableFontDir.this")
+ private final Map<String, FontFileInfo> mFontFileInfoMap = new HashMap<>();
+
+ UpdatableFontDir(File filesDir, FontFileParser parser) {
+ mFilesDir = filesDir;
+ mParser = parser;
+ loadFontFileMap();
+ }
+
+ private void loadFontFileMap() {
+ synchronized (UpdatableFontDir.this) {
+ mFontFileInfoMap.clear();
+ File[] dirs = mFilesDir.listFiles();
+ if (dirs == null) return;
+ for (File dir : dirs) {
+ if (!dir.getName().startsWith(RANDOM_DIR_PREFIX)) continue;
+ File[] files = dir.listFiles();
+ if (files == null || files.length != 1) continue;
+ addFileToMapLocked(files[0], true);
+ }
+ }
+ }
+
+ void installFontFile(String name, FileDescriptor fd) throws IOException {
+ // TODO: Validate name.
+ synchronized (UpdatableFontDir.this) {
+ // TODO: proper error handling
+ File newDir = getRandomDir(mFilesDir);
+ if (!newDir.mkdir()) {
+ throw new IOException("Failed to create a new dir");
+ }
+ File newFontFile = new File(newDir, name);
+ try (FileOutputStream out = new FileOutputStream(newFontFile)) {
+ FileUtils.copy(fd, out.getFD());
+ }
+ addFileToMapLocked(newFontFile, false);
+ }
+ }
+
+ /**
+ * Given {@code parent}, returns {@code parent/~~[randomStr]}.
+ * Makes sure that {@code parent/~~[randomStr]} directory doesn't exist.
+ * Notice that this method doesn't actually create any directory.
+ */
+ private static File getRandomDir(File parent) {
+ SecureRandom random = new SecureRandom();
+ byte[] bytes = new byte[16];
+ File dir;
+ do {
+ random.nextBytes(bytes);
+ String dirName = RANDOM_DIR_PREFIX
+ + Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_WRAP);
+ dir = new File(parent, dirName);
+ } while (dir.exists());
+ return dir;
+ }
+
+ private void addFileToMapLocked(File file, boolean deleteOldFile) {
+ final long version;
+ try {
+ version = mParser.getVersion(file);
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to read font file", e);
+ return;
+ }
+ if (version == -1) {
+ Slog.e(TAG, "Invalid font file");
+ return;
+ }
+ FontFileInfo info = mFontFileInfoMap.get(file.getName());
+ if (info == null) {
+ // TODO: check version of font in /system/fonts and /product/fonts
+ mFontFileInfoMap.put(file.getName(), new FontFileInfo(file, version));
+ } else if (info.mVersion < version) {
+ if (deleteOldFile) {
+ FileUtils.deleteContentsAndDir(info.mFile.getParentFile());
+ }
+ mFontFileInfoMap.put(file.getName(), new FontFileInfo(file, version));
+ }
+ }
+
+ Map<String, File> getFontFileMap() {
+ Map<String, File> map = new HashMap<>();
+ synchronized (UpdatableFontDir.this) {
+ for (Map.Entry<String, FontFileInfo> entry : mFontFileInfoMap.entrySet()) {
+ map.put(entry.getKey(), entry.getValue().mFile);
+ }
+ }
+ return map;
+ }
+}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index a207a96..3e0d040 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -2059,8 +2059,7 @@
@Override // Binder call
public InputSensorInfo[] getSensorList(int deviceId) {
- InputSensorInfo[] sensors = nativeGetSensorList(mPtr, deviceId);
- return sensors;
+ return nativeGetSensorList(mPtr, deviceId);
}
@Override // Binder call
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index e8052289..83b6eca 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -807,22 +807,7 @@
@Override
public LocationTime getGnssTimeMillis() {
- synchronized (mLock) {
- LocationProviderManager gpsManager = getLocationProviderManager(GPS_PROVIDER);
- if (gpsManager == null) {
- return null;
- }
-
- Location location = gpsManager.getLastLocationUnsafe(UserHandle.USER_ALL,
- PERMISSION_FINE, false, Long.MAX_VALUE);
- if (location == null) {
- return null;
- }
-
- long currentNanos = SystemClock.elapsedRealtimeNanos();
- long deltaMs = NANOSECONDS.toMillis(location.getElapsedRealtimeAgeNanos(currentNanos));
- return new LocationTime(location.getTime() + deltaMs, currentNanos);
- }
+ return mLocalService.getGnssTimeMillis();
}
@Override
@@ -1292,6 +1277,25 @@
mGnssManagerService.sendNiResponse(notifId, userResponse);
}
}
+
+ @Override
+ public @Nullable LocationTime getGnssTimeMillis() {
+ LocationProviderManager gpsManager = getLocationProviderManager(GPS_PROVIDER);
+ if (gpsManager == null) {
+ return null;
+ }
+
+ Location location = gpsManager.getLastLocationUnsafe(UserHandle.USER_ALL,
+ PERMISSION_FINE, false, Long.MAX_VALUE);
+ if (location == null) {
+ return null;
+ }
+
+ long currentNanos = SystemClock.elapsedRealtimeNanos();
+ long deltaMs = NANOSECONDS.toMillis(
+ location.getElapsedRealtimeAgeNanos(currentNanos));
+ return new LocationTime(location.getTime() + deltaMs, currentNanos);
+ }
}
private static class SystemInjector implements Injector {
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index 63a42f8..dc1a26a 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
+import android.hardware.SensorPrivacyManager;
import android.hardware.contexthub.V1_0.AsyncEventType;
import android.hardware.contexthub.V1_0.ContextHub;
import android.hardware.contexthub.V1_0.ContextHubMsg;
@@ -117,6 +118,9 @@
// True if WiFi is available for the Context Hub
private boolean mIsWifiAvailable = false;
+ // True if audio is disabled for the ContextHub
+ private boolean mIsAudioDisabled = false;
+
// Lock object for sendWifiSettingUpdate()
private final Object mSendWifiSettingUpdateLock = new Object();
@@ -256,6 +260,21 @@
}
}, UserHandle.USER_ALL);
}
+
+ if (mContextHubWrapper.supportsMicrophoneDisableSettingNotifications()) {
+ sendMicrophoneDisableSettingUpdate();
+
+ SensorPrivacyManager.OnSensorPrivacyChangedListener listener =
+ new SensorPrivacyManager.OnSensorPrivacyChangedListener() {
+ @Override
+ public void onSensorPrivacyChanged(boolean enabled) {
+ sendMicrophoneDisableSettingUpdate();
+ }
+ };
+ SensorPrivacyManager manager = SensorPrivacyManager.getInstance(mContext);
+ manager.addSensorPrivacyListener(
+ SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE, listener);
+ }
}
/**
@@ -999,6 +1018,21 @@
mContextHubWrapper.onAirplaneModeSettingChanged(enabled);
}
+ /**
+ * Obtains the latest microphone disable setting value and notifies the
+ * Context Hub.
+ */
+ private void sendMicrophoneDisableSettingUpdate() {
+ SensorPrivacyManager manager = SensorPrivacyManager.getInstance(mContext);
+ boolean disabled = manager.isIndividualSensorPrivacyEnabled(
+ SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE);
+ if (mIsAudioDisabled != disabled) {
+ mIsAudioDisabled = disabled;
+ mContextHubWrapper.onMicrophoneDisableSettingChanged(disabled);
+ }
+ }
+
+
private String getCallingPackageName() {
return mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
}
diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
index 4242d72..c11e289 100644
--- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
+++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
@@ -129,6 +129,18 @@
*/
public abstract void onAirplaneModeSettingChanged(boolean enabled);
+ /**
+ * @return True if this version of the Contexthub HAL supports microphone
+ * disable setting notifications.
+ */
+ public abstract boolean supportsMicrophoneDisableSettingNotifications();
+
+ /**
+ * Notifies the Contexthub implementation of a microphone disable setting
+ * change.
+ */
+ public abstract void onMicrophoneDisableSettingChanged(boolean enabled);
+
private static class ContextHubWrapperV1_0 extends IContextHubWrapper {
private android.hardware.contexthub.V1_0.IContexthub mHub;
@@ -152,6 +164,10 @@
return false;
}
+ public boolean supportsMicrophoneDisableSettingNotifications() {
+ return false;
+ }
+
public void onLocationSettingChanged(boolean enabled) {
}
@@ -160,6 +176,9 @@
public void onAirplaneModeSettingChanged(boolean enabled) {
}
+
+ public void onMicrophoneDisableSettingChanged(boolean enabled) {
+ }
}
private static class ContextHubWrapperV1_1 extends IContextHubWrapper {
@@ -185,6 +204,10 @@
return false;
}
+ public boolean supportsMicrophoneDisableSettingNotifications() {
+ return false;
+ }
+
public void onLocationSettingChanged(boolean enabled) {
try {
mHub.onSettingChanged(Setting.LOCATION,
@@ -199,6 +222,9 @@
public void onAirplaneModeSettingChanged(boolean enabled) {
}
+
+ public void onMicrophoneDisableSettingChanged(boolean enabled) {
+ }
}
private static class ContextHubWrapperV1_2 extends IContextHubWrapper {
@@ -224,6 +250,10 @@
return true;
}
+ public boolean supportsMicrophoneDisableSettingNotifications() {
+ return true;
+ }
+
public void onLocationSettingChanged(boolean enabled) {
sendSettingChanged(Setting.LOCATION,
enabled ? SettingValue.ENABLED : SettingValue.DISABLED);
@@ -239,6 +269,11 @@
enabled ? SettingValue.ENABLED : SettingValue.DISABLED);
}
+ public void onMicrophoneDisableSettingChanged(boolean enabled) {
+ sendSettingChanged(android.hardware.contexthub.V1_2.Setting.GLOBAL_MIC_DISABLE,
+ enabled ? SettingValue.ENABLED : SettingValue.DISABLED);
+ }
+
private void sendSettingChanged(byte setting, byte newValue) {
try {
mHub.onSettingChanged_1_2(setting, newValue);
diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
index 92957aa..b6695c2 100644
--- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -193,7 +193,9 @@
IGnssMeasurementsListener listener, String packageName,
@Nullable String attributionTag) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
-
+ if (request.isCorrelationVectorOutputsEnabled()) {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
+ }
CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag);
mGnssMeasurementsProvider.addListener(request, identity, listener);
}
diff --git a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
index b623e27..305bc9b 100644
--- a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
@@ -118,7 +118,8 @@
@Override
protected boolean registerWithService(GnssMeasurementRequest request,
Collection<GnssListenerRegistration> registrations) {
- if (mGnssNative.startMeasurementCollection(request.isFullTracking())) {
+ if (mGnssNative.startMeasurementCollection(request.isFullTracking(),
+ request.isCorrelationVectorOutputsEnabled())) {
if (D) {
Log.d(TAG, "starting gnss measurements (" + request + ")");
}
@@ -160,18 +161,26 @@
protected GnssMeasurementRequest mergeRegistrations(
Collection<GnssListenerRegistration> registrations) {
boolean fullTracking = false;
+ boolean enableCorrVecOutputs = false;
+
if (mSettingsHelper.isGnssMeasurementsFullTrackingEnabled()) {
fullTracking = true;
- } else {
- for (GnssListenerRegistration registration : registrations) {
- if (registration.getRequest().isFullTracking()) {
- fullTracking = true;
- break;
- }
+ }
+
+ for (GnssListenerRegistration registration : registrations) {
+ GnssMeasurementRequest request = registration.getRequest();
+ if (request.isFullTracking()) {
+ fullTracking = true;
+ }
+ if (request.isCorrelationVectorOutputsEnabled()) {
+ enableCorrVecOutputs = true;
}
}
- return new GnssMeasurementRequest.Builder().setFullTracking(fullTracking).build();
+ return new GnssMeasurementRequest.Builder()
+ .setFullTracking(fullTracking)
+ .setCorrelationVectorOutputsEnabled(enableCorrVecOutputs)
+ .build();
}
@Override
diff --git a/services/core/java/com/android/server/location/gnss/hal/GnssNative.java b/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
index 402e84b..7e2f089 100644
--- a/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
+++ b/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
@@ -733,9 +733,10 @@
/**
* Starts measurement collection.
*/
- public boolean startMeasurementCollection(boolean enableFullTracking) {
+ public boolean startMeasurementCollection(boolean enableFullTracking,
+ boolean enableCorrVecOutputs) {
Preconditions.checkState(mRegistered);
- return mGnssHal.startMeasurementCollection(enableFullTracking);
+ return mGnssHal.startMeasurementCollection(enableFullTracking, enableCorrVecOutputs);
}
/**
@@ -1274,8 +1275,9 @@
return native_is_measurement_supported();
}
- protected boolean startMeasurementCollection(boolean enableFullTracking) {
- return native_start_measurement_collection(enableFullTracking);
+ protected boolean startMeasurementCollection(boolean enableFullTracking,
+ boolean enableCorrVecOutputs) {
+ return native_start_measurement_collection(enableFullTracking, enableCorrVecOutputs);
}
protected boolean stopMeasurementCollection() {
@@ -1438,7 +1440,8 @@
private static native boolean native_is_measurement_supported();
- private static native boolean native_start_measurement_collection(boolean enableFullTracking);
+ private static native boolean native_start_measurement_collection(boolean enableFullTracking,
+ boolean enableCorrVecOutputs);
private static native boolean native_stop_measurement_collection();
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index 5d0544b..7dd961a 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -753,8 +753,9 @@
pw.increaseIndent();
File[] files = userPath.listFiles();
if (files != null) {
+ Arrays.sort(files);
for (File file : files) {
- pw.println(String.format("%4d %s %s", file.length(),
+ pw.println(String.format("%6d %s %s", file.length(),
LockSettingsService.timestampToString(file.lastModified()),
file.getName()));
}
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
index 289290b..fbec915 100644
--- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
@@ -224,6 +224,10 @@
for (UserInfo user : rebootEscrowUsers) {
allUsersUnlocked &= restoreRebootEscrowForUser(user.id, escrowKey, kk);
}
+
+ // Clear the old key in keystore. A new key will be generated by new RoR requests.
+ mKeyStoreManager.clearKeyStoreEncryptionKey();
+
onEscrowRestoreComplete(allUsersUnlocked);
}
@@ -273,9 +277,6 @@
} catch (IOException e) {
Slog.w(TAG, "Could not load reboot escrow data for user " + userId, e);
return false;
- } finally {
- // Clear the old key in keystore. A new key will be generated by new RoR requests.
- mKeyStoreManager.clearKeyStoreEncryptionKey();
}
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 1b27ef4..c0381e4 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -109,6 +109,10 @@
private static final int LONG_PRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout()
+ /* Buffer for delayed delivery of key event */ 50;
private static final int MULTI_TAP_TIMEOUT = ViewConfiguration.getMultiPressTimeout();
+ /**
+ * Copied from Settings.System.MEDIA_BUTTON_RECEIVER
+ */
+ private static final String MEDIA_BUTTON_RECEIVER = "media_button_receiver";
private final Context mContext;
private final SessionManagerImpl mSessionManagerImpl;
@@ -131,7 +135,6 @@
private KeyguardManager mKeyguardManager;
private AudioManager mAudioManager;
- private ContentResolver mContentResolver;
private boolean mHasFeatureLeanback;
// The FullUserRecord of the current users. (i.e. The foreground user that isn't a profile)
@@ -183,7 +186,6 @@
}
}
}, null /* handler */);
- mContentResolver = mContext.getContentResolver();
mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LEANBACK);
@@ -831,6 +833,7 @@
*/
final class FullUserRecord implements MediaSessionStack.OnMediaButtonSessionChangedListener {
private final int mFullUserId;
+ private final ContentResolver mContentResolver;
private final MediaSessionStack mPriorityStack;
private final HashMap<IBinder, OnMediaKeyEventDispatchedListenerRecord>
mOnMediaKeyEventDispatchedListeners = new HashMap<>();
@@ -848,10 +851,12 @@
FullUserRecord(int fullUserId) {
mFullUserId = fullUserId;
+ mContentResolver = mContext.createContextAsUser(UserHandle.of(mFullUserId), 0)
+ .getContentResolver();
mPriorityStack = new MediaSessionStack(mAudioPlayerStateMonitor, this);
// Restore the remembered media button receiver before the boot.
- String mediaButtonReceiverInfo = Settings.Secure.getStringForUser(mContentResolver,
- Settings.System.MEDIA_BUTTON_RECEIVER, mFullUserId);
+ String mediaButtonReceiverInfo = Settings.Secure.getString(mContentResolver,
+ MEDIA_BUTTON_RECEIVER);
mLastMediaButtonReceiverHolder =
MediaButtonReceiverHolder.unflattenFromString(
mContext, mediaButtonReceiverInfo);
@@ -970,10 +975,9 @@
mLastMediaButtonReceiverHolder = sessionRecord.getMediaButtonReceiver();
String mediaButtonReceiverInfo = (mLastMediaButtonReceiverHolder == null)
? "" : mLastMediaButtonReceiverHolder.flattenToString();
- Settings.Secure.putStringForUser(mContentResolver,
- Settings.System.MEDIA_BUTTON_RECEIVER,
- mediaButtonReceiverInfo,
- mFullUserId);
+ Settings.Secure.putString(mContentResolver,
+ MEDIA_BUTTON_RECEIVER,
+ mediaButtonReceiverInfo);
}
private void pushAddressedPlayerChangedLocked(
diff --git a/services/core/java/com/android/server/media/metrics/PlaybackMetricsManagerService.java b/services/core/java/com/android/server/media/metrics/PlaybackMetricsManagerService.java
index 9c68349..2a3cc90 100644
--- a/services/core/java/com/android/server/media/metrics/PlaybackMetricsManagerService.java
+++ b/services/core/java/com/android/server/media/metrics/PlaybackMetricsManagerService.java
@@ -18,8 +18,14 @@
import android.content.Context;
import android.media.metrics.IPlaybackMetricsManager;
+import android.media.metrics.NetworkEvent;
+import android.media.metrics.PlaybackErrorEvent;
import android.media.metrics.PlaybackMetrics;
+import android.media.metrics.PlaybackStateEvent;
+import android.os.Binder;
import android.util.Base64;
+import android.util.StatsEvent;
+import android.util.StatsLog;
import com.android.server.SystemService;
@@ -50,6 +56,33 @@
private final class BinderService extends IPlaybackMetricsManager.Stub {
@Override
public void reportPlaybackMetrics(String sessionId, PlaybackMetrics metrics, int userId) {
+ StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(320)
+ .writeInt(Binder.getCallingUid())
+ .writeString(sessionId)
+ .writeLong(metrics.getMediaDurationMillis())
+ .writeInt(metrics.getStreamSource())
+ .writeInt(metrics.getStreamType())
+ .writeInt(metrics.getPlaybackType())
+ .writeInt(metrics.getDrmType())
+ .writeInt(metrics.getContentType())
+ .writeString(metrics.getPlayerName())
+ .writeString(metrics.getPlayerVersion())
+ .writeByteArray(new byte[0]) // TODO: write experiments proto
+ .writeInt(metrics.getVideoFramesPlayed())
+ .writeInt(metrics.getVideoFramesDropped())
+ .writeInt(metrics.getAudioUnderrunCount())
+ .writeLong(metrics.getNetworkBytesRead())
+ .writeLong(metrics.getLocalBytesRead())
+ .writeLong(metrics.getNetworkTransferDurationMillis())
+ .usePooledBuffer()
+ .build();
+ StatsLog.write(statsEvent);
+ }
+
+ @Override
+ public void reportPlaybackStateEvent(
+ String sessionId, PlaybackStateEvent event, int userId) {
// TODO: log it to statsd
}
@@ -60,5 +93,32 @@
String id = Base64.encodeToString(byteId, Base64.DEFAULT);
return id;
}
+
+ @Override
+ public void reportPlaybackErrorEvent(
+ String sessionId, PlaybackErrorEvent event, int userId) {
+ StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(323)
+ .writeString(sessionId)
+ .writeString(event.getExceptionStack())
+ .writeInt(event.getErrorCode())
+ .writeInt(event.getSubErrorCode())
+ .writeLong(event.getTimeSincePlaybackCreatedMillis())
+ .usePooledBuffer()
+ .build();
+ StatsLog.write(statsEvent);
+ }
+
+ public void reportNetworkEvent(
+ String sessionId, NetworkEvent event, int userId) {
+ StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(321)
+ .writeString(sessionId)
+ .writeInt(event.getType())
+ .writeLong(event.getTimeSincePlaybackCreatedMillis())
+ .usePooledBuffer()
+ .build();
+ StatsLog.write(statsEvent);
+ }
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ed7e5fb..61b218c 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -128,6 +128,7 @@
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.AutomaticZenRule;
+import android.app.BroadcastOptions;
import android.app.IActivityManager;
import android.app.INotificationManager;
import android.app.ITransientNotification;
@@ -5960,7 +5961,9 @@
PendingIntent pendingIntent = notification.allPendingIntents.valueAt(i);
if (pendingIntent != null) {
am.setPendingIntentWhitelistDuration(pendingIntent.getTarget(),
- ALLOWLIST_TOKEN, duration);
+ ALLOWLIST_TOKEN, duration,
+ BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED
+ );
am.setPendingIntentAllowBgActivityStarts(pendingIntent.getTarget(),
ALLOWLIST_TOKEN, (FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER
| FLAG_SERVICE_SENDER));
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index 01eeb31..ef0f0ee 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -21,6 +21,7 @@
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.BugreportParams;
@@ -31,6 +32,7 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserManager;
+import android.telephony.TelephonyManager;
import android.util.ArraySet;
import android.util.Slog;
@@ -53,11 +55,13 @@
private final Object mLock = new Object();
private final Context mContext;
private final AppOpsManager mAppOps;
+ private final TelephonyManager mTelephonyManager;
private final ArraySet<String> mBugreportWhitelistedPackages;
BugreportManagerServiceImpl(Context context) {
mContext = context;
- mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ mAppOps = context.getSystemService(AppOpsManager.class);
+ mTelephonyManager = context.getSystemService(TelephonyManager.class);
mBugreportWhitelistedPackages =
SystemConfig.getInstance().getBugreportWhitelistedPackages();
}
@@ -67,11 +71,14 @@
public void startBugreport(int callingUidUnused, String callingPackage,
FileDescriptor bugreportFd, FileDescriptor screenshotFd,
int bugreportMode, IDumpstateListener listener, boolean isScreenshotRequested) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "startBugreport");
Objects.requireNonNull(callingPackage);
Objects.requireNonNull(bugreportFd);
Objects.requireNonNull(listener);
validateBugreportMode(bugreportMode);
+
+ int callingUid = Binder.getCallingUid();
+ enforcePermission(callingPackage, callingUid, bugreportMode
+ == BugreportParams.BUGREPORT_MODE_TELEPHONY /* checkCarrierPrivileges */);
final long identity = Binder.clearCallingIdentity();
try {
ensureIsPrimaryUser();
@@ -79,13 +86,6 @@
Binder.restoreCallingIdentity(identity);
}
- int callingUid = Binder.getCallingUid();
- mAppOps.checkPackage(callingUid, callingPackage);
-
- if (!mBugreportWhitelistedPackages.contains(callingPackage)) {
- throw new SecurityException(
- callingPackage + " is not whitelisted to use Bugreport API");
- }
synchronized (mLock) {
startBugreportLocked(callingUid, callingPackage, bugreportFd, screenshotFd,
bugreportMode, listener, isScreenshotRequested);
@@ -93,12 +93,10 @@
}
@Override
- @RequiresPermission(android.Manifest.permission.DUMP)
+ @RequiresPermission(android.Manifest.permission.DUMP) // or carrier privileges
public void cancelBugreport(int callingUidUnused, String callingPackage) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
- "cancelBugreport");
int callingUid = Binder.getCallingUid();
- mAppOps.checkPackage(callingUid, callingPackage);
+ enforcePermission(callingPackage, callingUid, true /* checkCarrierPrivileges */);
synchronized (mLock) {
IDumpstate ds = getDumpstateBinderServiceLocked();
@@ -134,6 +132,34 @@
}
}
+ private void enforcePermission(
+ String callingPackage, int callingUid, boolean checkCarrierPrivileges) {
+ mAppOps.checkPackage(callingUid, callingPackage);
+
+ // To gain access through the DUMP permission, the OEM has to allow this package explicitly
+ // via sysconfig and privileged permissions.
+ if (mBugreportWhitelistedPackages.contains(callingPackage)
+ && mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ // For carrier privileges, this can include user-installed apps. This is essentially a
+ // function of the current active SIM(s) in the device to let carrier apps through.
+ if (checkCarrierPrivileges
+ && mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ return;
+ }
+
+ String message =
+ callingPackage
+ + " does not hold the DUMP permission or is not bugreport-whitelisted "
+ + (checkCarrierPrivileges ? "and does not have carrier privileges " : "")
+ + "to request a bugreport";
+ Slog.w(TAG, message);
+ throw new SecurityException(message);
+ }
+
/**
* Validates that the current user is the primary user.
*
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 608580c..b65fc73 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -331,8 +331,6 @@
private boolean mCommitted = false;
@GuardedBy("mLock")
private boolean mRelinquished = false;
- @GuardedBy("mLock")
- private boolean mDestroyed = false;
/** Permissions have been accepted by the user (see {@link #setPermissionsResult}) */
@GuardedBy("mLock")
@@ -762,8 +760,13 @@
@GuardedBy("mLock")
private boolean mVerityFound;
- @GuardedBy("mLock")
- private boolean mDataLoaderFinished = false;
+ /**
+ * Both flags should be guarded with mLock whenever changes need to be in lockstep.
+ * Ok to check without mLock in case the proper check is done later, e.g. status callbacks
+ * for DataLoaders with deferred processing.
+ */
+ private volatile boolean mDestroyed = false;
+ private volatile boolean mDataLoaderFinished = false;
@GuardedBy("mLock")
private IncrementalFileStorages mIncrementalFileStorages;
@@ -3562,19 +3565,15 @@
return;
}
- synchronized (mLock) {
- if (mDestroyed || mDataLoaderFinished) {
- // No need to worry about post installation
- return;
- }
+ if (mDestroyed || mDataLoaderFinished) {
+ // No need to worry about post installation
+ return;
}
try {
IDataLoader dataLoader = dataLoaderManager.getDataLoader(dataLoaderId);
if (dataLoader == null) {
- synchronized (mLock) {
- mDataLoaderFinished = true;
- }
+ mDataLoaderFinished = true;
dispatchSessionValidationFailure(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"Failure to obtain data loader");
return;
@@ -3607,9 +3606,7 @@
break;
}
case IDataLoaderStatusListener.DATA_LOADER_IMAGE_READY: {
- synchronized (mLock) {
- mDataLoaderFinished = true;
- }
+ mDataLoaderFinished = true;
if (hasParentSessionId()) {
mSessionProvider.getSession(
getParentSessionId()).dispatchSessionSealed();
@@ -3622,9 +3619,7 @@
break;
}
case IDataLoaderStatusListener.DATA_LOADER_IMAGE_NOT_READY: {
- synchronized (mLock) {
- mDataLoaderFinished = true;
- }
+ mDataLoaderFinished = true;
dispatchSessionValidationFailure(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"Failed to prepare image.");
if (manualStartAndDestroy) {
@@ -3643,9 +3638,7 @@
break;
}
case IDataLoaderStatusListener.DATA_LOADER_UNRECOVERABLE:
- synchronized (mLock) {
- mDataLoaderFinished = true;
- }
+ mDataLoaderFinished = true;
dispatchSessionValidationFailure(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"DataLoader reported unrecoverable failure.");
break;
@@ -3683,11 +3676,9 @@
final IStorageHealthListener healthListener = new IStorageHealthListener.Stub() {
@Override
public void onHealthStatus(int storageId, int status) {
- synchronized (mLock) {
- if (mDestroyed || mDataLoaderFinished) {
- // No need to worry about post installation
- return;
- }
+ if (mDestroyed || mDataLoaderFinished) {
+ // No need to worry about post installation
+ return;
}
switch (status) {
@@ -3702,9 +3693,7 @@
// fallthrough
case IStorageHealthListener.HEALTH_STATUS_UNHEALTHY:
// Even ADB installation can't wait for missing pages for too long.
- synchronized (mLock) {
- mDataLoaderFinished = true;
- }
+ mDataLoaderFinished = true;
dispatchSessionValidationFailure(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"Image is missing pages required for installation.");
break;
diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
deleted file mode 100644
index b95c5efc..0000000
--- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.policy.role;
-
-import android.annotation.NonNull;
-import android.annotation.UserIdInt;
-import android.app.role.RoleManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
-import android.content.pm.ResolveInfo;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Slog;
-
-import com.android.internal.R;
-import com.android.internal.telephony.SmsApplication;
-import com.android.internal.util.CollectionUtils;
-import com.android.server.LocalServices;
-import com.android.server.role.LegacyRoleHolderProvider;
-import com.android.server.role.RoleManagerService;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Logic to retrieve the various legacy(pre-Q) equivalents of role holders.
- *
- * Unlike {@link RoleManagerService} this is meant to be pretty high-level to allow for depending
- * on all kinds of various systems that are historically involved in legacy role resolution,
- * e.g. {@link SmsApplication}
- *
- * @see RoleManagerService#migrateRoleIfNecessary
- */
-public class LegacyRoleResolutionPolicy implements LegacyRoleHolderProvider {
-
- private static final boolean DEBUG = false;
- private static final String LOG_TAG = "LegacyRoleResolutionPol";
-
- @NonNull
- private final Context mContext;
-
- public LegacyRoleResolutionPolicy(@NonNull Context context) {
- mContext = context;
- }
-
- @NonNull
- @Override
- public List<String> getLegacyRoleHolders(@NonNull String roleName, @UserIdInt int userId) {
- switch (roleName) {
- case RoleManager.ROLE_ASSISTANT: {
- String packageName;
- String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
- Settings.Secure.ASSISTANT, userId);
- // AssistUtils was using the default assistant app if Settings.Secure.ASSISTANT is
- // null, while only an empty string means user selected "None".
- if (setting != null) {
- if (!setting.isEmpty()) {
- ComponentName componentName = ComponentName.unflattenFromString(setting);
- packageName = componentName != null ? componentName.getPackageName() : null;
- } else {
- packageName = null;
- }
- } else if (mContext.getPackageManager().isDeviceUpgrading()) {
- String defaultAssistant = mContext.getString(R.string.config_defaultAssistant);
- packageName = !TextUtils.isEmpty(defaultAssistant) ? defaultAssistant : null;
- } else {
- packageName = null;
- }
- return CollectionUtils.singletonOrEmpty(packageName);
- }
- case RoleManager.ROLE_BROWSER: {
- PackageManagerInternal packageManagerInternal = LocalServices.getService(
- PackageManagerInternal.class);
- String packageName = packageManagerInternal.removeLegacyDefaultBrowserPackageName(
- userId);
- return CollectionUtils.singletonOrEmpty(packageName);
- }
- case RoleManager.ROLE_DIALER: {
- String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
- Settings.Secure.DIALER_DEFAULT_APPLICATION, userId);
- String packageName;
- if (!TextUtils.isEmpty(setting)) {
- packageName = setting;
- } else if (mContext.getPackageManager().isDeviceUpgrading()) {
- // DefaultDialerManager was using the default dialer app if
- // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid.
- // TelecomManager.getSystemDialerPackage() won't work because it might not
- // be ready.
- packageName = mContext.getString(R.string.config_defaultDialer);
- } else {
- packageName = null;
- }
- return CollectionUtils.singletonOrEmpty(packageName);
- }
- case RoleManager.ROLE_SMS: {
- String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
- Settings.Secure.SMS_DEFAULT_APPLICATION, userId);
- String packageName;
- if (!TextUtils.isEmpty(setting)) {
- packageName = setting;
- } else if (mContext.getPackageManager().isDeviceUpgrading()) {
- // SmsApplication was using the default SMS app if
- // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid.
- packageName = mContext.getString(R.string.config_defaultSms);
- } else {
- packageName = null;
- }
- return CollectionUtils.singletonOrEmpty(packageName);
- }
- case RoleManager.ROLE_HOME: {
- PackageManager packageManager = mContext.getPackageManager();
- String packageName;
- if (packageManager.isDeviceUpgrading()) {
- ResolveInfo resolveInfo = packageManager.resolveActivityAsUser(
- new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),
- PackageManager.MATCH_DEFAULT_ONLY
- | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
- packageName = resolveInfo != null && resolveInfo.activityInfo != null
- ? resolveInfo.activityInfo.packageName : null;
- if (packageName != null && isSettingsApplication(packageName, userId)) {
- packageName = null;
- }
- } else {
- packageName = null;
- }
- return CollectionUtils.singletonOrEmpty(packageName);
- }
- case RoleManager.ROLE_EMERGENCY: {
- String defaultEmergencyApp = Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
- Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION, userId);
- return CollectionUtils.singletonOrEmpty(defaultEmergencyApp);
- }
- default: {
- Slog.e(LOG_TAG, "Don't know how to find legacy role holders for " + roleName);
- return Collections.emptyList();
- }
- }
- }
-
- private boolean isSettingsApplication(@NonNull String packageName, @UserIdInt int userId) {
- PackageManager packageManager = mContext.getPackageManager();
- ResolveInfo resolveInfo = packageManager.resolveActivityAsUser(new Intent(
- Settings.ACTION_SETTINGS), PackageManager.MATCH_DEFAULT_ONLY
- | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
- if (resolveInfo == null || resolveInfo.activityInfo == null) {
- return false;
- }
- return Objects.equals(packageName, resolveInfo.activityInfo.packageName);
- }
-}
diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleStateProviderImpl.java b/services/core/java/com/android/server/policy/role/LegacyRoleStateProviderImpl.java
new file mode 100644
index 0000000..097f332
--- /dev/null
+++ b/services/core/java/com/android/server/policy/role/LegacyRoleStateProviderImpl.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.policy.role;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.role.RoleManager;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
+import android.content.pm.ResolveInfo;
+import android.os.Environment;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.R;
+import com.android.server.LocalServices;
+import com.android.server.role.LegacyRoleStateProvider;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Implementation to provide legacy role state.
+ */
+public class LegacyRoleStateProviderImpl implements LegacyRoleStateProvider {
+ private static final String LOG_TAG = "LegacyRoleState";
+
+ private static final String ROLES_FILE_NAME = "roles.xml";
+
+ private static final String TAG_ROLES = "roles";
+ private static final String TAG_ROLE = "role";
+ private static final String TAG_HOLDER = "holder";
+ private static final String ATTRIBUTE_NAME = "name";
+
+ @NonNull
+ private final Context mContext;
+
+ public LegacyRoleStateProviderImpl(@NonNull Context context) {
+ mContext = context;
+ }
+
+ @NonNull
+ @Override
+ public Map<String, Set<String>> getLegacyRoleState(@UserIdInt int userId) {
+ Map<String, Set<String>> roles = readFile(userId);
+ if (roles == null) {
+ roles = readFromLegacySettings(userId);
+ }
+ return roles;
+ }
+
+ @Nullable
+ private Map<String, Set<String>> readFile(@UserIdInt int userId) {
+ File file = getFile(userId);
+ try (FileInputStream in = new AtomicFile(file).openRead()) {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(in, null);
+ Map<String, Set<String>> roles = parseXml(parser);
+ Slog.i(LOG_TAG, "Read legacy roles.xml successfully");
+ return roles;
+ } catch (FileNotFoundException e) {
+ Slog.i(LOG_TAG, "Legacy roles.xml not found");
+ return null;
+ } catch (XmlPullParserException | IOException e) {
+ Slog.wtf(LOG_TAG, "Failed to parse legacy roles.xml: " + file, e);
+ return null;
+ }
+ }
+
+ @NonNull
+ private Map<String, Set<String>> parseXml(@NonNull XmlPullParser parser) throws IOException,
+ XmlPullParserException {
+ int type;
+ int depth;
+ int innerDepth = parser.getDepth() + 1;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
+ if (depth > innerDepth || type != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ if (parser.getName().equals(TAG_ROLES)) {
+ return parseRoles(parser);
+ }
+ }
+
+ throw new IOException("Missing <" + TAG_ROLES + "> in roles.xml");
+ }
+
+ @NonNull
+ private Map<String, Set<String>> parseRoles(@NonNull XmlPullParser parser) throws IOException,
+ XmlPullParserException {
+ Map<String, Set<String>> roles = new ArrayMap<>();
+
+ int type;
+ int depth;
+ int innerDepth = parser.getDepth() + 1;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
+ if (depth > innerDepth || type != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ if (parser.getName().equals(TAG_ROLE)) {
+ String roleName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+ Set<String> roleHolders = parseRoleHoldersLocked(parser);
+ roles.put(roleName, roleHolders);
+ }
+ }
+
+ return roles;
+ }
+
+ @NonNull
+ private Set<String> parseRoleHoldersLocked(@NonNull XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ Set<String> roleHolders = new ArraySet<>();
+
+ int type;
+ int depth;
+ int innerDepth = parser.getDepth() + 1;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
+ if (depth > innerDepth || type != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ if (parser.getName().equals(TAG_HOLDER)) {
+ String roleHolder = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+ roleHolders.add(roleHolder);
+ }
+ }
+
+ return roleHolders;
+ }
+
+ @NonNull
+ private static File getFile(@UserIdInt int userId) {
+ return new File(Environment.getUserSystemDirectory(userId), ROLES_FILE_NAME);
+ }
+
+ @NonNull
+ private Map<String, Set<String>> readFromLegacySettings(@UserIdInt int userId) {
+ Map<String, Set<String>> roles = new ArrayMap<>();
+
+ // Assistant
+ ContentResolver contentResolver = mContext.getContentResolver();
+ String assistantSetting = Settings.Secure.getStringForUser(contentResolver,
+ Settings.Secure.ASSISTANT, userId);
+ PackageManager packageManager = mContext.getPackageManager();
+ String assistantPackageName;
+ // AssistUtils was using the default assistant app if Settings.Secure.ASSISTANT is
+ // null, while only an empty string means user selected "None".
+ if (assistantSetting != null) {
+ if (!assistantSetting.isEmpty()) {
+ ComponentName componentName = ComponentName.unflattenFromString(assistantSetting);
+ assistantPackageName = componentName != null ? componentName.getPackageName()
+ : null;
+ } else {
+ assistantPackageName = null;
+ }
+ } else if (packageManager.isDeviceUpgrading()) {
+ String defaultAssistant = mContext.getString(R.string.config_defaultAssistant);
+ assistantPackageName = !TextUtils.isEmpty(defaultAssistant) ? defaultAssistant : null;
+ } else {
+ assistantPackageName = null;
+ }
+ if (assistantPackageName != null) {
+ roles.put(RoleManager.ROLE_ASSISTANT, Collections.singleton(assistantPackageName));
+ }
+
+ // Browser
+ PackageManagerInternal packageManagerInternal = LocalServices.getService(
+ PackageManagerInternal.class);
+ String browserPackageName = packageManagerInternal.removeLegacyDefaultBrowserPackageName(
+ userId);
+ if (browserPackageName != null) {
+ roles.put(RoleManager.ROLE_BROWSER, Collections.singleton(browserPackageName));
+ }
+
+ // Dialer
+ String dialerSetting = Settings.Secure.getStringForUser(contentResolver,
+ Settings.Secure.DIALER_DEFAULT_APPLICATION, userId);
+ String dialerPackageName;
+ if (!TextUtils.isEmpty(dialerSetting)) {
+ dialerPackageName = dialerSetting;
+ } else if (packageManager.isDeviceUpgrading()) {
+ // DefaultDialerManager was using the default dialer app if
+ // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid.
+ // TelecomManager.getSystemDialerPackage() won't work because it might not
+ // be ready.
+ dialerPackageName = mContext.getString(R.string.config_defaultDialer);
+ } else {
+ dialerPackageName = null;
+ }
+ if (dialerPackageName != null) {
+ roles.put(RoleManager.ROLE_DIALER, Collections.singleton(dialerPackageName));
+ }
+
+ // SMS
+ String smsSetting = Settings.Secure.getStringForUser(contentResolver,
+ Settings.Secure.SMS_DEFAULT_APPLICATION, userId);
+ String smsPackageName;
+ if (!TextUtils.isEmpty(smsSetting)) {
+ smsPackageName = smsSetting;
+ } else if (mContext.getPackageManager().isDeviceUpgrading()) {
+ // SmsApplication was using the default SMS app if
+ // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid.
+ smsPackageName = mContext.getString(R.string.config_defaultSms);
+ } else {
+ smsPackageName = null;
+ }
+ if (smsPackageName != null) {
+ roles.put(RoleManager.ROLE_SMS, Collections.singleton(smsPackageName));
+ }
+
+ // Home
+ String homePackageName;
+ if (packageManager.isDeviceUpgrading()) {
+ ResolveInfo resolveInfo = packageManager.resolveActivityAsUser(
+ new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),
+ PackageManager.MATCH_DEFAULT_ONLY
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ homePackageName = resolveInfo != null && resolveInfo.activityInfo != null
+ ? resolveInfo.activityInfo.packageName : null;
+ if (homePackageName != null && isSettingsApplication(homePackageName, userId)) {
+ homePackageName = null;
+ }
+ } else {
+ homePackageName = null;
+ }
+ if (homePackageName != null) {
+ roles.put(RoleManager.ROLE_HOME, Collections.singleton(homePackageName));
+ }
+
+ // Emergency
+ String emergencyPackageName = Settings.Secure.getStringForUser(contentResolver,
+ Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION, userId);
+ if (emergencyPackageName != null) {
+ roles.put(RoleManager.ROLE_EMERGENCY, Collections.singleton(emergencyPackageName));
+ }
+
+ return roles;
+ }
+
+ private boolean isSettingsApplication(@NonNull String packageName, @UserIdInt int userId) {
+ PackageManager packageManager = mContext.getPackageManager();
+ ResolveInfo resolveInfo = packageManager.resolveActivityAsUser(new Intent(
+ Settings.ACTION_SETTINGS), PackageManager.MATCH_DEFAULT_ONLY
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ if (resolveInfo == null || resolveInfo.activityInfo == null) {
+ return false;
+ }
+ return Objects.equals(packageName, resolveInfo.activityInfo.packageName);
+ }
+}
diff --git a/services/core/java/com/android/server/role/LegacyRoleHolderProvider.java b/services/core/java/com/android/server/role/LegacyRoleHolderProvider.java
deleted file mode 100644
index ed0d675..0000000
--- a/services/core/java/com/android/server/role/LegacyRoleHolderProvider.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.role;
-
-import android.annotation.NonNull;
-import android.annotation.UserIdInt;
-
-import java.util.List;
-
-/**
- * A provider for migrating legacy "role"s to their actual role implementation.
- */
-//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-public interface LegacyRoleHolderProvider {
- /**
- * Get the list of holders of a legacy "role" before its actual role is introduced.
- * <p>
- * This method will only be called for the first time a role is made available in the platform.
- *
- * @param roleName the name of the role
- * @param userId the user ID
- * @return a list of holders for the given role
- */
- @NonNull
- List<String> getLegacyRoleHolders(@NonNull String roleName, @UserIdInt int userId);
-}
diff --git a/services/core/java/com/android/server/role/LegacyRoleStateProvider.java b/services/core/java/com/android/server/role/LegacyRoleStateProvider.java
new file mode 100644
index 0000000..ec4cfc1
--- /dev/null
+++ b/services/core/java/com/android/server/role/LegacyRoleStateProvider.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.role;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Provider for legacy role state.
+ * <p>
+ * The role state may come from two sources, either the different pre-role default app settings, or
+ * the pre-modularization roles.xml file stored in platform.
+ *
+ * @hide
+ */
+//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+public interface LegacyRoleStateProvider {
+ /**
+ * Get the legacy role state stored in the platform.
+ *
+ * @param userId the user ID
+ * @return a mapping of role name to its set of holders
+ */
+ @NonNull
+ Map<String, Set<String>> getLegacyRoleState(@UserIdInt int userId);
+}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 4e42f16..bc5ddd3 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -103,7 +103,7 @@
private final Object mLock = new Object();
@NonNull
- private final LegacyRoleHolderProvider mLegacyRoleHolderProvider;
+ private final LegacyRoleStateProvider mLegacyRoleStateProvider;
/**
* Maps user id to its state.
@@ -139,10 +139,10 @@
new SparseArray<>();
public RoleManagerService(@NonNull Context context,
- @NonNull LegacyRoleHolderProvider legacyRoleHolderProvider) {
+ @NonNull LegacyRoleStateProvider legacyRoleStateProvider) {
super(context);
- mLegacyRoleHolderProvider = legacyRoleHolderProvider;
+ mLegacyRoleStateProvider = legacyRoleStateProvider;
RoleControllerManager.initializeRemoteServiceComponentName(context);
@@ -241,16 +241,6 @@
return AndroidFuture.completedFuture(null);
}
- //TODO gradually add more role migrations statements here for remaining roles
- // Make sure to implement LegacyRoleResolutionPolicy#getRoleHolders
- // for a given role before adding a migration statement for it here
- maybeMigrateRole(RoleManager.ROLE_ASSISTANT, userId);
- maybeMigrateRole(RoleManager.ROLE_BROWSER, userId);
- maybeMigrateRole(RoleManager.ROLE_DIALER, userId);
- maybeMigrateRole(RoleManager.ROLE_SMS, userId);
- maybeMigrateRole(RoleManager.ROLE_EMERGENCY, userId);
- maybeMigrateRole(RoleManager.ROLE_HOME, userId);
-
// Some package state has changed, so grant default roles again.
Slog.i(LOG_TAG, "Granting default roles...");
AndroidFuture<Void> future = new AndroidFuture<>();
@@ -266,23 +256,6 @@
return future;
}
- private void maybeMigrateRole(String role, @UserIdInt int userId) {
- // Any role for which we have a record are already migrated
- RoleUserState userState = getOrCreateUserState(userId);
- if (!userState.isRoleAvailable(role)) {
- List<String> roleHolders = mLegacyRoleHolderProvider.getLegacyRoleHolders(role, userId);
- if (roleHolders.isEmpty()) {
- return;
- }
- Slog.i(LOG_TAG, "Migrating " + role + ", legacy holders: " + roleHolders);
- userState.addRoleName(role);
- int size = roleHolders.size();
- for (int i = 0; i < size; i++) {
- userState.addRoleHolder(role, roleHolders.get(i));
- }
- }
- }
-
@Nullable
private String computePackageStateHash(@UserIdInt int userId) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
@@ -327,7 +300,7 @@
synchronized (mLock) {
RoleUserState userState = mUserStates.get(userId);
if (userState == null) {
- userState = new RoleUserState(userId, this);
+ userState = new RoleUserState(userId, mLegacyRoleStateProvider, this);
mUserStates.put(userId, userState);
}
return userState;
@@ -663,7 +636,7 @@
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
}
- if (mPackageManagerInternal.getInstantAppPackageName(callingUid) != null) {
+ if (isInstantApp(callingUid)) {
return null;
}
@@ -676,6 +649,25 @@
}
}
+ private boolean isInstantApp(int uid) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final UserHandle user = UserHandle.getUserHandleForUid(uid);
+ final Context userContext = getContext().createContextAsUser(user, 0);
+ final PackageManager userPackageManager = userContext.getPackageManager();
+ // Instant apps can not have shared UID, so it's safe to check only the first
+ // package name here.
+ final String packageName = ArrayUtils.firstOrNull(
+ userPackageManager.getPackagesForUid(uid));
+ if (packageName == null) {
+ return false;
+ }
+ return userPackageManager.isInstantApp(packageName);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
@Override
public boolean setBrowserRoleHolder(@Nullable String packageName, @UserIdInt int userId) {
final Context context = getContext();
diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java
index 3a5ed5c..f5a79ea 100644
--- a/services/core/java/com/android/server/role/RoleUserState.java
+++ b/services/core/java/com/android/server/role/RoleUserState.java
@@ -21,14 +21,11 @@
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
-import android.os.Environment;
import android.os.Handler;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.AtomicFile;
import android.util.Slog;
-import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
@@ -38,13 +35,6 @@
import com.android.role.persistence.RolesPersistence;
import com.android.role.persistence.RolesState;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -59,23 +49,17 @@
public static final int VERSION_UNDEFINED = -1;
- private static final String ROLES_FILE_NAME = "roles.xml";
-
private static final long WRITE_DELAY_MILLIS = 200;
- private static final String TAG_ROLES = "roles";
- private static final String TAG_ROLE = "role";
- private static final String TAG_HOLDER = "holder";
- private static final String ATTRIBUTE_VERSION = "version";
- private static final String ATTRIBUTE_NAME = "name";
- private static final String ATTRIBUTE_PACKAGES_HASH = "packagesHash";
-
private final RolesPersistence mPersistence = RolesPersistence.createInstance();
@UserIdInt
private final int mUserId;
@NonNull
+ private final LegacyRoleStateProvider mLegacyStateProvider;
+
+ @NonNull
private final Callback mCallback;
@NonNull
@@ -108,10 +92,13 @@
* Create a new user state, and read its state from disk if previously persisted.
*
* @param userId the user id for this user state
+ * @param legacyStateProvider the provider for legacy role state
* @param callback the callback for this user state
*/
- public RoleUserState(@UserIdInt int userId, @NonNull Callback callback) {
+ public RoleUserState(@UserIdInt int userId,
+ @NonNull LegacyRoleStateProvider legacyStateProvider, @NonNull Callback callback) {
mUserId = userId;
+ mLegacyStateProvider = legacyStateProvider;
mCallback = callback;
readFile();
@@ -368,102 +355,27 @@
private void readFile() {
synchronized (mLock) {
- RolesState roles = mPersistence.readForUser(UserHandle.of(mUserId));
- if (roles == null) {
- readLegacyFileLocked();
- scheduleWriteFileLocked();
- return;
+ RolesState roleState = mPersistence.readForUser(UserHandle.of(mUserId));
+
+ Map<String, Set<String>> roles;
+ if (roleState != null) {
+ mVersion = roleState.getVersion();
+ mPackagesHash = roleState.getPackagesHash();
+ roles = roleState.getRoles();
+ } else {
+ roles = mLegacyStateProvider.getLegacyRoleState(mUserId);
}
-
- mVersion = roles.getVersion();
- mPackagesHash = roles.getPackagesHash();
-
mRoles.clear();
- for (Map.Entry<String, Set<String>> entry : roles.getRoles().entrySet()) {
+ for (Map.Entry<String, Set<String>> entry : roles.entrySet()) {
String roleName = entry.getKey();
ArraySet<String> roleHolders = new ArraySet<>(entry.getValue());
mRoles.put(roleName, roleHolders);
}
- }
- }
- private void readLegacyFileLocked() {
- File file = getFile(mUserId);
- try (FileInputStream in = new AtomicFile(file).openRead()) {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(in, null);
- parseXmlLocked(parser);
- Slog.i(LOG_TAG, "Read roles.xml successfully");
- } catch (FileNotFoundException e) {
- Slog.i(LOG_TAG, "roles.xml not found");
- } catch (XmlPullParserException | IOException e) {
- throw new IllegalStateException("Failed to parse roles.xml: " + file, e);
- }
- }
-
- private void parseXmlLocked(@NonNull XmlPullParser parser) throws IOException,
- XmlPullParserException {
- int type;
- int depth;
- int innerDepth = parser.getDepth() + 1;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
- if (depth > innerDepth || type != XmlPullParser.START_TAG) {
- continue;
- }
-
- if (parser.getName().equals(TAG_ROLES)) {
- parseRolesLocked(parser);
- return;
+ if (roleState == null) {
+ scheduleWriteFileLocked();
}
}
- Slog.w(LOG_TAG, "Missing <" + TAG_ROLES + "> in roles.xml");
- }
-
- private void parseRolesLocked(@NonNull XmlPullParser parser) throws IOException,
- XmlPullParserException {
- mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_VERSION));
- mPackagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH);
- mRoles.clear();
-
- int type;
- int depth;
- int innerDepth = parser.getDepth() + 1;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
- if (depth > innerDepth || type != XmlPullParser.START_TAG) {
- continue;
- }
-
- if (parser.getName().equals(TAG_ROLE)) {
- String roleName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
- ArraySet<String> roleHolders = parseRoleHoldersLocked(parser);
- mRoles.put(roleName, roleHolders);
- }
- }
- }
-
- @NonNull
- private ArraySet<String> parseRoleHoldersLocked(@NonNull XmlPullParser parser)
- throws IOException, XmlPullParserException {
- ArraySet<String> roleHolders = new ArraySet<>();
-
- int type;
- int depth;
- int innerDepth = parser.getDepth() + 1;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
- if (depth > innerDepth || type != XmlPullParser.START_TAG) {
- continue;
- }
-
- if (parser.getName().equals(TAG_HOLDER)) {
- String roleHolder = parser.getAttributeValue(null, ATTRIBUTE_NAME);
- roleHolders.add(roleHolder);
- }
- }
-
- return roleHolders;
}
/**
@@ -549,11 +461,6 @@
}
}
- @NonNull
- private static File getFile(@UserIdInt int userId) {
- return new File(Environment.getUserSystemDirectory(userId), ROLES_FILE_NAME);
- }
-
/**
* Callback for a user state.
*/
diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java
index 42f12eb..0772503 100644
--- a/services/core/java/com/android/server/tv/TvInputHal.java
+++ b/services/core/java/com/android/server/tv/TvInputHal.java
@@ -51,7 +51,8 @@
public interface Callback {
void onDeviceAvailable(TvInputHardwareInfo info, TvStreamConfig[] configs);
void onDeviceUnavailable(int deviceId);
- void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs);
+ void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs,
+ int cableConnectionStatus);
void onFirstFrameCaptured(int deviceId, int streamId);
}
@@ -142,8 +143,9 @@
mHandler.obtainMessage(EVENT_DEVICE_UNAVAILABLE, deviceId, 0).sendToTarget();
}
- private void streamConfigsChangedFromNative(int deviceId) {
- mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, 0).sendToTarget();
+ private void streamConfigsChangedFromNative(int deviceId, int cableConnectionStatus) {
+ mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId,
+ cableConnectionStatus).sendToTarget();
}
private void firstFrameCapturedFromNative(int deviceId, int streamId) {
@@ -184,6 +186,7 @@
case EVENT_STREAM_CONFIGURATION_CHANGED: {
TvStreamConfig[] configs;
int deviceId = msg.arg1;
+ int cableConnectionStatus = msg.arg2;
synchronized (mLock) {
if (DEBUG) {
Slog.d(TAG, "EVENT_STREAM_CONFIGURATION_CHANGED: deviceId = " + deviceId);
@@ -191,7 +194,7 @@
retrieveStreamConfigsLocked(deviceId);
configs = mStreamConfigs.get(deviceId);
}
- mCallback.onStreamConfigurationChanged(deviceId, configs);
+ mCallback.onStreamConfigurationChanged(deviceId, configs, cableConnectionStatus);
break;
}
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index a036bd1..38ae51f 100755
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -156,6 +156,7 @@
synchronized (mLock) {
Connection connection = new Connection(info);
connection.updateConfigsLocked(configs);
+ connection.updateCableConnectionStatusLocked(info.getCableConnectionStatus());
mConnections.put(info.getDeviceId(), connection);
buildHardwareListLocked();
mHandler.obtainMessage(
@@ -202,7 +203,8 @@
}
@Override
- public void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs) {
+ public void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs,
+ int cableConnectionStatus) {
synchronized (mLock) {
Connection connection = mConnections.get(deviceId);
if (connection == null) {
@@ -211,12 +213,22 @@
return;
}
int previousConfigsLength = connection.getConfigsLengthLocked();
+ int previousCableConnectionStatus = connection.getInputStateLocked();
connection.updateConfigsLocked(configs);
String inputId = mHardwareInputIdMap.get(deviceId);
- if (inputId != null
- && (previousConfigsLength == 0) != (connection.getConfigsLengthLocked() == 0)) {
- mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
- connection.getInputStateLocked(), 0, inputId).sendToTarget();
+ if (inputId != null) {
+ if (connection.updateCableConnectionStatusLocked(cableConnectionStatus)) {
+ if (previousCableConnectionStatus != connection.getInputStateLocked()) {
+ mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
+ connection.getInputStateLocked(), 0, inputId).sendToTarget();
+ }
+ } else {
+ if ((previousConfigsLength == 0)
+ != (connection.getConfigsLengthLocked() == 0)) {
+ mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
+ connection.getInputStateLocked(), 0, inputId).sendToTarget();
+ }
+ }
}
ITvInputHardwareCallback callback = connection.getCallbackLocked();
if (callback != null) {
@@ -625,7 +637,7 @@
}
private class Connection implements IBinder.DeathRecipient {
- private final TvInputHardwareInfo mHardwareInfo;
+ private TvInputHardwareInfo mHardwareInfo;
private TvInputInfo mInfo;
private TvInputHardwareImpl mHardware = null;
private ITvInputHardwareCallback mCallback;
@@ -634,6 +646,7 @@
private Integer mResolvedUserId = null;
private Runnable mOnFirstFrameCaptured;
private ResourceClientProfile mResourceClientProfile = null;
+ private boolean mIsCableConnectionStatusUpdated = false;
public Connection(TvInputHardwareInfo hardwareInfo) {
mHardwareInfo = hardwareInfo;
@@ -736,6 +749,17 @@
+ " }";
}
+ public boolean updateCableConnectionStatusLocked(int cableConnectionStatus) {
+ // Update connection status only if it's not default value
+ if (cableConnectionStatus != TvInputHardwareInfo.CABLE_CONNECTION_STATUS_UNKNOWN
+ || mIsCableConnectionStatusUpdated) {
+ mIsCableConnectionStatusUpdated = true;
+ mHardwareInfo = mHardwareInfo.toBuilder()
+ .cableConnectionStatus(cableConnectionStatus).build();
+ }
+ return mIsCableConnectionStatusUpdated;
+ }
+
private int getConfigsLengthLocked() {
return mConfigs == null ? 0 : mConfigs.length;
}
@@ -743,7 +767,9 @@
private int getInputStateLocked() {
int configsLength = getConfigsLengthLocked();
if (configsLength > 0) {
- return INPUT_STATE_CONNECTED;
+ if (!mIsCableConnectionStatusUpdated) {
+ return INPUT_STATE_CONNECTED;
+ }
}
switch (mHardwareInfo.getCableConnectionStatus()) {
case TvInputHardwareInfo.CABLE_CONNECTION_STATUS_CONNECTED:
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index ff5b65b..a1d2f8a 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -1874,6 +1874,46 @@
}
@Override
+ public void pauseRecording(IBinder sessionToken, @NonNull Bundle params, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+ userId, "pauseRecording");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ getSessionLocked(sessionToken, callingUid, resolvedUserId)
+ .pauseRecording(params);
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slog.e(TAG, "error in pauseRecording", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void resumeRecording(IBinder sessionToken, @NonNull Bundle params, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+ userId, "resumeRecording");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ getSessionLocked(sessionToken, callingUid, resolvedUserId)
+ .resumeRecording(params);
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slog.e(TAG, "error in resumeRecording", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public List<TvInputHardwareInfo> getHardwareList() throws RemoteException {
if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
!= PackageManager.PERMISSION_GRANTED) {
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
index 072bdd2..988582d 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.media.IResourceManagerService;
import android.media.tv.TvInputManager;
+import android.media.tv.tuner.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.CasSessionRequest;
import android.media.tv.tunerresourcemanager.IResourcesReclaimListener;
import android.media.tv.tunerresourcemanager.ITunerResourceManager;
@@ -30,7 +31,6 @@
import android.media.tv.tunerresourcemanager.TunerCiCamRequest;
import android.media.tv.tunerresourcemanager.TunerDemuxRequest;
import android.media.tv.tunerresourcemanager.TunerDescramblerRequest;
-import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
import android.media.tv.tunerresourcemanager.TunerResourceManager;
@@ -578,7 +578,7 @@
} else {
// Add a new fe resource
FrontendResource newFe = new FrontendResource.Builder(infos[i].handle)
- .type(infos[i].frontendType)
+ .type(infos[i].type)
.exclusiveGroupId(infos[i].exclusiveGroupId)
.build();
addFrontendResource(newFe);
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index a34a507..536375f 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -36,6 +36,7 @@
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import java.util.ArrayList;
@@ -59,7 +60,8 @@
private final Vibrator mVibrator;
private final AudioManager mAudioManager;
private final SettingsObserver mSettingObserver;
- private final UidObserver mUidObserver;
+ @VisibleForTesting
+ final UidObserver mUidObserver;
@GuardedBy("mLock")
private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>();
@@ -251,8 +253,7 @@
* allowed to play in the background (i.e. it's a notification, ringtone or alarm vibration).
*/
public boolean shouldVibrateForUid(int uid, int usageHint) {
- return mUidObserver.isUidForeground(uid) || isNotification(usageHint)
- || isRingtone(usageHint) || isAlarm(usageHint);
+ return mUidObserver.isUidForeground(uid) || isClassAlarm(usageHint);
}
/**
@@ -292,6 +293,11 @@
return usageHint == VibrationAttributes.USAGE_ALARM;
}
+ private static boolean isClassAlarm(int usageHint) {
+ return (usageHint & VibrationAttributes.USAGE_CLASS_MASK)
+ == VibrationAttributes.USAGE_CLASS_ALARM;
+ }
+
/** Updates all vibration settings and triggers registered listeners. */
public void updateSettings() {
synchronized (mLock) {
@@ -414,7 +420,8 @@
}
/** Implementation of {@link ContentObserver} to be registered to a setting {@link Uri}. */
- private final class UidObserver extends IUidObserver.Stub {
+ @VisibleForTesting
+ final class UidObserver extends IUidObserver.Stub {
private final SparseArray<Integer> mProcStatesCache = new SparseArray<>();
public boolean isUidForeground(int uid) {
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 03cf021..6bca484 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -288,7 +288,7 @@
return;
}
mLastLaunchedActivity = r;
- if (!r.noDisplay) {
+ if (!r.noDisplay && !r.isReportedDrawn()) {
if (DEBUG_METRICS) Slog.i(TAG, "Add pending draw " + r);
mPendingDrawActivities.add(r);
}
@@ -576,7 +576,7 @@
+ " processSwitch=" + processSwitch + " info=" + info);
}
- if (launchedActivity.isReportedDrawn()) {
+ if (launchedActivity.isReportedDrawn() && launchedActivity.isVisible()) {
// Launched activity is already visible. We cannot measure windows drawn delay.
abort(info, "launched activity already visible");
return;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index a9c5474..0b5bd7a 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -294,6 +294,7 @@
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.TransitionOldType;
import android.view.animation.Animation;
+import android.window.IRemoteTransition;
import android.window.TaskSnapshot;
import android.window.WindowContainerToken;
@@ -467,6 +468,7 @@
private ActivityOptions mPendingOptions;
/** Non-null if {@link #mPendingOptions} specifies the remote animation. */
private RemoteAnimationAdapter mPendingRemoteAnimation;
+ private IRemoteTransition mPendingRemoteTransition;
ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections.
@@ -894,6 +896,9 @@
pw.print("pendingRemoteAnimationCallingPid=");
pw.println(mPendingRemoteAnimation.getCallingPid());
}
+ if (mPendingRemoteTransition != null) {
+ pw.print(prefix + " pendingRemoteTransition=" + mPendingRemoteTransition);
+ }
if (appTimeTracker != null) {
appTimeTracker.dumpWithHeader(pw, prefix, false);
}
@@ -3884,6 +3889,7 @@
if (options.getAnimationType() == ANIM_REMOTE_ANIMATION) {
mPendingRemoteAnimation = options.getRemoteAnimationAdapter();
}
+ mPendingRemoteTransition = options.getRemoteTransition();
}
void applyOptionsAnimation() {
@@ -4064,6 +4070,7 @@
void clearOptionsAnimation() {
mPendingOptions = null;
mPendingRemoteAnimation = null;
+ mPendingRemoteTransition = null;
}
ActivityOptions getOptions() {
@@ -4078,6 +4085,12 @@
return opts;
}
+ IRemoteTransition takeRemoteTransition() {
+ IRemoteTransition out = mPendingRemoteTransition;
+ mPendingRemoteTransition = null;
+ return out;
+ }
+
boolean allowMoveToFront() {
return mPendingOptions == null || !mPendingOptions.getAvoidMoveToFront();
}
@@ -6479,8 +6492,9 @@
mLastReportedConfiguration.setConfiguration(global, override);
}
- boolean hasCompatDisplayInsets() {
- return mCompatDisplayInsets != null;
+ @Nullable
+ CompatDisplayInsets getCompatDisplayInsets() {
+ return mCompatDisplayInsets;
}
/**
@@ -6569,7 +6583,12 @@
}
return !isResizeable() && (info.isFixedOrientation() || info.hasFixedAspectRatio())
// The configuration of non-standard type should be enforced by system.
- && isActivityTypeStandard()
+ // {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD} is set when this activity is
+ // added to a task, but this function is called when resolving the launch params, at
+ // which point, the activity type is still undefined if it will be standard.
+ // For other non-standard types, the type is set in the constructor, so this should
+ // not be a problem.
+ && isActivityTypeStandardOrUndefined()
&& !mAtmService.mForceResizableActivities;
}
@@ -7798,13 +7817,16 @@
/**
* The precomputed insets of the display in each rotation. This is used to make the size
* compatibility mode activity compute the configuration without relying on its current display.
- * This currently only supports fullscreen and freeform windowing mode.
*/
static class CompatDisplayInsets {
+ /** The container width on rotation 0. */
private final int mWidth;
+ /** The container height on rotation 0. */
private final int mHeight;
+ /** Whether the {@link Task} windowingMode represents a floating window*/
final boolean mIsFloating;
-
+ /** Whether the {@link Task} is letterboxed when the unresizable activity is first shown. */
+ final boolean mIsTaskLetterboxed;
/**
* The nonDecorInsets for each rotation. Includes the navigation bar and cutout insets. It
* is used to compute the appBounds.
@@ -7831,27 +7853,24 @@
mNonDecorInsets[rotation] = emptyRect;
mStableInsets[rotation] = emptyRect;
}
+ mIsTaskLetterboxed = false;
return;
}
final Task task = container.getTask();
- if (task != null && task.isTaskLetterboxed()) {
- // For apps in Task letterbox, it should fill the task bounds.
- final Point dimensions = getRotationZeroDimensions(task);
- mWidth = dimensions.x;
- mHeight = dimensions.y;
- } else {
- // If the activity is not floating nor letterboxed, assume it fills the root.
- final RootDisplayArea root = container.getRootDisplayArea();
- if (root == null || root == display) {
- mWidth = display.mBaseDisplayWidth;
- mHeight = display.mBaseDisplayHeight;
- } else {
- final Point dimensions = getRotationZeroDimensions(root);
- mWidth = dimensions.x;
- mHeight = dimensions.y;
- }
- }
+ mIsTaskLetterboxed = task != null && task.isTaskLetterboxed();
+
+ // Store the bounds of the Task for the non-resizable activity to use in size compat
+ // mode so that the activity will not be resized regardless the windowing mode it is
+ // currently in.
+ final WindowContainer filledContainer = task != null ? task : display;
+ final Point dimensions = getRotationZeroDimensions(filledContainer);
+ mWidth = dimensions.x;
+ mHeight = dimensions.y;
+
+ // Bounds of the filled container if it doesn't fill the display.
+ final Rect unfilledContainerBounds =
+ filledContainer.getBounds().equals(display.getBounds()) ? null : new Rect();
final DisplayPolicy policy = display.getDisplayPolicy();
for (int rotation = 0; rotation < 4; rotation++) {
mNonDecorInsets[rotation] = new Rect();
@@ -7864,6 +7883,20 @@
policy.getNonDecorInsetsLw(rotation, dw, dh, cutout, mNonDecorInsets[rotation]);
mStableInsets[rotation].set(mNonDecorInsets[rotation]);
policy.convertNonDecorInsetsToStableInsets(mStableInsets[rotation], rotation);
+
+ if (unfilledContainerBounds == null) {
+ continue;
+ }
+ // The insets is based on the display, but the container may be smaller than the
+ // display, so update the insets to exclude parts that are not intersected with the
+ // container.
+ unfilledContainerBounds.set(filledContainer.getBounds());
+ display.rotateBounds(
+ filledContainer.getConfiguration().windowConfiguration.getRotation(),
+ rotation,
+ unfilledContainerBounds);
+ updateInsetsForBounds(unfilledContainerBounds, dw, dh, mNonDecorInsets[rotation]);
+ updateInsetsForBounds(unfilledContainerBounds, dw, dh, mStableInsets[rotation]);
}
}
@@ -7881,6 +7914,18 @@
return rotated ? new Point(height, width) : new Point(width, height);
}
+ /**
+ * Updates the display insets to exclude the parts that are not intersected with the given
+ * bounds.
+ */
+ private static void updateInsetsForBounds(Rect bounds, int displayWidth, int displayHeight,
+ Rect inset) {
+ inset.left = Math.max(0, inset.left - bounds.left);
+ inset.top = Math.max(0, inset.top - bounds.top);
+ inset.right = Math.max(0, bounds.right - displayWidth + inset.right);
+ inset.bottom = Math.max(0, bounds.bottom - displayHeight + inset.bottom);
+ }
+
void getBoundsByRotation(Rect outBounds, int rotation) {
final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
final int dw = rotated ? mHeight : mWidth;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 20625c8..e67210e 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -110,6 +110,7 @@
import android.util.DebugUtils;
import android.util.Pools.SynchronizedPool;
import android.util.Slog;
+import android.window.IRemoteTransition;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.HeavyWeightSwitcherActivity;
@@ -1573,6 +1574,10 @@
final Transition newTransition = (!mService.getTransitionController().isCollecting()
&& mService.getTransitionController().getTransitionPlayer() != null)
? mService.getTransitionController().createTransition(TRANSIT_OPEN) : null;
+ IRemoteTransition remoteTransition = r.takeRemoteTransition();
+ if (newTransition != null && remoteTransition != null) {
+ newTransition.setRemoteTransition(remoteTransition);
+ }
mService.getTransitionController().collect(r);
try {
mService.deferWindowLayout();
@@ -1611,7 +1616,7 @@
}
if (newTransition != null) {
mService.getTransitionController().requestStartTransition(newTransition,
- r.getTask());
+ mTargetTask, remoteTransition);
} else {
// Make the collecting transition wait until this request is ready.
mService.getTransitionController().setReady(false);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 599bf37..a68f5575 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -1365,7 +1365,8 @@
mUserLeaving = true;
}
- mService.getTransitionController().requestTransitionIfNeeded(TRANSIT_TO_FRONT, task);
+ mService.getTransitionController().requestTransitionIfNeeded(TRANSIT_TO_FRONT,
+ 0 /* flags */, task, options != null ? options.getRemoteTransition() : null);
reason = reason + " findTaskToMoveToFront";
boolean reparented = false;
if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index fc8747d..6d2b0bf 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2825,9 +2825,7 @@
getResolvedOverrideConfiguration().windowConfiguration.getBounds();
if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
- computeFullscreenBounds(outOverrideBounds, null /* refActivity */,
- newParentConfig.windowConfiguration.getBounds(),
- newParentConfig.orientation);
+ computeFullscreenBounds(outOverrideBounds, newParentConfig);
// The bounds for fullscreen mode shouldn't be adjusted by minimal size. Otherwise if
// the parent or display is smaller than the size, the content may be cropped.
return;
@@ -2867,19 +2865,19 @@
* {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN} when the parent doesn't handle the
* orientation change and the requested orientation is different from the parent.
*/
- void computeFullscreenBounds(@NonNull Rect outBounds, @Nullable ActivityRecord refActivity,
- @NonNull Rect parentBounds, int parentOrientation) {
+ void computeFullscreenBounds(@NonNull Rect outBounds, @NonNull Configuration newParentConfig) {
// In FULLSCREEN mode, always start with empty bounds to indicate "fill parent".
outBounds.setEmpty();
if (handlesOrientationChangeFromDescendant()) {
+ // No need to letterbox at task level. Display will handle fixed-orientation requests.
return;
}
- if (refActivity == null) {
- // Use the top activity as the reference of orientation. Don't include overlays because
- // it is usually not the actual content or just temporarily shown.
- // E.g. ForcedResizableInfoActivity.
- refActivity = getTopNonFinishingActivity(false /* includeOverlays */);
- }
+
+ final int parentOrientation = newParentConfig.orientation;
+ // Use the top activity as the reference of orientation. Don't include overlays because
+ // it is usually not the actual content or just temporarily shown.
+ // E.g. ForcedResizableInfoActivity.
+ final ActivityRecord refActivity = getTopNonFinishingActivity(false /* includeOverlays */);
// If the task or the reference activity requires a different orientation (either by
// override or activityInfo), make it fit the available bounds by scaling down its bounds.
@@ -2891,11 +2889,17 @@
return;
}
- if (refActivity != null && refActivity.hasCompatDisplayInsets()) {
+ final ActivityRecord.CompatDisplayInsets compatDisplayInsets =
+ refActivity == null ? null : refActivity.getCompatDisplayInsets();
+ if (compatDisplayInsets != null && !compatDisplayInsets.mIsTaskLetterboxed) {
// App prefers to keep its original size.
+ // If the size compat is from previous task letterboxing, we may want to have task
+ // letterbox again, otherwise it will show the size compat restart button even if the
+ // restart bounds will be the same.
return;
}
+ final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
final int parentWidth = parentBounds.width();
final int parentHeight = parentBounds.height();
float aspect = Math.max(parentWidth, parentHeight)
@@ -2930,6 +2934,18 @@
final int left = parentBounds.centerX() - width / 2;
outBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
}
+
+ if (compatDisplayInsets != null) {
+ compatDisplayInsets.getBoundsByRotation(
+ mTmpBounds, newParentConfig.windowConfiguration.getRotation());
+ if (outBounds.width() != mTmpBounds.width()
+ || outBounds.height() != mTmpBounds.height()) {
+ // The app shouldn't be resized, we only do task letterboxing if the compat bounds
+ // is also from the same task letterbox. Otherwise, clear the task bounds to show
+ // app in size compat mode.
+ outBounds.setEmpty();
+ }
+ }
}
Rect updateOverrideConfigurationFromLaunchBounds() {
@@ -4093,6 +4109,7 @@
info.topActivityInfo = mReuseActivitiesReport.top != null
? mReuseActivitiesReport.top.info
: null;
+ info.launchCookies.clear();
info.addLaunchCookie(mLaunchCookie);
forAllActivities(r -> {
info.addLaunchCookie(r.mLaunchCookie);
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 9a83ac7..65247d0 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -555,6 +555,7 @@
changed = (cfgChanges & REPORT_CONFIGS) != 0;
}
if (!(changed || force)) {
+ // mTmpTaskInfo will be reused next time.
return;
}
final RunningTaskInfo newInfo = mTmpTaskInfo;
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index b37e3c4..46aea23 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -50,6 +50,7 @@
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.animation.Animation;
+import android.window.IRemoteTransition;
import android.window.TransitionInfo;
import com.android.internal.annotations.VisibleForTesting;
@@ -101,6 +102,7 @@
private @WindowManager.TransitionFlags int mFlags;
private final TransitionController mController;
private final BLASTSyncEngine mSyncEngine;
+ private IRemoteTransition mRemoteTransition = null;
/**
* This is a leash to put animating surfaces into flatly without clipping/ordering issues. It
@@ -235,8 +237,14 @@
if (target.getParent() != null) {
// Ensure surfaceControls are re-parented back into the hierarchy.
t.reparent(target.getSurfaceControl(), target.getParent().getSurfaceControl());
+ t.setLayer(target.getSurfaceControl(), target.getLastLayer());
+ // TODO(shell-transitions): Once all remotables have been moved, see if there is
+ // a more appropriate place to do the following. This may
+ // involve passing an SF transaction from shell on finish.
target.getRelativePosition(tmpPos);
t.setPosition(target.getSurfaceControl(), tmpPos.x, tmpPos.y);
+ t.setCornerRadius(target.getSurfaceControl(), 0);
+ t.setShadowRadius(target.getSurfaceControl(), 0);
displays.add(target.getDisplayContent());
}
}
@@ -283,6 +291,14 @@
mSyncEngine.abort(mSyncId);
}
+ void setRemoteTransition(IRemoteTransition remoteTransition) {
+ mRemoteTransition = remoteTransition;
+ }
+
+ IRemoteTransition getRemoteTransition() {
+ return mRemoteTransition;
+ }
+
@Override
public void onTransactionReady(int syncId, SurfaceControl.Transaction transaction) {
if (syncId != mSyncId) {
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 0fe0afa..5f46ffe 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -26,7 +26,9 @@
import android.os.RemoteException;
import android.util.Slog;
import android.view.WindowManager;
+import android.window.IRemoteTransition;
import android.window.ITransitionPlayer;
+import android.window.TransitionRequestInfo;
import com.android.internal.protolog.ProtoLogGroup;
import com.android.internal.protolog.common.ProtoLog;
@@ -140,7 +142,7 @@
}
/**
- * @see #requestTransitionIfNeeded(int, int)
+ * @see #requestTransitionIfNeeded(int, int, WindowContainer, IRemoteTransition)
*/
@Nullable
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
@@ -148,9 +150,19 @@
return requestTransitionIfNeeded(type, 0 /* flags */, trigger);
}
+ /**
+ * @see #requestTransitionIfNeeded(int, int, WindowContainer, IRemoteTransition)
+ */
+ @Nullable
+ Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
+ @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger) {
+ return requestTransitionIfNeeded(type, flags, trigger, null /* remote */);
+ }
+
private static boolean isExistenceType(@WindowManager.TransitionType int type) {
return type == TRANSIT_OPEN || type == TRANSIT_CLOSE;
}
+
/**
* If a transition isn't requested yet, creates one and asks the TransitionPlayer (Shell) to
* start it. Collection can start immediately.
@@ -159,7 +171,8 @@
*/
@Nullable
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
- @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger) {
+ @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger,
+ @Nullable IRemoteTransition remoteTransition) {
if (mTransitionPlayer == null) {
return null;
}
@@ -169,7 +182,7 @@
mCollectingTransition.setReady(false);
} else {
newTransition = requestStartTransition(createTransition(type, flags),
- trigger != null ? trigger.asTask() : null);
+ trigger != null ? trigger.asTask() : null, remoteTransition);
}
if (trigger != null) {
if (isExistenceType(type)) {
@@ -183,7 +196,8 @@
/** Asks the transition player (shell) to start a created but not yet started transition. */
@NonNull
- Transition requestStartTransition(@NonNull Transition transition, @Nullable Task startTask) {
+ Transition requestStartTransition(@NonNull Transition transition, @Nullable Task startTask,
+ @Nullable IRemoteTransition remoteTransition) {
try {
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
"Requesting StartTransition: %s", transition);
@@ -192,7 +206,8 @@
info = new ActivityManager.RunningTaskInfo();
startTask.fillTaskInfo(info);
}
- mTransitionPlayer.requestStartTransition(transition.mType, transition, info);
+ mTransitionPlayer.requestStartTransition(transition, new TransitionRequestInfo(
+ transition.mType, info, remoteTransition));
} catch (RemoteException e) {
Slog.e(TAG, "Error requesting transition", e);
transition.start();
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 13c6752..dc15b07 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -161,7 +161,7 @@
jmethodID size;
} gSparseArrayClassInfo;
-struct InputSensorInfoOffsets {
+static struct InputSensorInfoOffsets {
jclass clazz;
// fields
jfieldID name;
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 35aad3e..b2d6b15 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -2709,7 +2709,7 @@
}
static jboolean android_location_gnss_hal_GnssNative_start_measurement_collection(
- JNIEnv* /* env */, jclass, jboolean enableFullTracking) {
+ JNIEnv* /* env */, jclass, jboolean enableFullTracking, jboolean enableCorrVecOutputs) {
if (gnssMeasurementIface == nullptr) {
ALOGE("%s: IGnssMeasurement interface not available.", __func__);
return JNI_FALSE;
@@ -2717,7 +2717,7 @@
return gnssMeasurementIface->setCallback(std::make_unique<gnss::GnssMeasurementCallback>(
mCallbacksObj),
- enableFullTracking);
+ enableFullTracking, enableCorrVecOutputs);
}
static jboolean android_location_gnss_hal_GnssNative_stop_measurement_collection(JNIEnv* env,
@@ -3211,7 +3211,7 @@
/* name, signature, funcPtr */
{"native_is_measurement_supported", "()Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_is_measurement_supported)},
- {"native_start_measurement_collection", "(Z)Z",
+ {"native_start_measurement_collection", "(ZZ)Z",
reinterpret_cast<void*>(
android_location_gnss_hal_GnssNative_start_measurement_collection)},
{"native_stop_measurement_collection", "()Z",
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 631e185..7b379e5 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -68,6 +68,9 @@
static constexpr auto PollTimeoutMs = 5000;
static constexpr auto TraceTagCheckInterval = 1s;
+static constexpr auto WaitOnEofMinInterval = 10ms;
+static constexpr auto WaitOnEofMaxInterval = 1s;
+
struct JniIds {
jclass packageManagerShellCommandDataLoader;
jmethodID pmscdLookupShellCommand;
@@ -485,14 +488,16 @@
if (read == 0) {
if (waitOnEof) {
// eof of stdin, waiting...
- ALOGE("eof of stdin, waiting...: %d, remaining: %d, block: %d, read: %d",
- int(totalSize), int(remaining), int(blockIdx), int(read));
- using namespace std::chrono_literals;
- std::this_thread::sleep_for(10ms);
- continue;
+ if (doWaitOnEof()) {
+ continue;
+ } else {
+ return false;
+ }
}
break;
}
+ resetWaitOnEof();
+
if (read < 0) {
return false;
}
@@ -776,6 +781,21 @@
return fileId;
}
+ // Waiting with exponential backoff, maximum total time ~1.2sec.
+ bool doWaitOnEof() {
+ if (mWaitOnEofInterval >= WaitOnEofMaxInterval) {
+ resetWaitOnEof();
+ return false;
+ }
+ auto result = mWaitOnEofInterval;
+ mWaitOnEofInterval =
+ std::min<std::chrono::milliseconds>(mWaitOnEofInterval * 2, WaitOnEofMaxInterval);
+ std::this_thread::sleep_for(result);
+ return true;
+ }
+
+ void resetWaitOnEof() { mWaitOnEofInterval = WaitOnEofMinInterval; }
+
JavaVM* const mJvm;
std::string mArgs;
android::dataloader::FilesystemConnectorPtr mIfs = nullptr;
@@ -786,6 +806,7 @@
std::thread mReceiverThread;
std::atomic<bool> mStopReceiving = false;
std::atomic<bool> mReadLogsEnabled = false;
+ std::chrono::milliseconds mWaitOnEofInterval{WaitOnEofMinInterval};
/** Tracks which files have been requested */
std::unordered_set<FileIdx> mRequestedFiles;
};
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index 4e1a234..a5311f3 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -261,7 +261,7 @@
void onDeviceAvailable(const TvInputDeviceInfo& info);
void onDeviceUnavailable(int deviceId);
- void onStreamConfigurationsChanged(int deviceId);
+ void onStreamConfigurationsChanged(int deviceId, int cableConnectionStatus);
void onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded);
private:
@@ -519,7 +519,7 @@
deviceId);
}
-void JTvInputHal::onStreamConfigurationsChanged(int deviceId) {
+void JTvInputHal::onStreamConfigurationsChanged(int deviceId, int cableConnectionStatus) {
{
Mutex::Autolock autoLock(&mLock);
KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId);
@@ -529,10 +529,8 @@
connections.clear();
}
JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(
- mThiz,
- gTvInputHalClassInfo.streamConfigsChanged,
- deviceId);
+ env->CallVoidMethod(mThiz, gTvInputHalClassInfo.streamConfigsChanged, deviceId,
+ cableConnectionStatus);
}
void JTvInputHal::onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded) {
@@ -572,7 +570,8 @@
mHal->onDeviceUnavailable(mEvent.deviceInfo.deviceId);
} break;
case TvInputEventType::STREAM_CONFIGURATIONS_CHANGED: {
- mHal->onStreamConfigurationsChanged(mEvent.deviceInfo.deviceId);
+ int cableConnectionStatus = static_cast<int>(mEvent.deviceInfo.cableConnectionStatus);
+ mHal->onStreamConfigurationsChanged(mEvent.deviceInfo.deviceId, cableConnectionStatus);
} break;
default:
ALOGE("Unrecognizable event");
@@ -688,9 +687,8 @@
"deviceAvailableFromNative", "(Landroid/media/tv/TvInputHardwareInfo;)V");
GET_METHOD_ID(
gTvInputHalClassInfo.deviceUnavailable, clazz, "deviceUnavailableFromNative", "(I)V");
- GET_METHOD_ID(
- gTvInputHalClassInfo.streamConfigsChanged, clazz,
- "streamConfigsChangedFromNative", "(I)V");
+ GET_METHOD_ID(gTvInputHalClassInfo.streamConfigsChanged, clazz,
+ "streamConfigsChangedFromNative", "(II)V");
GET_METHOD_ID(
gTvInputHalClassInfo.firstFrameCaptured, clazz,
"firstFrameCapturedFromNative", "(II)V");
diff --git a/services/core/jni/gnss/GnssMeasurement.cpp b/services/core/jni/gnss/GnssMeasurement.cpp
index 2261c38..663d839 100644
--- a/services/core/jni/gnss/GnssMeasurement.cpp
+++ b/services/core/jni/gnss/GnssMeasurement.cpp
@@ -50,8 +50,9 @@
: mIGnssMeasurement(iGnssMeasurement) {}
jboolean GnssMeasurement::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) {
- auto status = mIGnssMeasurement->setCallback(callback->getAidl(), enableFullTracking);
+ bool enableFullTracking, bool enableCorrVecOutputs) {
+ auto status = mIGnssMeasurement->setCallback(callback->getAidl(), enableFullTracking,
+ enableCorrVecOutputs);
return checkAidlStatus(status, "IGnssMeasurement setCallback() failed.");
}
@@ -66,9 +67,12 @@
: mIGnssMeasurement_V1_0(iGnssMeasurement) {}
jboolean GnssMeasurement_V1_0::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) {
+ bool enableFullTracking, bool enableCorrVecOutputs) {
if (enableFullTracking == true) {
- ALOGW("Full tracking is mode not supported in 1.0 GNSS HAL.");
+ ALOGW("Full tracking mode is not supported in 1.0 GNSS HAL.");
+ }
+ if (enableCorrVecOutputs == true) {
+ ALOGW("Correlation vector output is not supported in 1.0 GNSS HAL.");
}
auto status = mIGnssMeasurement_V1_0->setCallback(callback->getHidl());
if (!checkHidlReturn(status, "IGnssMeasurement setCallback() failed.")) {
@@ -89,7 +93,10 @@
: GnssMeasurement_V1_0{iGnssMeasurement}, mIGnssMeasurement_V1_1(iGnssMeasurement) {}
jboolean GnssMeasurement_V1_1::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) {
+ bool enableFullTracking, bool enableCorrVecOutputs) {
+ if (enableCorrVecOutputs == true) {
+ ALOGW("Correlation vector output is not supported in 1.1 GNSS HAL.");
+ }
auto status = mIGnssMeasurement_V1_1->setCallback_1_1(callback->getHidl(), enableFullTracking);
if (!checkHidlReturn(status, "IGnssMeasurement setCallback_V1_1() failed.")) {
return JNI_FALSE;
@@ -104,7 +111,10 @@
: GnssMeasurement_V1_1{iGnssMeasurement}, mIGnssMeasurement_V2_0(iGnssMeasurement) {}
jboolean GnssMeasurement_V2_0::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) {
+ bool enableFullTracking, bool enableCorrVecOutputs) {
+ if (enableCorrVecOutputs == true) {
+ ALOGW("Correlation vector output is not supported in 2.0 GNSS HAL.");
+ }
auto status = mIGnssMeasurement_V2_0->setCallback_2_0(callback->getHidl(), enableFullTracking);
if (!checkHidlReturn(status, "IGnssMeasurement setCallback_2_0() failed.")) {
return JNI_FALSE;
@@ -119,7 +129,10 @@
: GnssMeasurement_V2_0{iGnssMeasurement}, mIGnssMeasurement_V2_1(iGnssMeasurement) {}
jboolean GnssMeasurement_V2_1::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) {
+ bool enableFullTracking, bool enableCorrVecOutputs) {
+ if (enableCorrVecOutputs == true) {
+ ALOGW("Correlation vector output is not supported in 2.1 GNSS HAL.");
+ }
auto status = mIGnssMeasurement_V2_1->setCallback_2_1(callback->getHidl(), enableFullTracking);
if (!checkHidlReturn(status, "IGnssMeasurement setCallback_2_1() failed.")) {
return JNI_FALSE;
diff --git a/services/core/jni/gnss/GnssMeasurement.h b/services/core/jni/gnss/GnssMeasurement.h
index e64336f..f0752cd 100644
--- a/services/core/jni/gnss/GnssMeasurement.h
+++ b/services/core/jni/gnss/GnssMeasurement.h
@@ -38,7 +38,7 @@
public:
virtual ~GnssMeasurementInterface() {}
virtual jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) = 0;
+ bool enableFullTracking, bool enableCorrVecOutputs) = 0;
virtual jboolean close() = 0;
};
@@ -46,7 +46,7 @@
public:
GnssMeasurement(const sp<android::hardware::gnss::IGnssMeasurementInterface>& iGnssMeasurement);
jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) override;
+ bool enableFullTracking, bool enableCorrVecOutputs) override;
jboolean close() override;
private:
@@ -58,7 +58,7 @@
GnssMeasurement_V1_0(
const sp<android::hardware::gnss::V1_0::IGnssMeasurement>& iGnssMeasurement);
jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) override;
+ bool enableFullTracking, bool enableCorrVecOutputs) override;
jboolean close() override;
private:
@@ -70,7 +70,7 @@
GnssMeasurement_V1_1(
const sp<android::hardware::gnss::V1_1::IGnssMeasurement>& iGnssMeasurement);
jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) override;
+ bool enableFullTracking, bool enableCorrVecOutputs) override;
private:
const sp<android::hardware::gnss::V1_1::IGnssMeasurement> mIGnssMeasurement_V1_1;
@@ -81,7 +81,7 @@
GnssMeasurement_V2_0(
const sp<android::hardware::gnss::V2_0::IGnssMeasurement>& iGnssMeasurement);
jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) override;
+ bool enableFullTracking, bool enableCorrVecOutputs) override;
private:
const sp<android::hardware::gnss::V2_0::IGnssMeasurement> mIGnssMeasurement_V2_0;
@@ -92,7 +92,7 @@
GnssMeasurement_V2_1(
const sp<android::hardware::gnss::V2_1::IGnssMeasurement>& iGnssMeasurement);
jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) override;
+ bool enableFullTracking, bool enableCorrVecOutputs) override;
private:
const sp<android::hardware::gnss::V2_1::IGnssMeasurement> mIGnssMeasurement_V2_1;
diff --git a/services/core/jni/gnss/GnssMeasurementCallback.cpp b/services/core/jni/gnss/GnssMeasurementCallback.cpp
index 8cba773..757381d 100644
--- a/services/core/jni/gnss/GnssMeasurementCallback.cpp
+++ b/services/core/jni/gnss/GnssMeasurementCallback.cpp
@@ -21,21 +21,33 @@
namespace android::gnss {
using binder::Status;
+using hardware::gnss::CorrelationVector;
using hardware::gnss::ElapsedRealtime;
using hardware::gnss::GnssClock;
using hardware::gnss::GnssData;
using hardware::gnss::GnssMeasurement;
using hardware::gnss::SatellitePvt;
+jclass class_arrayList;
+jclass class_clockInfo;
+jclass class_correlationVectorBuilder;
jclass class_gnssMeasurementsEvent;
jclass class_gnssMeasurement;
jclass class_gnssClock;
-jclass class_satellitePvtBuilder;
jclass class_positionEcef;
+jclass class_satellitePvtBuilder;
jclass class_velocityEcef;
-jclass class_clockInfo;
+jmethodID method_arrayListAdd;
+jmethodID method_arrayListCtor;
+jmethodID method_correlationVectorBuilderBuild;
+jmethodID method_correlationVectorBuilderCtor;
+jmethodID method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond;
+jmethodID method_correlationVectorBuilderSetMagnitude;
+jmethodID method_correlationVectorBuilderSetSamplingStartMeters;
+jmethodID method_correlationVectorBuilderSetSamplingWidthMeters;
jmethodID method_gnssMeasurementsEventCtor;
+jmethodID method_gnssMeasurementsSetCorrelationVectors;
jmethodID method_gnssMeasurementsSetSatellitePvt;
jmethodID method_gnssClockCtor;
jmethodID method_gnssMeasurementCtor;
@@ -66,6 +78,9 @@
method_gnssMeasurementsSetSatellitePvt =
env->GetMethodID(class_gnssMeasurement, "setSatellitePvt",
"(Landroid/location/SatellitePvt;)V");
+ method_gnssMeasurementsSetCorrelationVectors =
+ env->GetMethodID(class_gnssMeasurement, "setCorrelationVectors",
+ "(Ljava/util/Collection;)V");
jclass gnssClockClass = env->FindClass("android/location/GnssClock");
class_gnssClock = (jclass)env->NewGlobalRef(gnssClockClass);
@@ -106,6 +121,31 @@
jclass clockInfoClass = env->FindClass("android/location/SatellitePvt$ClockInfo");
class_clockInfo = (jclass)env->NewGlobalRef(clockInfoClass);
method_clockInfo = env->GetMethodID(class_clockInfo, "<init>", "(DDD)V");
+
+ jclass correlationVectorBuilder = env->FindClass("android/location/CorrelationVector$Builder");
+ class_correlationVectorBuilder = (jclass)env->NewGlobalRef(correlationVectorBuilder);
+ method_correlationVectorBuilderCtor =
+ env->GetMethodID(class_correlationVectorBuilder, "<init>", "()V");
+ method_correlationVectorBuilderSetMagnitude =
+ env->GetMethodID(class_correlationVectorBuilder, "setMagnitude",
+ "([I)Landroid/location/CorrelationVector$Builder;");
+ method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond =
+ env->GetMethodID(class_correlationVectorBuilder, "setFrequencyOffsetMetersPerSecond",
+ "(I)Landroid/location/CorrelationVector$Builder;");
+ method_correlationVectorBuilderSetSamplingStartMeters =
+ env->GetMethodID(class_correlationVectorBuilder, "setSamplingStartMeters",
+ "(D)Landroid/location/CorrelationVector$Builder;");
+ method_correlationVectorBuilderSetSamplingWidthMeters =
+ env->GetMethodID(class_correlationVectorBuilder, "setSamplingWidthMeters",
+ "(D)Landroid/location/CorrelationVector$Builder;");
+ method_correlationVectorBuilderBuild =
+ env->GetMethodID(class_correlationVectorBuilder, "build",
+ "()Landroid/location/CorrelationVector;");
+
+ jclass arrayListClass = env->FindClass("java/util/ArrayList");
+ class_arrayList = (jclass)env->NewGlobalRef(arrayListClass);
+ method_arrayListCtor = env->GetMethodID(class_arrayList, "<init>", "()V");
+ method_arrayListAdd = env->GetMethodID(class_arrayList, "add", "(Ljava/lang/Object;)Z");
}
void setMeasurementData(JNIEnv* env, jobject& callbacksObj, jobject clock,
@@ -310,6 +350,47 @@
env->DeleteLocalRef(satellitePvtObject);
}
+ if (measurement.flags & static_cast<uint32_t>(GnssMeasurement::HAS_CORRELATION_VECTOR)) {
+ jobject correlationVectorList = env->NewObject(class_arrayList, method_arrayListCtor);
+ for (uint16_t i = 0; i < measurement.correlationVectors.size(); ++i) {
+ const CorrelationVector& correlationVector = measurement.correlationVectors[i];
+ const std::vector<int32_t>& magnitudeVector = correlationVector.magnitude;
+
+ jsize numMagnitude = magnitudeVector.size();
+ jintArray magnitudeArray = env->NewIntArray(numMagnitude);
+ env->SetIntArrayRegion(magnitudeArray, 0, numMagnitude,
+ reinterpret_cast<const jint*>(magnitudeVector.data()));
+
+ jobject correlationVectorBuilderObject =
+ env->NewObject(class_correlationVectorBuilder,
+ method_correlationVectorBuilderCtor);
+ env->CallObjectMethod(correlationVectorBuilderObject,
+ method_correlationVectorBuilderSetMagnitude, magnitudeArray);
+ env->CallObjectMethod(correlationVectorBuilderObject,
+ method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond,
+ correlationVector.frequencyOffsetMps);
+ env->CallObjectMethod(correlationVectorBuilderObject,
+ method_correlationVectorBuilderSetSamplingStartMeters,
+ correlationVector.samplingStartM);
+ env->CallObjectMethod(correlationVectorBuilderObject,
+ method_correlationVectorBuilderSetSamplingWidthMeters,
+ correlationVector.samplingWidthM);
+ jobject correlationVectorObject =
+ env->CallObjectMethod(correlationVectorBuilderObject,
+ method_correlationVectorBuilderBuild);
+
+ env->CallBooleanMethod(correlationVectorList, method_arrayListAdd,
+ correlationVectorObject);
+
+ env->DeleteLocalRef(magnitudeArray);
+ env->DeleteLocalRef(correlationVectorBuilderObject);
+ env->DeleteLocalRef(correlationVectorObject);
+ }
+ env->CallVoidMethod(object.get(), method_gnssMeasurementsSetCorrelationVectors,
+ correlationVectorList);
+ env->DeleteLocalRef(correlationVectorList);
+ }
+
jstring codeType = env->NewStringUTF(measurement.signalType.codeType.c_str());
SET(CodeType, codeType);
env->DeleteLocalRef(codeType);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 4fe2752..2975800 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3383,6 +3383,7 @@
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REMOVE_ACTIVE_ADMIN);
enforceUserUnlocked(userHandle);
synchronized (getLockObject()) {
@@ -5143,6 +5144,7 @@
}
final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
Preconditions.checkCallAuthorization(canManageCaCerts(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_INSTALL_CA_CERT);
final String alias = mInjector.binderWithCleanCallingIdentity(() -> {
String installedAlias = mCertificateMonitor.installCaCert(
@@ -5174,6 +5176,7 @@
}
final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
Preconditions.checkCallAuthorization(canManageCaCerts(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_UNINSTALL_CA_CERT);
mInjector.binderWithCleanCallingIdentity(() -> {
mCertificateMonitor.uninstallCaCerts(caller.getUserHandle(), aliases);
@@ -5203,6 +5206,7 @@
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
&& (isProfileOwner(caller) || isDeviceOwner(caller)))
|| (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_INSTALL_KEY_PAIR);
final long id = mInjector.binderClearCallingIdentity();
try {
@@ -5260,6 +5264,7 @@
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
&& (isProfileOwner(caller) || isDeviceOwner(caller)))
|| (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REMOVE_KEY_PAIR);
final long id = Binder.clearCallingIdentity();
try {
@@ -6157,6 +6162,7 @@
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_ALWAYS_ON_VPN_PACKAGE);
final int userId = caller.getUserId();
mInjector.binderWithCleanCallingIdentity(() -> {
@@ -6500,6 +6506,8 @@
CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller)
|| isProfileOwnerOfOrganizationOwnedDevice(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager
+ .OPERATION_SET_FACTORY_RESET_PROTECTION_POLICY);
final int frpManagementAgentUid = getFrpManagementAgentUidOrThrow();
synchronized (getLockObject()) {
@@ -7397,6 +7405,7 @@
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller));
checkAllUsersAreAffiliatedWithDevice();
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REQUEST_BUGREPORT);
if (mBugreportCollectionManager.requestBugreport()) {
DevicePolicyEventLogger
@@ -7506,6 +7515,7 @@
if (parent) {
Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller));
}
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_CAMERA_DISABLED);
final int userHandle = caller.getUserId();
synchronized (getLockObject()) {
@@ -9256,6 +9266,7 @@
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_RESTRICTIONS_PROVIDER);
synchronized (getLockObject()) {
int userHandle = caller.getUserId();
@@ -9854,8 +9865,14 @@
final long id = mInjector.binderClearCallingIdentity();
try {
- manageUserUnchecked(admin, profileOwner, userHandle, adminExtras,
- /* showDisclaimer= */ true);
+ if (!mInjector.userManagerIsHeadlessSystemUserMode()) {
+ manageUserUnchecked(admin, profileOwner, userHandle, adminExtras,
+ /* showDisclaimer= */ true);
+ } else if (VERBOSE_LOG) {
+ Slog.v(LOG_TAG, "createAndManageUser(): skipping manageUserUnchecked() on user "
+ + userHandle + " on headless system user as it will be called by "
+ + "handleNewUserCreated()");
+ }
if ((flags & DevicePolicyManager.SKIP_SETUP_WIZARD) != 0) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
@@ -9911,12 +9928,24 @@
}
private void handleNewUserCreated(UserInfo user) {
- if (!mOwners.hasDeviceOwner()) return;
+ if (VERBOSE_LOG) Slog.v(LOG_TAG, "handleNewUserCreated(): " + user.toFullString());
+
+ if (!mOwners.hasDeviceOwner() || !user.isFull() || user.isManagedProfile()) return;
final int userId = user.id;
- Log.i(LOG_TAG, "User " + userId + " added on DO mode; setting ShowNewUserDisclaimer");
- setShowNewUserDisclaimer(userId, DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED);
+ // TODO(b/177547285): add CTS test
+ if (mInjector.userManagerIsHeadlessSystemUserMode()) {
+ ComponentName admin = mOwners.getDeviceOwnerComponent();
+ Slog.i(LOG_TAG, "Automatically setting profile owner (" + admin + ") on new user "
+ + userId);
+ manageUserUnchecked(/* deviceOwner= */ admin, /* profileOwner= */ admin,
+ /* managedUser= */ userId, /* adminExtras= */ null,
+ /* showDisclaimer= */ true);
+ } else {
+ Log.i(LOG_TAG, "User " + userId + " added on DO mode; setting ShowNewUserDisclaimer");
+ setShowNewUserDisclaimer(userId, DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED);
+ }
}
@Override
@@ -11413,6 +11442,7 @@
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_MASTER_VOLUME_MUTED);
synchronized (getLockObject()) {
setUserRestriction(who, UserManager.DISALLOW_UNMUTE_DEVICE, on, /* parent */ false);
@@ -12389,6 +12419,7 @@
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
&& (isProfileOwner(caller) || isDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PERMISSION_GRANT)));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_PERMISSION_POLICY);
synchronized (getLockObject()) {
DevicePolicyData userPolicy = getUserData(caller.getUserId());
@@ -12424,6 +12455,7 @@
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
&& (isProfileOwner(caller) || isDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PERMISSION_GRANT)));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_PERMISSION_GRANT_STATE);
synchronized (getLockObject()) {
long ident = mInjector.binderClearCallingIdentity();
@@ -14400,6 +14432,7 @@
final CallerIdentity caller = getCallerIdentity(admin);
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_CLEAR_APPLICATION_USER_DATA);
long ident = mInjector.binderClearCallingIdentity();
try {
@@ -14431,6 +14464,7 @@
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOGOUT_ENABLED);
synchronized (getLockObject()) {
ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
@@ -14798,6 +14832,8 @@
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_OVERRIDE_APNS_ENABLED);
+
setOverrideApnsEnabledUnchecked(enabled);
}
@@ -14899,6 +14935,7 @@
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_GLOBAL_PRIVATE_DNS);
switch (mode) {
case PRIVATE_DNS_MODE_OPPORTUNISTIC:
@@ -14971,6 +15008,7 @@
final CallerIdentity caller = getCallerIdentity(admin);
Preconditions.checkCallAuthorization(isDeviceOwner(caller)
|| isProfileOwnerOfOrganizationOwnedDevice(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_INSTALL_SYSTEM_UPDATE);
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.INSTALL_SYSTEM_UPDATE)
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 94df185..57b3e8d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -160,7 +160,7 @@
import com.android.server.pm.dex.SystemServerDexLoadReporter;
import com.android.server.policy.PermissionPolicyService;
import com.android.server.policy.PhoneWindowManager;
-import com.android.server.policy.role.LegacyRoleResolutionPolicy;
+import com.android.server.policy.role.LegacyRoleStateProviderImpl;
import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
import com.android.server.power.ThermalManagerService;
@@ -2021,7 +2021,7 @@
// Grants default permissions and defines roles
t.traceBegin("StartRoleManagerService");
mSystemServiceManager.startService(new RoleManagerService(
- mSystemContext, new LegacyRoleResolutionPolicy(mSystemContext)));
+ mSystemContext, new LegacyRoleStateProviderImpl(mSystemContext)));
t.traceEnd();
// We need to always start this service, regardless of whether the
diff --git a/services/people/java/com/android/server/people/PeopleService.java b/services/people/java/com/android/server/people/PeopleService.java
index 16b9165..091e688 100644
--- a/services/people/java/com/android/server/people/PeopleService.java
+++ b/services/people/java/com/android/server/people/PeopleService.java
@@ -188,6 +188,9 @@
ConversationStatus status) {
handleIncomingUser(userId);
checkCallerIsSameApp(packageName);
+ if (status.getStartTimeMillis() > System.currentTimeMillis()) {
+ throw new IllegalArgumentException("Start time must be in the past");
+ }
mDataManager.addOrUpdateStatus(packageName, userId, conversationId, status);
}
diff --git a/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java b/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java
index e4daddc..0a85f7f 100644
--- a/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java
+++ b/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java
@@ -85,8 +85,10 @@
}
@WorkerThread
- synchronized void delete(@NonNull String fileName) {
- mScheduledFileDataMap.remove(fileName);
+ void delete(@NonNull String fileName) {
+ synchronized (this) {
+ mScheduledFileDataMap.remove(fileName);
+ }
final File file = getFile(fileName);
if (!file.exists()) {
return;
@@ -136,28 +138,6 @@
}
/**
- * Reads all files in directory and returns a map with file names as keys and parsed file
- * contents as values.
- */
- @WorkerThread
- @Nullable
- Map<String, T> readAll() {
- File[] files = mRootDir.listFiles(File::isFile);
- if (files == null) {
- return null;
- }
-
- Map<String, T> results = new ArrayMap<>();
- for (File file : files) {
- T result = parseFile(file);
- if (result != null) {
- results.put(file.getName(), result);
- }
- }
- return results;
- }
-
- /**
* Schedules the specified data to be flushed to a file in the future. Subsequent
* calls for the same file before the flush occurs will replace the previous data but will not
* reset when the flush will occur. All unique files will be flushed at the same time.
diff --git a/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java b/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java
new file mode 100644
index 0000000..c631026
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.UserIdInt;
+import android.app.ActivityManager;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.app.people.ConversationStatus;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.CancellationSignal;
+import android.os.SystemClock;
+
+import com.android.server.LocalServices;
+import com.android.server.notification.NotificationRecord;
+import com.android.server.people.PeopleServiceInternal;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * If a {@link ConversationStatus} is added to the system with an expiration time, remove that
+ * status at that time
+ */
+public class ConversationStatusExpirationBroadcastReceiver extends BroadcastReceiver {
+
+ static final String ACTION = "ConversationStatusExpiration";
+ static final String EXTRA_USER_ID = "userId";
+ static final int REQUEST_CODE = 10;
+ static final String SCHEME = "expStatus";
+
+ void scheduleExpiration(Context context, @UserIdInt int userId, String pkg,
+ String conversationId, ConversationStatus status) {
+
+ final PendingIntent pi = PendingIntent.getBroadcast(context,
+ REQUEST_CODE,
+ new Intent(ACTION)
+ .setData(new Uri.Builder().scheme(SCHEME)
+ .appendPath(getKey(userId, pkg, conversationId, status))
+ .build())
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+ .putExtra(EXTRA_USER_ID, userId),
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+ context.getSystemService(AlarmManager.class).setExactAndAllowWhileIdle(
+ AlarmManager.RTC_WAKEUP, status.getEndTimeMillis(), pi);
+ }
+
+ private static String getKey(@UserIdInt int userId, String pkg,
+ String conversationId, ConversationStatus status) {
+ return userId + pkg + conversationId + status.getId();
+ }
+
+ static IntentFilter getFilter() {
+ IntentFilter conversationStatusFilter =
+ new IntentFilter(ConversationStatusExpirationBroadcastReceiver.ACTION);
+ conversationStatusFilter.addDataScheme(
+ ConversationStatusExpirationBroadcastReceiver.SCHEME);
+ return conversationStatusFilter;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action == null) {
+ return;
+ }
+ if (ACTION.equals(action)) {
+ new Thread(() -> {
+ PeopleServiceInternal peopleServiceInternal =
+ LocalServices.getService(PeopleServiceInternal.class);
+ peopleServiceInternal.pruneDataForUser(intent.getIntExtra(EXTRA_USER_ID,
+ ActivityManager.getCurrentUser()), new CancellationSignal());
+ }).start();
+ }
+ }
+}
diff --git a/services/people/java/com/android/server/people/data/ConversationStore.java b/services/people/java/com/android/server/people/data/ConversationStore.java
index 28e3d4b..6faeb80 100644
--- a/services/people/java/com/android/server/people/data/ConversationStore.java
+++ b/services/people/java/com/android/server/people/data/ConversationStore.java
@@ -90,7 +90,7 @@
* after the device powers on and the user has been unlocked.
*/
@WorkerThread
- synchronized void loadConversationsFromDisk() {
+ void loadConversationsFromDisk() {
ConversationInfosProtoDiskReadWriter conversationInfosProtoDiskReadWriter =
getConversationInfosProtoDiskReadWriter();
if (conversationInfosProtoDiskReadWriter == null) {
@@ -111,54 +111,64 @@
* powering off.
*/
@MainThread
- synchronized void saveConversationsToDisk() {
+ void saveConversationsToDisk() {
ConversationInfosProtoDiskReadWriter conversationInfosProtoDiskReadWriter =
getConversationInfosProtoDiskReadWriter();
if (conversationInfosProtoDiskReadWriter != null) {
- conversationInfosProtoDiskReadWriter.saveConversationsImmediately(
- new ArrayList<>(mConversationInfoMap.values()));
+ List<ConversationInfo> conversations;
+ synchronized (this) {
+ conversations = new ArrayList<>(mConversationInfoMap.values());
+ }
+ conversationInfosProtoDiskReadWriter.saveConversationsImmediately(conversations);
}
}
@MainThread
- synchronized void addOrUpdate(@NonNull ConversationInfo conversationInfo) {
+ void addOrUpdate(@NonNull ConversationInfo conversationInfo) {
updateConversationsInMemory(conversationInfo);
scheduleUpdateConversationsOnDisk();
}
@MainThread
@Nullable
- synchronized ConversationInfo deleteConversation(@NonNull String shortcutId) {
- ConversationInfo conversationInfo = mConversationInfoMap.remove(shortcutId);
- if (conversationInfo == null) {
- return null;
- }
+ ConversationInfo deleteConversation(@NonNull String shortcutId) {
+ ConversationInfo conversationInfo;
+ synchronized (this) {
+ conversationInfo = mConversationInfoMap.remove(shortcutId);
+ if (conversationInfo == null) {
+ return null;
+ }
- LocusId locusId = conversationInfo.getLocusId();
- if (locusId != null) {
- mLocusIdToShortcutIdMap.remove(locusId);
- }
+ LocusId locusId = conversationInfo.getLocusId();
+ if (locusId != null) {
+ mLocusIdToShortcutIdMap.remove(locusId);
+ }
- Uri contactUri = conversationInfo.getContactUri();
- if (contactUri != null) {
- mContactUriToShortcutIdMap.remove(contactUri);
- }
+ Uri contactUri = conversationInfo.getContactUri();
+ if (contactUri != null) {
+ mContactUriToShortcutIdMap.remove(contactUri);
+ }
- String phoneNumber = conversationInfo.getContactPhoneNumber();
- if (phoneNumber != null) {
- mPhoneNumberToShortcutIdMap.remove(phoneNumber);
- }
+ String phoneNumber = conversationInfo.getContactPhoneNumber();
+ if (phoneNumber != null) {
+ mPhoneNumberToShortcutIdMap.remove(phoneNumber);
+ }
- String notifChannelId = conversationInfo.getNotificationChannelId();
- if (notifChannelId != null) {
- mNotifChannelIdToShortcutIdMap.remove(notifChannelId);
+ String notifChannelId = conversationInfo.getNotificationChannelId();
+ if (notifChannelId != null) {
+ mNotifChannelIdToShortcutIdMap.remove(notifChannelId);
+ }
}
scheduleUpdateConversationsOnDisk();
return conversationInfo;
}
- synchronized void forAllConversations(@NonNull Consumer<ConversationInfo> consumer) {
- for (ConversationInfo ci : mConversationInfoMap.values()) {
+ void forAllConversations(@NonNull Consumer<ConversationInfo> consumer) {
+ List<ConversationInfo> conversations;
+ synchronized (this) {
+ conversations = new ArrayList<>(mConversationInfoMap.values());
+ }
+ for (ConversationInfo ci : conversations) {
consumer.accept(ci);
}
}
@@ -184,16 +194,19 @@
}
@Nullable
- ConversationInfo getConversationByNotificationChannelId(@NonNull String notifChannelId) {
+ synchronized ConversationInfo getConversationByNotificationChannelId(
+ @NonNull String notifChannelId) {
return getConversation(mNotifChannelIdToShortcutIdMap.get(notifChannelId));
}
- synchronized void onDestroy() {
- mConversationInfoMap.clear();
- mContactUriToShortcutIdMap.clear();
- mLocusIdToShortcutIdMap.clear();
- mNotifChannelIdToShortcutIdMap.clear();
- mPhoneNumberToShortcutIdMap.clear();
+ void onDestroy() {
+ synchronized (this) {
+ mConversationInfoMap.clear();
+ mContactUriToShortcutIdMap.clear();
+ mLocusIdToShortcutIdMap.clear();
+ mNotifChannelIdToShortcutIdMap.clear();
+ mPhoneNumberToShortcutIdMap.clear();
+ }
ConversationInfosProtoDiskReadWriter writer = getConversationInfosProtoDiskReadWriter();
if (writer != null) {
writer.deleteConversationsFile();
@@ -201,22 +214,21 @@
}
@Nullable
- synchronized byte[] getBackupPayload() {
+ byte[] getBackupPayload() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream conversationInfosOut = new DataOutputStream(baos);
- for (ConversationInfo conversationInfo : mConversationInfoMap.values()) {
+ forAllConversations(conversationInfo -> {
byte[] backupPayload = conversationInfo.getBackupPayload();
if (backupPayload == null) {
- continue;
+ return;
}
try {
conversationInfosOut.writeInt(backupPayload.length);
conversationInfosOut.write(backupPayload);
} catch (IOException e) {
Slog.e(TAG, "Failed to write conversation info to backup payload.", e);
- return null;
}
- }
+ });
try {
conversationInfosOut.writeInt(CONVERSATION_INFOS_END_TOKEN);
} catch (IOException e) {
@@ -226,7 +238,7 @@
return baos.toByteArray();
}
- synchronized void restore(@NonNull byte[] payload) {
+ void restore(@NonNull byte[] payload) {
DataInputStream in = new DataInputStream(new ByteArrayInputStream(payload));
try {
for (int conversationInfoSize = in.readInt();
@@ -245,7 +257,6 @@
}
}
- @MainThread
private synchronized void updateConversationsInMemory(
@NonNull ConversationInfo conversationInfo) {
mConversationInfoMap.put(conversationInfo.getShortcutId(), conversationInfo);
@@ -273,12 +284,15 @@
/** Schedules a dump of all conversations onto disk, overwriting existing values. */
@MainThread
- private synchronized void scheduleUpdateConversationsOnDisk() {
+ private void scheduleUpdateConversationsOnDisk() {
ConversationInfosProtoDiskReadWriter conversationInfosProtoDiskReadWriter =
getConversationInfosProtoDiskReadWriter();
if (conversationInfosProtoDiskReadWriter != null) {
- conversationInfosProtoDiskReadWriter.scheduleConversationsSave(
- new ArrayList<>(mConversationInfoMap.values()));
+ List<ConversationInfo> conversations;
+ synchronized (this) {
+ conversations = new ArrayList<>(mConversationInfoMap.values());
+ }
+ conversationInfosProtoDiskReadWriter.scheduleConversationsSave(conversations);
}
}
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index e04e287..7521415 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -124,6 +124,7 @@
private PackageManagerInternal mPackageManagerInternal;
private NotificationManagerInternal mNotificationManagerInternal;
private UserManager mUserManager;
+ private ConversationStatusExpirationBroadcastReceiver mStatusExpReceiver;
public DataManager(Context context) {
this(context, new Injector());
@@ -145,6 +146,10 @@
mShortcutServiceInternal.addShortcutChangeCallback(new ShortcutServiceCallback());
+ mStatusExpReceiver = new ConversationStatusExpirationBroadcastReceiver();
+ mContext.registerReceiver(mStatusExpReceiver,
+ ConversationStatusExpirationBroadcastReceiver.getFilter());
+
IntentFilter shutdownIntentFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
BroadcastReceiver shutdownBroadcastReceiver = new ShutdownBroadcastReceiver();
mContext.registerReceiver(shutdownBroadcastReceiver, shutdownIntentFilter);
@@ -296,6 +301,27 @@
}
/**
+ * Removes any status with an expiration time in the past.
+ */
+ public void pruneExpiredConversationStatuses(@UserIdInt int callingUserId, long currentTimeMs) {
+ forPackagesInProfile(callingUserId, packageData -> {
+ final ConversationStore cs = packageData.getConversationStore();
+ packageData.forAllConversations(conversationInfo -> {
+ ConversationInfo.Builder builder = new ConversationInfo.Builder(conversationInfo);
+ List<ConversationStatus> newStatuses = new ArrayList<>();
+ for (ConversationStatus status : conversationInfo.getStatuses()) {
+ if (status.getEndTimeMillis() < 0
+ || currentTimeMs < status.getEndTimeMillis()) {
+ newStatuses.add(status);
+ }
+ }
+ builder.setStatuses(newStatuses);
+ cs.addOrUpdate(builder.build());
+ });
+ });
+ }
+
+ /**
* Returns the last notification interaction with the specified conversation. If the
* conversation can't be found or no interactions have been recorded, returns 0L.
*/
@@ -317,6 +343,12 @@
ConversationInfo.Builder builder = new ConversationInfo.Builder(convToModify);
builder.addOrUpdateStatus(status);
cs.addOrUpdate(builder.build());
+
+ if (status.getEndTimeMillis() >= 0) {
+ mStatusExpReceiver.scheduleExpiration(
+ mContext, userId, packageName, conversationId, status);
+ }
+
}
public void clearStatus(String packageName, int userId, String conversationId,
@@ -458,6 +490,7 @@
packageData.getEventStore().deleteEventHistories(EventStore.CATEGORY_SMS);
}
packageData.pruneOrphanEvents();
+ pruneExpiredConversationStatuses(userId, System.currentTimeMillis());
pruneOldRecentConversations(userId, System.currentTimeMillis());
cleanupCachedShortcuts(userId, MAX_CACHED_RECENT_SHORTCUTS);
});
diff --git a/services/searchui/OWNERS b/services/searchui/OWNERS
new file mode 100644
index 0000000..92835c2
--- /dev/null
+++ b/services/searchui/OWNERS
@@ -0,0 +1,2 @@
+hyunyoungs@google.com
+sfufa@google.com
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/src/com/android/server/pm/test/intent/verifier/VerifyReceiverTest.kt b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/src/com/android/server/pm/test/intent/verifier/VerifyReceiverTest.kt
index 6de3d4e..23ed278 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/src/com/android/server/pm/test/intent/verifier/VerifyReceiverTest.kt
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/src/com/android/server/pm/test/intent/verifier/VerifyReceiverTest.kt
@@ -77,12 +77,14 @@
val filter = IntentFilter().apply {
addAction(Intent.ACTION_VIEW)
addCategory(Intent.CATEGORY_DEFAULT)
+ addCategory(Intent.CATEGORY_BROWSABLE)
addDataScheme(uri.scheme)
addDataAuthority(uri.authority, null)
}
val intent = Intent(Intent.ACTION_VIEW, uri).apply {
addCategory(Intent.CATEGORY_DEFAULT)
+ addCategory(Intent.CATEGORY_BROWSABLE)
}
val allResults = context.packageManager.queryIntentActivities(intent, 0)
val allComponents = allResults
@@ -132,6 +134,8 @@
val intent = Intent(Intent.ACTION_VIEW).apply {
data = uri
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ addCategory(Intent.CATEGORY_DEFAULT)
+ addCategory(Intent.CATEGORY_BROWSABLE)
}
val expectedActivities = params.expected.toMutableList()
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java b/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java
index 675274b..69fe140 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java
@@ -233,6 +233,7 @@
private boolean mAntennaInfoListeningStarted = false;
private boolean mMeasurementCollectionStarted = false;
private boolean mMeasurementCollectionFullTracking = false;
+ private boolean mMeasurementCollectionCorrVecOutputsEnabled = false;
private GnssHalPositionMode mPositionMode = new GnssHalPositionMode();
private GnssHalBatchingMode mBatchingMode = new GnssHalBatchingMode();
private final ArrayList<Location> mBatchedLocations = new ArrayList<>();
@@ -521,9 +522,11 @@
}
@Override
- protected boolean startMeasurementCollection(boolean enableFullTracking) {
+ protected boolean startMeasurementCollection(boolean enableFullTracking,
+ boolean enableCorrVecOutputs) {
mState.mMeasurementCollectionStarted = true;
mState.mMeasurementCollectionFullTracking = enableFullTracking;
+ mState.mMeasurementCollectionCorrVecOutputsEnabled = enableCorrVecOutputs;
return true;
}
@@ -531,6 +534,7 @@
protected boolean stopMeasurementCollection() {
mState.mMeasurementCollectionStarted = false;
mState.mMeasurementCollectionFullTracking = false;
+ mState.mMeasurementCollectionCorrVecOutputsEnabled = false;
return true;
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java
index 99aab5c..392535e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java
@@ -16,6 +16,8 @@
package com.android.server.biometrics.sensors.face.hidl;
+import static junit.framework.Assert.assertEquals;
+
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -76,6 +78,12 @@
}
@Test
+ public void getAuthenticatorId_doesNotCrashWhenIdNotFound() {
+ assertEquals(0, mFace10.getAuthenticatorId(0 /* sensorId */, 111 /* userId */));
+ waitForIdle();
+ }
+
+ @Test
public void scheduleRevokeChallenge_doesNotCrash() {
mFace10.scheduleRevokeChallenge(0 /* sensorId */, 0 /* userId */, mBinder, TAG,
0 /* challenge */);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
index b2aeb33..61cc8e6 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
@@ -16,6 +16,8 @@
package com.android.server.biometrics.sensors.fingerprint.hidl;
+import static junit.framework.Assert.assertEquals;
+
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -85,6 +87,12 @@
}
@Test
+ public void getAuthenticatorId_doesNotCrashWhenIdNotFound() {
+ assertEquals(0, mFingerprint21.getAuthenticatorId(0 /* sensorId */, 111 /* userId */));
+ waitForIdle();
+ }
+
+ @Test
public void halServiceDied_resetsScheduler() {
// It's difficult to test the linkToDeath --> serviceDied path, so let's just invoke
// serviceDied directly.
diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
new file mode 100644
index 0000000..0cf0af3
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.graphics.fonts;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.content.Context;
+import android.os.FileUtils;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Map;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public final class UpdatableFontDirTest {
+
+ /**
+ * A {@link UpdatableFontDir.FontFileParser} for testing. Instead of using real font files,
+ * this test uses fake font files. A fake font file has its version as its file content.
+ */
+ private static class FakeFontFileParser implements UpdatableFontDir.FontFileParser {
+ @Override
+ public long getVersion(File file) throws IOException {
+ return Long.parseLong(FileUtils.readTextFile(file, 100, ""));
+ }
+ }
+
+ private File mCacheDir;
+ private File mUpdatableFontFilesDir;
+
+ @SuppressWarnings("ResultOfMethodCallIgnored")
+ @Before
+ public void setUp() {
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mCacheDir = new File(context.getCacheDir(), "UpdatableFontDirTest");
+ FileUtils.deleteContentsAndDir(mCacheDir);
+ mCacheDir.mkdirs();
+ mUpdatableFontFilesDir = new File(mCacheDir, "updatable_fonts");
+ mUpdatableFontFilesDir.mkdir();
+ }
+
+ @After
+ public void tearDown() {
+ FileUtils.deleteContentsAndDir(mCacheDir);
+ }
+
+ @Test
+ public void construct() throws Exception {
+ FakeFontFileParser parser = new FakeFontFileParser();
+ UpdatableFontDir dirForPreparation = new UpdatableFontDir(mUpdatableFontFilesDir, parser);
+ installFontFile(dirForPreparation, "foo.ttf", "1");
+ installFontFile(dirForPreparation, "bar.ttf", "2");
+ installFontFile(dirForPreparation, "foo.ttf", "3");
+ installFontFile(dirForPreparation, "bar.ttf", "4");
+ // Four font dirs are created.
+ assertThat(mUpdatableFontFilesDir.list()).hasLength(4);
+
+ UpdatableFontDir dir = new UpdatableFontDir(mUpdatableFontFilesDir, parser);
+ assertThat(dir.getFontFileMap()).containsKey("foo.ttf");
+ assertThat(parser.getVersion(dir.getFontFileMap().get("foo.ttf"))).isEqualTo(3);
+ assertThat(dir.getFontFileMap()).containsKey("bar.ttf");
+ assertThat(parser.getVersion(dir.getFontFileMap().get("bar.ttf"))).isEqualTo(4);
+ // Outdated font dir should be deleted.
+ assertThat(mUpdatableFontFilesDir.list()).hasLength(2);
+ }
+
+ @Test
+ public void construct_empty() {
+ FakeFontFileParser parser = new FakeFontFileParser();
+ UpdatableFontDir dir = new UpdatableFontDir(mUpdatableFontFilesDir, parser);
+ assertThat(dir.getFontFileMap()).isEmpty();
+ }
+
+ @Test
+ public void installFontFile() throws Exception {
+ FakeFontFileParser parser = new FakeFontFileParser();
+ UpdatableFontDir dir = new UpdatableFontDir(mUpdatableFontFilesDir, parser);
+
+ installFontFile(dir, "test.ttf", "1");
+ assertThat(dir.getFontFileMap()).containsKey("test.ttf");
+ assertThat(parser.getVersion(dir.getFontFileMap().get("test.ttf"))).isEqualTo(1);
+ }
+
+ @Test
+ public void installFontFile_upgrade() throws Exception {
+ FakeFontFileParser parser = new FakeFontFileParser();
+ UpdatableFontDir dir = new UpdatableFontDir(mUpdatableFontFilesDir, parser);
+
+ installFontFile(dir, "test.ttf", "1");
+ Map<String, File> mapBeforeUpgrade = dir.getFontFileMap();
+ installFontFile(dir, "test.ttf", "2");
+ assertThat(dir.getFontFileMap()).containsKey("test.ttf");
+ assertThat(parser.getVersion(dir.getFontFileMap().get("test.ttf"))).isEqualTo(2);
+ assertThat(mapBeforeUpgrade).containsKey("test.ttf");
+ assertWithMessage("Older fonts should not be deleted until next loadFontFileMap")
+ .that(parser.getVersion(mapBeforeUpgrade.get("test.ttf"))).isEqualTo(1);
+ }
+
+ @Test
+ public void installFontFile_downgrade() throws Exception {
+ FakeFontFileParser parser = new FakeFontFileParser();
+ UpdatableFontDir dir = new UpdatableFontDir(mUpdatableFontFilesDir, parser);
+
+ installFontFile(dir, "test.ttf", "2");
+ installFontFile(dir, "test.ttf", "1");
+ assertThat(dir.getFontFileMap()).containsKey("test.ttf");
+ assertWithMessage("Font should not be downgraded to an older version")
+ .that(parser.getVersion(dir.getFontFileMap().get("test.ttf"))).isEqualTo(2);
+ }
+
+ @Test
+ public void installFontFile_multiple() throws Exception {
+ FakeFontFileParser parser = new FakeFontFileParser();
+ UpdatableFontDir dir = new UpdatableFontDir(mUpdatableFontFilesDir, parser);
+
+ installFontFile(dir, "foo.ttf", "1");
+ installFontFile(dir, "bar.ttf", "2");
+ assertThat(dir.getFontFileMap()).containsKey("foo.ttf");
+ assertThat(parser.getVersion(dir.getFontFileMap().get("foo.ttf"))).isEqualTo(1);
+ assertThat(dir.getFontFileMap()).containsKey("bar.ttf");
+ assertThat(parser.getVersion(dir.getFontFileMap().get("bar.ttf"))).isEqualTo(2);
+ }
+
+ private void installFontFile(UpdatableFontDir dir, String name, String content)
+ throws IOException {
+ File file = File.createTempFile(name, "", mCacheDir);
+ FileUtils.stringToFile(file, content);
+ try (FileInputStream in = new FileInputStream(file)) {
+ dir.installFontFile(name, in.getFD());
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java b/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
index b7d9a56..a7b32ac 100644
--- a/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
@@ -41,6 +41,7 @@
import android.util.Log;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
@@ -134,6 +135,7 @@
assertTrue("Job did not start after scheduling", awaitJobStart(DEFAULT_WAIT_TIMEOUT));
}
+ @FlakyTest
@Test
public void testPowerExemption() throws Exception {
scheduleAndAssertJobStarted();
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index be8a99c..63330d5 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -42,12 +42,14 @@
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -141,6 +143,7 @@
@Mock private JobScheduler mJobScheduler;
@Mock private StatusBarNotification mStatusBarNotification;
@Mock private Notification mNotification;
+ @Mock private AlarmManager mAlarmManager;
@Captor private ArgumentCaptor<ShortcutChangeCallback> mShortcutChangeCallbackCaptor;
@Captor private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor;
@@ -152,7 +155,6 @@
private DataManager mDataManager;
private CancellationSignal mCancellationSignal;
private ShortcutChangeCallback mShortcutChangeCallback;
- private BroadcastReceiver mShutdownBroadcastReceiver;
private ShortcutInfo mShortcutInfo;
private TestInjector mInjector;
@@ -187,10 +189,15 @@
Context originalContext = getInstrumentation().getTargetContext();
when(mContext.getApplicationInfo()).thenReturn(originalContext.getApplicationInfo());
+ when(mContext.getUser()).thenReturn(originalContext.getUser());
+ when(mContext.getPackageName()).thenReturn(originalContext.getPackageName());
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
when(mContext.getSystemServiceName(UserManager.class)).thenReturn(
Context.USER_SERVICE);
+ when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mAlarmManager);
+ when(mContext.getSystemServiceName(AlarmManager.class)).thenReturn(
+ Context.ALARM_SERVICE);
when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
@@ -246,8 +253,7 @@
mShortcutChangeCallbackCaptor.capture());
mShortcutChangeCallback = mShortcutChangeCallbackCaptor.getValue();
- verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any());
- mShutdownBroadcastReceiver = mBroadcastReceiverCaptor.getValue();
+ verify(mContext, times(2)).registerReceiver(any(), any());
}
@After
@@ -767,6 +773,36 @@
}
@Test
+ public void testPruneExpiredConversationStatuses() {
+ mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+ ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+ buildPerson());
+ mDataManager.addOrUpdateConversationInfo(shortcut);
+
+ ConversationStatus cs1 = new ConversationStatus.Builder("cs1", 9)
+ .setEndTimeMillis(System.currentTimeMillis())
+ .build();
+ ConversationStatus cs2 = new ConversationStatus.Builder("cs2", 10)
+ .build();
+ ConversationStatus cs3 = new ConversationStatus.Builder("cs3", 1)
+ .setEndTimeMillis(Long.MAX_VALUE)
+ .build();
+ mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs1);
+ mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2);
+ mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs3);
+
+ mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal);
+
+ assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
+ .doesNotContain(cs1);
+ assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
+ .contains(cs2);
+ assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
+ .contains(cs3);
+ }
+
+ @Test
public void testDoNotUncacheShortcutWithActiveNotifications() {
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
NotificationListenerService listenerService =
@@ -976,6 +1012,29 @@
.contains(cs);
assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
.contains(cs2);
+
+ verify(mAlarmManager, never()).setExactAndAllowWhileIdle(anyInt(), anyLong(), any());
+ }
+
+ @Test
+ public void testAddOrUpdateStatus_schedulesJob() {
+ mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+ ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+ buildPerson());
+ mDataManager.addOrUpdateConversationInfo(shortcut);
+
+ ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY)
+ .setEndTimeMillis(1000)
+ .build();
+ mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs);
+
+ ConversationStatus cs2 = new ConversationStatus.Builder("id2", ACTIVITY_GAME)
+ .setEndTimeMillis(3000)
+ .build();
+ mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2);
+
+ verify(mAlarmManager, times(2)).setExactAndAllowWhileIdle(anyInt(), anyLong(), any());
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
index 3858370..aadab6e 100644
--- a/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
@@ -25,6 +25,7 @@
import android.media.tv.ITvInputManager;
import android.media.tv.TvInputManager;
import android.media.tv.TvInputService;
+import android.media.tv.tuner.TunerFrontendInfo;
import android.media.tv.tuner.frontend.FrontendSettings;
import android.media.tv.tunerresourcemanager.CasSessionRequest;
import android.media.tv.tunerresourcemanager.IResourcesReclaimListener;
@@ -32,7 +33,6 @@
import android.media.tv.tunerresourcemanager.TunerCiCamRequest;
import android.media.tv.tunerresourcemanager.TunerDemuxRequest;
import android.media.tv.tunerresourcemanager.TunerDescramblerRequest;
-import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
import android.media.tv.tunerresourcemanager.TunerResourceManager;
@@ -88,7 +88,7 @@
}
return actual.getHandle() == expected.handle
- && actual.getType() == expected.frontendType
+ && actual.getType() == expected.type
&& actual.getExclusiveGroupId() == expected.exclusiveGroupId;
}, "is correctly configured from ");
@@ -1156,7 +1156,7 @@
int handle, int frontendType, int exclusiveGroupId) {
TunerFrontendInfo info = new TunerFrontendInfo();
info.handle = handle;
- info.frontendType = frontendType;
+ info.type = frontendType;
info.exclusiveGroupId = exclusiveGroupId;
return info;
}
diff --git a/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java b/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
index 7c65dc0..b40d59c 100644
--- a/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
@@ -254,6 +254,8 @@
tester.verify(15, "Tick after snapshot");
// Verify that the snapshot is sealed
verifySealed(name, ()->arraySnap.put(INDEX_A, leafA));
+ assertTrue(!array.isSealed());
+ assertTrue(arraySnap.isSealed());
}
// Recreate the snapshot since the test corrupted it.
{
@@ -355,6 +357,8 @@
tester.verify(16, "Tick after snapshot");
// Verify that the array snapshot is sealed
verifySealed(name, ()->arraySnap.add(leafB));
+ assertTrue(!array.isSealed());
+ assertTrue(arraySnap.isSealed());
}
// Recreate the snapshot since the test corrupted it.
{
@@ -467,6 +471,8 @@
tester.verify(20, "Tick after snapshot");
// Verify that the array snapshot is sealed
verifySealed(name, ()->arraySnap.add(indexA, leafB));
+ assertTrue(!array.isSealed());
+ assertTrue(arraySnap.isSealed());
}
// Recreate the snapshot since the test corrupted it.
{
@@ -586,6 +592,8 @@
tester.verify(23, "Tick after snapshot");
// Verify that the array snapshot is sealed
verifySealed(name, ()->arraySnap.put(INDEX_A, leafB));
+ assertTrue(!array.isSealed());
+ assertTrue(arraySnap.isSealed());
}
// Recreate the snapshot since the test corrupted it.
{
@@ -649,6 +657,8 @@
tester.verify(6, "Tick after snapshot");
// Verify that the array is sealed
verifySealed(name, ()->arraySnap.put(INDEX_D, false));
+ assertTrue(!array.isSealed());
+ assertTrue(arraySnap.isSealed());
}
// Verify copy-in/out
{
@@ -705,6 +715,8 @@
tester.verify(6, "Tick after snapshot");
// Verify that the array is sealed
verifySealed(name, ()->arraySnap.put(INDEX_D, 10));
+ assertTrue(!array.isSealed());
+ assertTrue(arraySnap.isSealed());
}
// Verify copy-in/out
{
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
index ecdb8bc..1e112da 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -29,6 +29,7 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
@@ -36,7 +37,6 @@
import android.os.Handler;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
@@ -229,9 +229,23 @@
}
@Test
- public void shouldVibrateForUid_withBackgroundAllowedUsage_returnTrue() throws RemoteException {
+ public void shouldVibrateForUid_withForegroundOnlyUsage_returnsTrueWhInForeground() {
+ assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_TOUCH));
+
+ mVibrationSettings.mUidObserver.onUidStateChanged(
+ UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0);
+ assertFalse(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_TOUCH));
+ }
+
+ @Test
+ public void shouldVibrateForUid_withBackgroundAllowedUsage_returnTrue() {
+ mVibrationSettings.mUidObserver.onUidStateChanged(
+ UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0);
+
assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_ALARM));
assertTrue(mVibrationSettings.shouldVibrateForUid(UID,
+ VibrationAttributes.USAGE_COMMUNICATION_REQUEST));
+ assertTrue(mVibrationSettings.shouldVibrateForUid(UID,
VibrationAttributes.USAGE_NOTIFICATION));
assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_RINGTONE));
}
@@ -377,5 +391,4 @@
mAudioManager.setRingerModeInternal(ringerMode);
assertEquals(ringerMode, mAudioManager.getRingerModeInternal());
}
-
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index f1dc098..6b69ee9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -351,6 +351,22 @@
}
@Test
+ public void testActivityDrawnBeforeTransition() {
+ mTopActivity.setVisible(false);
+ notifyActivityLaunching(mTopActivity.intent);
+ // Assume the activity is launched the second time consecutively. The drawn event is from
+ // the first time (omitted in test) launch that is earlier than transition.
+ doReturn(true).when(mTopActivity).isReportedDrawn();
+ notifyWindowsDrawn(mTopActivity);
+ notifyActivityLaunched(START_SUCCESS, mTopActivity);
+ // If the launching activity was drawn when starting transition, the launch event should
+ // be reported successfully.
+ notifyTransitionStarting(mTopActivity);
+
+ verifyOnActivityLaunchFinished(mTopActivity);
+ }
+
+ @Test
public void testActivityRecordProtoIsNotTooBig() {
// The ActivityRecordProto must not be too big, otherwise converting it at runtime
// will become prohibitively expensive.
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index e190248..22430a1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -20,8 +20,10 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
+import static android.view.SurfaceProto.ROTATION_180;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -39,7 +41,6 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.clearInvocations;
@@ -243,7 +244,7 @@
// The bounds should be [800, 0 - 1800, 2500].
assertEquals(origBounds.width(), currentBounds.width());
assertEquals(origBounds.height(), currentBounds.height());
- assertEquals(Configuration.ORIENTATION_LANDSCAPE, display.getConfiguration().orientation);
+ assertEquals(ORIENTATION_LANDSCAPE, display.getConfiguration().orientation);
assertEquals(Configuration.ORIENTATION_PORTRAIT, mActivity.getConfiguration().orientation);
// The previous resize operation doesn't consider the rotation change after size changed.
@@ -729,7 +730,7 @@
// Update with new activity requested orientation and recompute bounds with no previous
// size compat cache.
verify(mTask).onDescendantOrientationChanged(same(newActivity));
- verify(mTask).computeFullscreenBounds(any(), any(), any(), anyInt());
+ verify(mTask).computeFullscreenBounds(any(), any());
final Rect displayBounds = new Rect(display.getBounds());
final Rect taskBounds = new Rect(mTask.getBounds());
@@ -770,7 +771,7 @@
// Update with new activity requested orientation and recompute bounds with no previous
// size compat cache.
verify(mTask).onDescendantOrientationChanged(same(newActivity));
- verify(mTask).computeFullscreenBounds(any(), any(), any(), anyInt());
+ verify(mTask).computeFullscreenBounds(any(), any());
final Rect displayBounds = new Rect(display.getBounds());
final Rect taskBounds = new Rect(mTask.getBounds());
@@ -821,6 +822,88 @@
assertEquals(activityBounds, mActivity.getBounds());
}
+ @Test
+ public void testDisplayIgnoreOrientationRequest_rotated180_notInSizeCompat() {
+ // Set up a display in landscape and ignoring orientation request.
+ setUpDisplaySizeWithApp(2800, 1400);
+ final DisplayContent display = mActivity.mDisplayContent;
+ display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+ // Portrait fixed app.
+ prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
+
+ // In Task letterbox
+ assertTrue(mTask.isTaskLetterboxed());
+ assertFalse(mActivity.inSizeCompatMode());
+
+ // Rotate display to portrait.
+ rotateDisplay(display, ROTATION_90);
+
+ // App should be in size compat.
+ assertFalse(mTask.isTaskLetterboxed());
+ assertScaled();
+
+ // Rotate display to landscape.
+ rotateDisplay(display, ROTATION_180);
+
+ // In Task letterbox
+ assertTrue(mTask.isTaskLetterboxed());
+ assertFalse(mActivity.inSizeCompatMode());
+ }
+
+ @Test
+ public void testDisplayIgnoreOrientationRequestWithInsets_rotated180_notInSizeCompat() {
+ // Set up a display in portrait with display cutout and ignoring orientation request.
+ final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1400, 2800)
+ .setNotch(75)
+ .build();
+ setUpApp(display);
+ display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+ // Landscape fixed app.
+ prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_LANDSCAPE);
+
+ // In Task letterbox
+ assertTrue(mTask.isTaskLetterboxed());
+ assertFalse(mActivity.inSizeCompatMode());
+
+ // Rotate display to portrait.
+ rotateDisplay(display, ROTATION_90);
+
+ // App should be in size compat.
+ assertFalse(mTask.isTaskLetterboxed());
+ assertScaled();
+
+ // Rotate display to landscape.
+ rotateDisplay(display, ROTATION_180);
+
+ // In Task letterbox
+ assertTrue(mTask.isTaskLetterboxed());
+ assertFalse(mActivity.inSizeCompatMode());
+ }
+
+ @Test
+ public void testTaskDisplayAreaNotFillDisplay() {
+ setUpDisplaySizeWithApp(1400, 2800);
+ final DisplayContent display = mActivity.mDisplayContent;
+ final TaskDisplayArea taskDisplayArea = mActivity.getDisplayArea();
+ taskDisplayArea.setBounds(0, 0, 1000, 2400);
+
+ // Portrait fixed app.
+ prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_LANDSCAPE);
+
+ final Rect displayBounds = new Rect(display.getBounds());
+ assertEquals(ORIENTATION_LANDSCAPE, display.getConfiguration().orientation);
+ assertEquals(2800, displayBounds.width());
+ assertEquals(1400, displayBounds.height());
+ taskDisplayArea.setBounds(0, 0, 2400, 1000);
+
+ final Rect activityBounds = new Rect(mActivity.getBounds());
+ assertFalse(mActivity.inSizeCompatMode());
+ assertEquals(2400, activityBounds.width());
+ assertEquals(1000, activityBounds.height());
+ }
+
private static WindowState addWindowToActivity(ActivityRecord activity) {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index f1bea67..04b365f 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -109,6 +109,20 @@
*/
public abstract class Connection extends Conferenceable {
+ /**@hide*/
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "STATE_", value = {
+ STATE_INITIALIZING,
+ STATE_NEW,
+ STATE_RINGING,
+ STATE_DIALING,
+ STATE_ACTIVE,
+ STATE_HOLDING,
+ STATE_DISCONNECTED,
+ STATE_PULLING_CALL
+ })
+ public @interface ConnectionState {}
+
/**
* The connection is initializing. This is generally the first state for a {@code Connection}
* returned by a {@link ConnectionService}.
diff --git a/telephony/common/com/android/internal/telephony/SipMessageParsingUtils.java b/telephony/common/com/android/internal/telephony/SipMessageParsingUtils.java
new file mode 100644
index 0000000..c7e7cd5
--- /dev/null
+++ b/telephony/common/com/android/internal/telephony/SipMessageParsingUtils.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.net.Uri;
+import android.util.Log;
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Utility methods for parsing parts of {@link android.telephony.ims.SipMessage}s.
+ * See RFC 3261 for more information.
+ * @hide
+ */
+// Note: This is lightweight in order to avoid a full SIP stack import in frameworks/base.
+public class SipMessageParsingUtils {
+ private static final String TAG = "SipMessageParsingUtils";
+ // "Method" in request-line
+ // Request-Line = Method SP Request-URI SP SIP-Version CRLF
+ private static final String[] SIP_REQUEST_METHODS = new String[] {"INVITE", "ACK", "OPTIONS",
+ "BYE", "CANCEL", "REGISTER", "PRACK", "SUBSCRIBE", "NOTIFY", "PUBLISH", "INFO", "REFER",
+ "MESSAGE", "UPDATE"};
+
+ // SIP Version 2.0 (corresponding to RCS 3261), set in "SIP-Version" of Status-Line and
+ // Request-Line
+ //
+ // Request-Line = Method SP Request-URI SP SIP-Version CRLF
+ // Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF
+ private static final String SIP_VERSION_2 = "SIP/2.0";
+
+ // headers are formatted Key:Value
+ private static final String HEADER_KEY_VALUE_SEPARATOR = ":";
+ // Multiple of the same header can be concatenated and put into one header Key:Value pair, for
+ // example "v: XX1;branch=YY1,XX2;branch=YY2". This needs to be treated as two "v:" headers.
+ private static final String SUBHEADER_VALUE_SEPARATOR = ",";
+
+ // SIP header parameters have the format ";paramName=paramValue"
+ private static final String PARAM_SEPARATOR = ";";
+ // parameters are formatted paramName=ParamValue
+ private static final String PARAM_KEY_VALUE_SEPARATOR = "=";
+
+ // The via branch parameter definition
+ private static final String BRANCH_PARAM_KEY = "branch";
+
+ // via header key
+ private static final String VIA_SIP_HEADER_KEY = "via";
+ // compact form of the via header key
+ private static final String VIA_SIP_HEADER_KEY_COMPACT = "v";
+
+ /**
+ * @return true if the SIP message start line is considered a request (based on known request
+ * methods).
+ */
+ public static boolean isSipRequest(String startLine) {
+ String[] splitLine = splitStartLineAndVerify(startLine);
+ if (splitLine == null) return false;
+ return verifySipRequest(splitLine);
+ }
+
+ /**
+ * Return the via branch parameter, which is used to identify the transaction ID (request and
+ * response pair) in a SIP transaction.
+ * @param headerString The string containing the headers of the SIP message.
+ */
+ public static String getTransactionId(String headerString) {
+ // search for Via: or v: parameter, we only care about the first one.
+ List<Pair<String, String>> headers = parseHeaders(headerString, true,
+ VIA_SIP_HEADER_KEY, VIA_SIP_HEADER_KEY_COMPACT);
+ for (Pair<String, String> header : headers) {
+ // Headers can also be concatenated together using a "," between each header value.
+ // format becomes v: XX1;branch=YY1,XX2;branch=YY2. Need to extract only the first ID's
+ // branch param YY1.
+ String[] subHeaders = header.second.split(SUBHEADER_VALUE_SEPARATOR);
+ for (String subHeader : subHeaders) {
+ // Search for ;branch=z9hG4bKXXXXXX and return parameter value
+ String[] params = subHeader.split(PARAM_SEPARATOR);
+ if (params.length < 2) {
+ // This param doesn't include a branch param, move to next param.
+ Log.w(TAG, "getTransactionId: via detected without branch param:"
+ + subHeader);
+ continue;
+ }
+ // by spec, each param can only appear once in a header.
+ for (String param : params) {
+ String[] pair = param.split(PARAM_KEY_VALUE_SEPARATOR);
+ if (pair.length < 2) {
+ // ignore info before the first parameter
+ continue;
+ }
+ if (pair.length > 2) {
+ Log.w(TAG,
+ "getTransactionId: unexpected parameter" + Arrays.toString(pair));
+ }
+ // Trim whitespace in parameter
+ pair[0] = pair[0].trim();
+ pair[1] = pair[1].trim();
+ if (BRANCH_PARAM_KEY.equalsIgnoreCase(pair[0])) {
+ // There can be multiple "Via" headers in the SIP message, however we want
+ // to return the first once found, as this corresponds with the transaction
+ // that is relevant here.
+ return pair[1];
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private static String[] splitStartLineAndVerify(String startLine) {
+ String[] splitLine = startLine.split(" ");
+ if (isStartLineMalformed(splitLine)) return null;
+ return splitLine;
+ }
+
+ private static boolean isStartLineMalformed(String[] startLine) {
+ if (startLine == null || startLine.length == 0) {
+ return true;
+ }
+ // start lines contain three segments separated by spaces (SP):
+ // Request-Line = Method SP Request-URI SP SIP-Version CRLF
+ // Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF
+ return (startLine.length != 3);
+ }
+
+ private static boolean verifySipRequest(String[] request) {
+ // Request-Line = Method SP Request-URI SP SIP-Version CRLF
+ boolean verified = request[2].contains(SIP_VERSION_2);
+ verified &= (Uri.parse(request[1]).getScheme() != null);
+ verified &= Arrays.stream(SIP_REQUEST_METHODS).anyMatch(s -> request[0].contains(s));
+ return verified;
+ }
+
+ private static boolean verifySipResponse(String[] response) {
+ // Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF
+ boolean verified = response[0].contains(SIP_VERSION_2);
+ int statusCode = Integer.parseInt(response[1]);
+ verified &= (statusCode >= 100 && statusCode < 700);
+ return verified;
+ }
+
+ /**
+ * Parse a String representation of the Header portion of the SIP Message and re-structure it
+ * into a List of key->value pairs representing each header in the order that they appeared in
+ * the message.
+ *
+ * @param headerString The raw string containing all headers
+ * @param stopAtFirstMatch Return early when the first match is found from matching header keys.
+ * @param matchingHeaderKeys An optional list of Strings containing header keys that should be
+ * returned if they exist. If none exist, all keys will be returned.
+ * (This is internally an equalsIgnoreMatch comparison).
+ * @return the matched header keys and values.
+ */
+ private static List<Pair<String, String>> parseHeaders(String headerString,
+ boolean stopAtFirstMatch, String... matchingHeaderKeys) {
+ // Ensure there is no leading whitespace
+ headerString = removeLeadingWhitespace(headerString);
+
+ List<Pair<String, String>> result = new ArrayList<>();
+ // Split the string line-by-line.
+ String[] headerLines = headerString.split("\\r?\\n");
+ if (headerLines.length == 0) {
+ return Collections.emptyList();
+ }
+
+ String headerKey = null;
+ StringBuilder headerValueSegment = new StringBuilder();
+ // loop through each line, either parsing a "key: value" pair or appending values that span
+ // multiple lines.
+ for (String line : headerLines) {
+ // This line is a continuation of the last line if it starts with whitespace or tab
+ if (line.startsWith("\t") || line.startsWith(" ")) {
+ headerValueSegment.append(removeLeadingWhitespace(line));
+ continue;
+ }
+ // This line is the start of a new key, If headerKey/value is already populated from a
+ // previous key/value pair, add it to list of parsed header pairs.
+ if (headerKey != null) {
+ final String key = headerKey;
+ if (matchingHeaderKeys == null || matchingHeaderKeys.length == 0
+ || Arrays.stream(matchingHeaderKeys).anyMatch(
+ (s) -> s.equalsIgnoreCase(key))) {
+ result.add(new Pair<>(key, headerValueSegment.toString()));
+ if (stopAtFirstMatch) {
+ return result;
+ }
+ }
+ headerKey = null;
+ headerValueSegment = new StringBuilder();
+ }
+
+ // Format is "Key:Value", ignore any ":" after the first.
+ String[] pair = line.split(HEADER_KEY_VALUE_SEPARATOR, 2);
+ if (pair.length < 2) {
+ // malformed line, skip
+ Log.w(TAG, "parseHeaders - received malformed line: " + line);
+ continue;
+ }
+
+ headerKey = pair[0].trim();
+ for (int i = 1; i < pair.length; i++) {
+ headerValueSegment.append(removeLeadingWhitespace(pair[i]));
+ }
+ }
+ // Pick up the last pending header being parsed, if it exists.
+ if (headerKey != null) {
+ final String key = headerKey;
+ if (matchingHeaderKeys == null || matchingHeaderKeys.length == 0
+ || Arrays.stream(matchingHeaderKeys).anyMatch(
+ (s) -> s.equalsIgnoreCase(key))) {
+ result.add(new Pair<>(key, headerValueSegment.toString()));
+ }
+ }
+
+ return result;
+ }
+
+ private static String removeLeadingWhitespace(String line) {
+ return line.replaceFirst("^\\s*", "");
+ }
+}
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index d012971..f6d18fc 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -18,10 +18,7 @@
import android.annotation.IntDef;
import android.annotation.SystemApi;
-import android.hardware.radio.V1_1.GeranBands;
import android.hardware.radio.V1_5.AccessNetwork;
-import android.hardware.radio.V1_5.EutranBands;
-import android.hardware.radio.V1_5.UtranBands;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -117,52 +114,120 @@
* http://www.etsi.org/deliver/etsi_ts/145000_145099/145005/14.00.00_60/ts_145005v140000p.pdf
*/
public static final class GeranBand {
- public static final int BAND_T380 = GeranBands.BAND_T380;
- public static final int BAND_T410 = GeranBands.BAND_T410;
- public static final int BAND_450 = GeranBands.BAND_450;
- public static final int BAND_480 = GeranBands.BAND_480;
- public static final int BAND_710 = GeranBands.BAND_710;
- public static final int BAND_750 = GeranBands.BAND_750;
- public static final int BAND_T810 = GeranBands.BAND_T810;
- public static final int BAND_850 = GeranBands.BAND_850;
- public static final int BAND_P900 = GeranBands.BAND_P900;
- public static final int BAND_E900 = GeranBands.BAND_E900;
- public static final int BAND_R900 = GeranBands.BAND_R900;
- public static final int BAND_DCS1800 = GeranBands.BAND_DCS1800;
- public static final int BAND_PCS1900 = GeranBands.BAND_PCS1900;
- public static final int BAND_ER900 = GeranBands.BAND_ER900;
+ public static final int BAND_T380 = android.hardware.radio.V1_1.GeranBands.BAND_T380;
+ public static final int BAND_T410 = android.hardware.radio.V1_1.GeranBands.BAND_T410;
+ public static final int BAND_450 = android.hardware.radio.V1_1.GeranBands.BAND_450;
+ public static final int BAND_480 = android.hardware.radio.V1_1.GeranBands.BAND_480;
+ public static final int BAND_710 = android.hardware.radio.V1_1.GeranBands.BAND_710;
+ public static final int BAND_750 = android.hardware.radio.V1_1.GeranBands.BAND_750;
+ public static final int BAND_T810 = android.hardware.radio.V1_1.GeranBands.BAND_T810;
+ public static final int BAND_850 = android.hardware.radio.V1_1.GeranBands.BAND_850;
+ public static final int BAND_P900 = android.hardware.radio.V1_1.GeranBands.BAND_P900;
+ public static final int BAND_E900 = android.hardware.radio.V1_1.GeranBands.BAND_E900;
+ public static final int BAND_R900 = android.hardware.radio.V1_1.GeranBands.BAND_R900;
+ public static final int BAND_DCS1800 = android.hardware.radio.V1_1.GeranBands.BAND_DCS1800;
+ public static final int BAND_PCS1900 = android.hardware.radio.V1_1.GeranBands.BAND_PCS1900;
+ public static final int BAND_ER900 = android.hardware.radio.V1_1.GeranBands.BAND_ER900;
+
+ /**
+ * GeranBand
+ *
+ * @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"BAND_"},
+ value = {BAND_T380,
+ BAND_T410,
+ BAND_450,
+ BAND_480,
+ BAND_710,
+ BAND_750,
+ BAND_T810,
+ BAND_850,
+ BAND_P900,
+ BAND_E900,
+ BAND_R900,
+ BAND_DCS1800,
+ BAND_PCS1900,
+ BAND_ER900})
+
+ public @interface GeranBands {}
/** @hide */
private GeranBand() {}
}
/**
+ * 3GPP TS 45.005 Table 2-1 Dynamically mapped ARFCN.
+ * 3GPP TS 45.005 Table 2-2 Fixed designation of ARFCN.
+ * @hide
+ */
+ enum GeranBandArfcnFrequency {
+
+ // Dynamically mapped ARFCN
+// GERAN_ARFCN_FREQUENCY_BAND_T380(GeranBand.BAND_T380, 380.2, 0),
+// GERAN_ARFCN_FREQUENCY_BAND_T410(GeranBand.BAND_T410, 410.2, 0),
+// GERAN_ARFCN_FREQUENCY_BAND_710(GeranBand.BAND_710, 698, 0),
+// GERAN_ARFCN_FREQUENCY_BAND_750(GeranBand.BAND_750, 747, 438, 30),
+// GERAN_ARFCN_FREQUENCY_BAND_T810(GeranBand.BAND_T810, 806, 350),
+ // Fixed designation of ARFCN
+ GERAN_ARFCN_FREQUENCY_BAND_450(GeranBand.BAND_450, 450600, 259, 259, 293, 10),
+ GERAN_ARFCN_FREQUENCY_BAND_480(GeranBand.BAND_480, 479000, 306, 306, 340, 10),
+ GERAN_ARFCN_FREQUENCY_BAND_850(GeranBand.BAND_850, 824200, 128, 128, 251, 45),
+ GERAN_ARFCN_FREQUENCY_BAND_DCS1800(GeranBand.BAND_DCS1800, 1710200, 512, 512, 885, 95),
+ GERAN_ARFCN_FREQUENCY_BAND_PCS1900(GeranBand.BAND_PCS1900, 1850200, 512, 512, 810, 80),
+ GERAN_ARFCN_FREQUENCY_BAND_E900_1(GeranBand.BAND_E900, 890000, 0, 0, 124, 45),
+ GERAN_ARFCN_FREQUENCY_BAND_E900_2(GeranBand.BAND_E900, 890000, 1024, 975, 1023, 45),
+ GERAN_ARFCN_FREQUENCY_BAND_R900_1(GeranBand.BAND_R900, 890000, 0, 0, 124, 45),
+ GERAN_ARFCN_FREQUENCY_BAND_R900_2(GeranBand.BAND_R900, 890000, 1024, 955, 1023, 45),
+ GERAN_ARFCN_FREQUENCY_BAND_P900(GeranBand.BAND_P900, 890000, 0, 1, 124, 45),
+ GERAN_ARFCN_FREQUENCY_BAND_ER900_1(GeranBand.BAND_ER900, 890000, 0, 0, 124, 45),
+ GERAN_ARFCN_FREQUENCY_BAND_ER900_2(GeranBand.BAND_ER900, 890000, 1024, 940, 1023, 1024);
+
+ GeranBandArfcnFrequency(int band, int uplinkFrequencyFirstKhz, int arfcnOffset,
+ int arfcnRangeFirst, int arfcnRangeLast, int downlinkOffset) {
+ this.band = band;
+ this.uplinkFrequencyFirst = uplinkFrequencyFirstKhz;
+ this.arfcnOffset = arfcnOffset;
+ this.arfcnRangeFirst = arfcnRangeFirst;
+ this.arfcnRangeLast = arfcnRangeLast;
+ this.downlinkOffset = downlinkOffset;
+ }
+
+ int band;
+ int uplinkFrequencyFirst;
+ int arfcnOffset;
+ int arfcnRangeFirst;
+ int arfcnRangeLast;
+ int downlinkOffset;
+ }
+
+ /**
* Frequency bands for UTRAN.
* http://www.etsi.org/deliver/etsi_ts/125100_125199/125104/13.03.00_60/ts_125104v130p.pdf
*/
public static final class UtranBand {
- public static final int BAND_1 = UtranBands.BAND_1;
- public static final int BAND_2 = UtranBands.BAND_2;
- public static final int BAND_3 = UtranBands.BAND_3;
- public static final int BAND_4 = UtranBands.BAND_4;
- public static final int BAND_5 = UtranBands.BAND_5;
- public static final int BAND_6 = UtranBands.BAND_6;
- public static final int BAND_7 = UtranBands.BAND_7;
- public static final int BAND_8 = UtranBands.BAND_8;
- public static final int BAND_9 = UtranBands.BAND_9;
- public static final int BAND_10 = UtranBands.BAND_10;
- public static final int BAND_11 = UtranBands.BAND_11;
- public static final int BAND_12 = UtranBands.BAND_12;
- public static final int BAND_13 = UtranBands.BAND_13;
- public static final int BAND_14 = UtranBands.BAND_14;
+ public static final int BAND_1 = android.hardware.radio.V1_5.UtranBands.BAND_1;
+ public static final int BAND_2 = android.hardware.radio.V1_5.UtranBands.BAND_2;
+ public static final int BAND_3 = android.hardware.radio.V1_5.UtranBands.BAND_3;
+ public static final int BAND_4 = android.hardware.radio.V1_5.UtranBands.BAND_4;
+ public static final int BAND_5 = android.hardware.radio.V1_5.UtranBands.BAND_5;
+ public static final int BAND_6 = android.hardware.radio.V1_5.UtranBands.BAND_6;
+ public static final int BAND_7 = android.hardware.radio.V1_5.UtranBands.BAND_7;
+ public static final int BAND_8 = android.hardware.radio.V1_5.UtranBands.BAND_8;
+ public static final int BAND_9 = android.hardware.radio.V1_5.UtranBands.BAND_9;
+ public static final int BAND_10 = android.hardware.radio.V1_5.UtranBands.BAND_10;
+ public static final int BAND_11 = android.hardware.radio.V1_5.UtranBands.BAND_11;
+ public static final int BAND_12 = android.hardware.radio.V1_5.UtranBands.BAND_12;
+ public static final int BAND_13 = android.hardware.radio.V1_5.UtranBands.BAND_13;
+ public static final int BAND_14 = android.hardware.radio.V1_5.UtranBands.BAND_14;
// band 15, 16, 17, 18 are reserved
- public static final int BAND_19 = UtranBands.BAND_19;
- public static final int BAND_20 = UtranBands.BAND_20;
- public static final int BAND_21 = UtranBands.BAND_21;
- public static final int BAND_22 = UtranBands.BAND_22;
+ public static final int BAND_19 = android.hardware.radio.V1_5.UtranBands.BAND_19;
+ public static final int BAND_20 = android.hardware.radio.V1_5.UtranBands.BAND_20;
+ public static final int BAND_21 = android.hardware.radio.V1_5.UtranBands.BAND_21;
+ public static final int BAND_22 = android.hardware.radio.V1_5.UtranBands.BAND_22;
// band 23, 24 are reserved
- public static final int BAND_25 = UtranBands.BAND_25;
- public static final int BAND_26 = UtranBands.BAND_26;
+ public static final int BAND_25 = android.hardware.radio.V1_5.UtranBands.BAND_25;
+ public static final int BAND_26 = android.hardware.radio.V1_5.UtranBands.BAND_26;
// Frequency bands for TD-SCDMA. Defined in 3GPP TS 25.102, Table 5.2.
@@ -171,115 +236,423 @@
* 1900 - 1920 MHz: Uplink and downlink transmission
* 2010 - 2025 MHz: Uplink and downlink transmission
*/
- public static final int BAND_A = UtranBands.BAND_A;
+ public static final int BAND_A = android.hardware.radio.V1_5.UtranBands.BAND_A;
/**
* Band B
* 1850 - 1910 MHz: Uplink and downlink transmission
* 1930 - 1990 MHz: Uplink and downlink transmission
*/
- public static final int BAND_B = UtranBands.BAND_B;
+ public static final int BAND_B = android.hardware.radio.V1_5.UtranBands.BAND_B;
/**
* Band C
* 1910 - 1930 MHz: Uplink and downlink transmission
*/
- public static final int BAND_C = UtranBands.BAND_C;
+ public static final int BAND_C = android.hardware.radio.V1_5.UtranBands.BAND_C;
/**
* Band D
* 2570 - 2620 MHz: Uplink and downlink transmission
*/
- public static final int BAND_D = UtranBands.BAND_D;
+ public static final int BAND_D = android.hardware.radio.V1_5.UtranBands.BAND_D;
/**
* Band E
* 2300—2400 MHz: Uplink and downlink transmission
*/
- public static final int BAND_E = UtranBands.BAND_E;
+ public static final int BAND_E = android.hardware.radio.V1_5.UtranBands.BAND_E;
/**
* Band F
* 1880 - 1920 MHz: Uplink and downlink transmission
*/
- public static final int BAND_F = UtranBands.BAND_F;
+ public static final int BAND_F = android.hardware.radio.V1_5.UtranBands.BAND_F;
+
+ /**
+ * UtranBand
+ *
+ * @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"BAND_"},
+ value = {BAND_1,
+ BAND_2,
+ BAND_3,
+ BAND_4,
+ BAND_5,
+ BAND_6,
+ BAND_7,
+ BAND_8,
+ BAND_9,
+ BAND_10,
+ BAND_11,
+ BAND_12,
+ BAND_13,
+ BAND_14,
+ BAND_19,
+ BAND_20,
+ BAND_21,
+ BAND_22,
+ BAND_25,
+ BAND_26,
+ BAND_A,
+ BAND_B,
+ BAND_C,
+ BAND_D,
+ BAND_E,
+ BAND_F})
+
+ public @interface UtranBands {}
/** @hide */
private UtranBand() {}
}
/**
+ * 3GPP TS 25.101, Table 5.1 UARFCN definition (general)
+ * 3GPP TS 25.102, Table 5.2 UTRA Absolute Radio Frequency Channel Number 1.28 Mcps TDD Option.
+ *
+ * @hide
+ */
+ enum UtranBandArfcnFrequency {
+
+ UTRAN_ARFCN_FREQUENCY_BAND_1(UtranBand.BAND_1, 0, 10562, 10838, 0, 9612, 9888),
+ UTRAN_ARFCN_FREQUENCY_BAND_2(UtranBand.BAND_2, 0, 9662, 9938, 0, 9262, 9538),
+ UTRAN_ARFCN_FREQUENCY_BAND_3(UtranBand.BAND_3, 1575000, 1162, 1513, 1525000, 937, 1288),
+ UTRAN_ARFCN_FREQUENCY_BAND_4(UtranBand.BAND_4, 1805000, 1537, 1738, 1450000, 1312, 1513),
+ UTRAN_ARFCN_FREQUENCY_BAND_5(UtranBand.BAND_5, 0, 4357, 4458, 0, 4132, 4233),
+ UTRAN_ARFCN_FREQUENCY_BAND_6(UtranBand.BAND_6, 0, 4387, 4413, 0, 4162, 4188),
+ UTRAN_ARFCN_FREQUENCY_BAND_7(UtranBand.BAND_7, 2175000, 2237, 2563, 2100000, 2012, 2338),
+ UTRAN_ARFCN_FREQUENCY_BAND_8(UtranBand.BAND_8, 340000, 2937, 3088, 340000, 2712, 2863),
+ UTRAN_ARFCN_FREQUENCY_BAND_9(UtranBand.BAND_9, 0, 9327, 9837, 0, 8762, 8912),
+ UTRAN_ARFCN_FREQUENCY_BAND_10(UtranBand.BAND_10, 1490000, 3112, 3388, 1135000, 2887, 3163),
+ UTRAN_ARFCN_FREQUENCY_BAND_11(UtranBand.BAND_11, 736000, 3712, 3787, 733000, 3487, 3562),
+ UTRAN_ARFCN_FREQUENCY_BAND_12(UtranBand.BAND_12, -37000, 3842, 3903, -22000, 3617, 3678),
+ UTRAN_ARFCN_FREQUENCY_BAND_13(UtranBand.BAND_13, -55000, 4017, 4043, 21000, 3792, 3818),
+ UTRAN_ARFCN_FREQUENCY_BAND_14(UtranBand.BAND_14, -63000, 4117, 4143, 12000, 3892, 3918),
+ UTRAN_ARFCN_FREQUENCY_BAND_19(UtranBand.BAND_19, 735000, 712, 763, 770000, 312, 363),
+ UTRAN_ARFCN_FREQUENCY_BAND_20(UtranBand.BAND_20, -109000, 4512, 4638, -23000, 4287, 4413),
+ UTRAN_ARFCN_FREQUENCY_BAND_21(UtranBand.BAND_21, 1326000, 862, 912, 1358000, 462, 512),
+ UTRAN_ARFCN_FREQUENCY_BAND_22(UtranBand.BAND_22, 2580000, 4662, 5038, 2525000, 4437, 4813),
+ UTRAN_ARFCN_FREQUENCY_BAND_25(UtranBand.BAND_25, 910000, 5112, 5413, 875000, 4887, 5188),
+ UTRAN_ARFCN_FREQUENCY_BAND_A(UtranBand.BAND_A, 0, 10054, 10121, 0, 9504, 9596),
+ UTRAN_ARFCN_FREQUENCY_BAND_B(UtranBand.BAND_B, 0, 9654, 9946, 0, 9254, 9546),
+ UTRAN_ARFCN_FREQUENCY_BAND_C(UtranBand.BAND_C, 0, 0, 0, 0, 9554, 9646),
+ UTRAN_ARFCN_FREQUENCY_BAND_D(UtranBand.BAND_D, 0, 0, 0, 0, 12854, 13096),
+ UTRAN_ARFCN_FREQUENCY_BAND_E(UtranBand.BAND_E, 0, 0, 0, 0, 11504, 11996),
+ UTRAN_ARFCN_FREQUENCY_BAND_F(UtranBand.BAND_F, 0, 0, 0, 0, 9404, 9596);
+
+ UtranBandArfcnFrequency(int band, int downlinkOffsetKhz, int downlinkRangeFirst,
+ int downlinkRangeLast, int uplinkOffsetKhz, int uplinkRangeFirst,
+ int uplinkRangeLast) {
+ this.band = band;
+ this.downlinkOffset = downlinkOffsetKhz;
+ this.downlinkRangeFirst = downlinkRangeFirst;
+ this.downlinkRangeLast = downlinkRangeLast;
+ this.uplinkOffset = uplinkOffsetKhz;
+ this.uplinkRangeFirst = uplinkRangeFirst;
+ this.uplinkRangeLast = uplinkRangeLast;
+ }
+
+ int band;
+ int downlinkOffset;
+ int downlinkRangeFirst;
+ int downlinkRangeLast;
+ int uplinkOffset;
+ int uplinkRangeFirst;
+ int uplinkRangeLast;
+ }
+
+ /**
* Frequency bands for EUTRAN.
* 3GPP TS 36.101, Version 16.4.0, Table 5.5: Operating bands
* https://www.etsi.org/deliver/etsi_ts/136100_136199/136101/15.09.00_60/ts_136101v150900p.pdf
*/
public static final class EutranBand {
- public static final int BAND_1 = EutranBands.BAND_1;
- public static final int BAND_2 = EutranBands.BAND_2;
- public static final int BAND_3 = EutranBands.BAND_3;
- public static final int BAND_4 = EutranBands.BAND_4;
- public static final int BAND_5 = EutranBands.BAND_5;
- public static final int BAND_6 = EutranBands.BAND_6;
- public static final int BAND_7 = EutranBands.BAND_7;
- public static final int BAND_8 = EutranBands.BAND_8;
- public static final int BAND_9 = EutranBands.BAND_9;
- public static final int BAND_10 = EutranBands.BAND_10;
- public static final int BAND_11 = EutranBands.BAND_11;
- public static final int BAND_12 = EutranBands.BAND_12;
- public static final int BAND_13 = EutranBands.BAND_13;
- public static final int BAND_14 = EutranBands.BAND_14;
- public static final int BAND_17 = EutranBands.BAND_17;
- public static final int BAND_18 = EutranBands.BAND_18;
- public static final int BAND_19 = EutranBands.BAND_19;
- public static final int BAND_20 = EutranBands.BAND_20;
- public static final int BAND_21 = EutranBands.BAND_21;
- public static final int BAND_22 = EutranBands.BAND_22;
- public static final int BAND_23 = EutranBands.BAND_23;
- public static final int BAND_24 = EutranBands.BAND_24;
- public static final int BAND_25 = EutranBands.BAND_25;
- public static final int BAND_26 = EutranBands.BAND_26;
- public static final int BAND_27 = EutranBands.BAND_27;
- public static final int BAND_28 = EutranBands.BAND_28;
- public static final int BAND_30 = EutranBands.BAND_30;
- public static final int BAND_31 = EutranBands.BAND_31;
- public static final int BAND_33 = EutranBands.BAND_33;
- public static final int BAND_34 = EutranBands.BAND_34;
- public static final int BAND_35 = EutranBands.BAND_35;
- public static final int BAND_36 = EutranBands.BAND_36;
- public static final int BAND_37 = EutranBands.BAND_37;
- public static final int BAND_38 = EutranBands.BAND_38;
- public static final int BAND_39 = EutranBands.BAND_39;
- public static final int BAND_40 = EutranBands.BAND_40;
- public static final int BAND_41 = EutranBands.BAND_41;
- public static final int BAND_42 = EutranBands.BAND_42;
- public static final int BAND_43 = EutranBands.BAND_43;
- public static final int BAND_44 = EutranBands.BAND_44;
- public static final int BAND_45 = EutranBands.BAND_45;
- public static final int BAND_46 = EutranBands.BAND_46;
- public static final int BAND_47 = EutranBands.BAND_47;
- public static final int BAND_48 = EutranBands.BAND_48;
- public static final int BAND_49 = EutranBands.BAND_49;
- public static final int BAND_50 = EutranBands.BAND_50;
- public static final int BAND_51 = EutranBands.BAND_51;
- public static final int BAND_52 = EutranBands.BAND_52;
- public static final int BAND_53 = EutranBands.BAND_53;
- public static final int BAND_65 = EutranBands.BAND_65;
- public static final int BAND_66 = EutranBands.BAND_66;
- public static final int BAND_68 = EutranBands.BAND_68;
- public static final int BAND_70 = EutranBands.BAND_70;
- public static final int BAND_71 = EutranBands.BAND_71;
- public static final int BAND_72 = EutranBands.BAND_72;
- public static final int BAND_73 = EutranBands.BAND_73;
- public static final int BAND_74 = EutranBands.BAND_74;
- public static final int BAND_85 = EutranBands.BAND_85;
- public static final int BAND_87 = EutranBands.BAND_87;
- public static final int BAND_88 = EutranBands.BAND_88;
+ public static final int BAND_1 = android.hardware.radio.V1_5.EutranBands.BAND_1;
+ public static final int BAND_2 = android.hardware.radio.V1_5.EutranBands.BAND_2;
+ public static final int BAND_3 = android.hardware.radio.V1_5.EutranBands.BAND_3;
+ public static final int BAND_4 = android.hardware.radio.V1_5.EutranBands.BAND_4;
+ public static final int BAND_5 = android.hardware.radio.V1_5.EutranBands.BAND_5;
+ public static final int BAND_6 = android.hardware.radio.V1_5.EutranBands.BAND_6;
+ public static final int BAND_7 = android.hardware.radio.V1_5.EutranBands.BAND_7;
+ public static final int BAND_8 = android.hardware.radio.V1_5.EutranBands.BAND_8;
+ public static final int BAND_9 = android.hardware.radio.V1_5.EutranBands.BAND_9;
+ public static final int BAND_10 = android.hardware.radio.V1_5.EutranBands.BAND_10;
+ public static final int BAND_11 = android.hardware.radio.V1_5.EutranBands.BAND_11;
+ public static final int BAND_12 = android.hardware.radio.V1_5.EutranBands.BAND_12;
+ public static final int BAND_13 = android.hardware.radio.V1_5.EutranBands.BAND_13;
+ public static final int BAND_14 = android.hardware.radio.V1_5.EutranBands.BAND_14;
+ public static final int BAND_17 = android.hardware.radio.V1_5.EutranBands.BAND_17;
+ public static final int BAND_18 = android.hardware.radio.V1_5.EutranBands.BAND_18;
+ public static final int BAND_19 = android.hardware.radio.V1_5.EutranBands.BAND_19;
+ public static final int BAND_20 = android.hardware.radio.V1_5.EutranBands.BAND_20;
+ public static final int BAND_21 = android.hardware.radio.V1_5.EutranBands.BAND_21;
+ public static final int BAND_22 = android.hardware.radio.V1_5.EutranBands.BAND_22;
+ public static final int BAND_23 = android.hardware.radio.V1_5.EutranBands.BAND_23;
+ public static final int BAND_24 = android.hardware.radio.V1_5.EutranBands.BAND_24;
+ public static final int BAND_25 = android.hardware.radio.V1_5.EutranBands.BAND_25;
+ public static final int BAND_26 = android.hardware.radio.V1_5.EutranBands.BAND_26;
+ public static final int BAND_27 = android.hardware.radio.V1_5.EutranBands.BAND_27;
+ public static final int BAND_28 = android.hardware.radio.V1_5.EutranBands.BAND_28;
+ public static final int BAND_30 = android.hardware.radio.V1_5.EutranBands.BAND_30;
+ public static final int BAND_31 = android.hardware.radio.V1_5.EutranBands.BAND_31;
+ public static final int BAND_33 = android.hardware.radio.V1_5.EutranBands.BAND_33;
+ public static final int BAND_34 = android.hardware.radio.V1_5.EutranBands.BAND_34;
+ public static final int BAND_35 = android.hardware.radio.V1_5.EutranBands.BAND_35;
+ public static final int BAND_36 = android.hardware.radio.V1_5.EutranBands.BAND_36;
+ public static final int BAND_37 = android.hardware.radio.V1_5.EutranBands.BAND_37;
+ public static final int BAND_38 = android.hardware.radio.V1_5.EutranBands.BAND_38;
+ public static final int BAND_39 = android.hardware.radio.V1_5.EutranBands.BAND_39;
+ public static final int BAND_40 = android.hardware.radio.V1_5.EutranBands.BAND_40;
+ public static final int BAND_41 = android.hardware.radio.V1_5.EutranBands.BAND_41;
+ public static final int BAND_42 = android.hardware.radio.V1_5.EutranBands.BAND_42;
+ public static final int BAND_43 = android.hardware.radio.V1_5.EutranBands.BAND_43;
+ public static final int BAND_44 = android.hardware.radio.V1_5.EutranBands.BAND_44;
+ public static final int BAND_45 = android.hardware.radio.V1_5.EutranBands.BAND_45;
+ public static final int BAND_46 = android.hardware.radio.V1_5.EutranBands.BAND_46;
+ public static final int BAND_47 = android.hardware.radio.V1_5.EutranBands.BAND_47;
+ public static final int BAND_48 = android.hardware.radio.V1_5.EutranBands.BAND_48;
+ public static final int BAND_49 = android.hardware.radio.V1_5.EutranBands.BAND_49;
+ public static final int BAND_50 = android.hardware.radio.V1_5.EutranBands.BAND_50;
+ public static final int BAND_51 = android.hardware.radio.V1_5.EutranBands.BAND_51;
+ public static final int BAND_52 = android.hardware.radio.V1_5.EutranBands.BAND_52;
+ public static final int BAND_53 = android.hardware.radio.V1_5.EutranBands.BAND_53;
+ public static final int BAND_65 = android.hardware.radio.V1_5.EutranBands.BAND_65;
+ public static final int BAND_66 = android.hardware.radio.V1_5.EutranBands.BAND_66;
+ public static final int BAND_68 = android.hardware.radio.V1_5.EutranBands.BAND_68;
+ public static final int BAND_70 = android.hardware.radio.V1_5.EutranBands.BAND_70;
+ public static final int BAND_71 = android.hardware.radio.V1_5.EutranBands.BAND_71;
+ public static final int BAND_72 = android.hardware.radio.V1_5.EutranBands.BAND_72;
+ public static final int BAND_73 = android.hardware.radio.V1_5.EutranBands.BAND_73;
+ public static final int BAND_74 = android.hardware.radio.V1_5.EutranBands.BAND_74;
+ public static final int BAND_85 = android.hardware.radio.V1_5.EutranBands.BAND_85;
+ public static final int BAND_87 = android.hardware.radio.V1_5.EutranBands.BAND_87;
+ public static final int BAND_88 = android.hardware.radio.V1_5.EutranBands.BAND_88;
+
+ /**
+ * EutranBands
+ *
+ * @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"BAND_"},
+ value = {BAND_1,
+ BAND_2,
+ BAND_3,
+ BAND_4,
+ BAND_5,
+ BAND_6,
+ BAND_7,
+ BAND_8,
+ BAND_9,
+ BAND_10,
+ BAND_11,
+ BAND_12,
+ BAND_13,
+ BAND_14,
+ BAND_17,
+ BAND_18,
+ BAND_19,
+ BAND_20,
+ BAND_21,
+ BAND_22,
+ BAND_23,
+ BAND_24,
+ BAND_25,
+ BAND_26,
+ BAND_27,
+ BAND_28,
+ BAND_30,
+ BAND_31,
+ BAND_33,
+ BAND_34,
+ BAND_35,
+ BAND_36,
+ BAND_37,
+ BAND_38,
+ BAND_39,
+ BAND_40,
+ BAND_41,
+ BAND_42,
+ BAND_43,
+ BAND_44,
+ BAND_45,
+ BAND_46,
+ BAND_47,
+ BAND_48,
+ BAND_49,
+ BAND_50,
+ BAND_51,
+ BAND_52,
+ BAND_53,
+ BAND_65,
+ BAND_66,
+ BAND_68,
+ BAND_70,
+ BAND_71,
+ BAND_72,
+ BAND_73,
+ BAND_74,
+ BAND_85,
+ BAND_87,
+ BAND_88})
+
+ public @interface EutranBands {}
/** @hide */
private EutranBand() {};
}
/**
+ * 3GPP TS 36.101 Table 5.7.3-1 E-UTRA channel numbers.
+ *
+ * @hide
+ */
+ enum EutranBandArfcnFrequency {
+
+ EUTRAN_ARFCN_FREQUENCY_BAND_1(
+ EutranBand.BAND_1, 2110000, 0, 599, 1920000, 18800, 18599),
+ EUTRAN_ARFCN_FREQUENCY_BAND_2(
+ EutranBand.BAND_2, 1930000, 600, 1199, 1850000, 18600, 19199),
+ EUTRAN_ARFCN_FREQUENCY_BAND_3(
+ EutranBand.BAND_3, 1805000, 1200, 1949, 1710000, 19200, 19949),
+ EUTRAN_ARFCN_FREQUENCY_BAND_4(
+ EutranBand.BAND_4, 2110000, 1950, 2399, 1710000, 19950, 20399),
+ EUTRAN_ARFCN_FREQUENCY_BAND_5(
+ EutranBand.BAND_5, 869000, 2400, 2649, 824000, 20400, 20649),
+ EUTRAN_ARFCN_FREQUENCY_BAND_6(
+ EutranBand.BAND_6, 875000, 2650, 2749, 830000, 20650, 20749),
+ EUTRAN_ARFCN_FREQUENCY_BAND_7(
+ EutranBand.BAND_7, 2620000, 2750, 3449, 2500000, 20750, 21449),
+ EUTRAN_ARFCN_FREQUENCY_BAND_8(
+ EutranBand.BAND_8, 925000, 3450, 3799, 880000, 21450, 21799),
+ EUTRAN_ARFCN_FREQUENCY_BAND_9(
+ EutranBand.BAND_9, 1844900, 3800, 4149, 1749900, 21800, 22149),
+ EUTRAN_ARFCN_FREQUENCY_BAND_10(
+ EutranBand.BAND_10, 2110000, 4150, 4749, 1710000, 22150, 22749),
+ EUTRAN_ARFCN_FREQUENCY_BAND_11(
+ EutranBand.BAND_11, 1475900, 4750, 4949, 1427900, 22750, 22949),
+ EUTRAN_ARFCN_FREQUENCY_BAND_12(
+ EutranBand.BAND_12, 729000, 5010, 5179, 699000, 23010, 23179),
+ EUTRAN_ARFCN_FREQUENCY_BAND_13(
+ EutranBand.BAND_13, 746000, 5180, 5279, 777000, 23180, 23279),
+ EUTRAN_ARFCN_FREQUENCY_BAND_14(
+ EutranBand.BAND_14, 758000, 5280, 5379, 788000, 23230, 23379),
+ EUTRAN_ARFCN_FREQUENCY_BAND_17(
+ EutranBand.BAND_17, 734000, 5730, 5849, 704000, 23730, 23849),
+ EUTRAN_ARFCN_FREQUENCY_BAND_18(
+ EutranBand.BAND_18, 860000, 5850, 5999, 815000, 23850, 23999),
+ EUTRAN_ARFCN_FREQUENCY_BAND_19(
+ EutranBand.BAND_19, 875000, 6000, 6149, 830000, 24000, 24149),
+ EUTRAN_ARFCN_FREQUENCY_BAND_20(
+ EutranBand.BAND_20, 791000, 6150, 6449, 832000, 24150, 24449),
+ EUTRAN_ARFCN_FREQUENCY_BAND_21(
+ EutranBand.BAND_21, 1495900, 6450, 6599, 1447900, 24450, 24599),
+ EUTRAN_ARFCN_FREQUENCY_BAND_22(
+ EutranBand.BAND_22, 3510000, 6600, 7399, 3410000, 24600, 25399),
+ EUTRAN_ARFCN_FREQUENCY_BAND_23(
+ EutranBand.BAND_23, 2180000, 7500, 7699, 2000000, 25500, 25699),
+ EUTRAN_ARFCN_FREQUENCY_BAND_24(
+ EutranBand.BAND_24, 1525000, 7700, 8039, 1626500, 25700, 26039),
+ EUTRAN_ARFCN_FREQUENCY_BAND_25(
+ EutranBand.BAND_25, 1930000, 8040, 8689, 1850000, 26040, 26689),
+ EUTRAN_ARFCN_FREQUENCY_BAND_26(
+ EutranBand.BAND_26, 859000, 8690, 9039, 814000, 26690, 27039),
+ EUTRAN_ARFCN_FREQUENCY_BAND_27(
+ EutranBand.BAND_27, 852000, 9040, 9209, 807000, 27040, 27209),
+ EUTRAN_ARFCN_FREQUENCY_BAND_28(
+ EutranBand.BAND_28, 758000, 9210, 9659, 703000, 27210, 27659),
+ EUTRAN_ARFCN_FREQUENCY_BAND_30(
+ EutranBand.BAND_30, 2350000, 9770, 9869, 2305000, 27660, 27759),
+ EUTRAN_ARFCN_FREQUENCY_BAND_31(
+ EutranBand.BAND_31, 462500, 9870, 9919, 452500, 27760, 27809),
+ EUTRAN_ARFCN_FREQUENCY_BAND_33(
+ EutranBand.BAND_33, 1900000, 36000, 36199, 1900000, 36000, 36199),
+ EUTRAN_ARFCN_FREQUENCY_BAND_34(
+ EutranBand.BAND_34, 2010000, 36200, 36349, 2010000, 36200, 36349),
+ EUTRAN_ARFCN_FREQUENCY_BAND_35(
+ EutranBand.BAND_35, 1850000, 36350, 36949, 1850000, 36350, 36949),
+ EUTRAN_ARFCN_FREQUENCY_BAND_36(
+ EutranBand.BAND_36, 1930000, 36950, 37549, 1930000, 36950, 37549),
+ EUTRAN_ARFCN_FREQUENCY_BAND_37(
+ EutranBand.BAND_37, 1910000, 37550, 37749, 1910000, 37550, 37749),
+ EUTRAN_ARFCN_FREQUENCY_BAND_38(
+ EutranBand.BAND_38, 2570000, 37750, 38249, 2570000, 37750, 38249),
+ EUTRAN_ARFCN_FREQUENCY_BAND_39(
+ EutranBand.BAND_39, 1880000, 38250, 38649, 1880000, 38250, 38649),
+ EUTRAN_ARFCN_FREQUENCY_BAND_40(
+ EutranBand.BAND_40, 2300000, 38650, 39649, 2300000, 38650, 39649),
+ EUTRAN_ARFCN_FREQUENCY_BAND_41(
+ EutranBand.BAND_41, 2496000, 39650, 41589, 2496000, 39650, 41589),
+ EUTRAN_ARFCN_FREQUENCY_BAND_42(
+ EutranBand.BAND_42, 3400000, 41950, 43589, 3400000, 41950, 43589),
+ EUTRAN_ARFCN_FREQUENCY_BAND_43(
+ EutranBand.BAND_43, 3600000, 43950, 45589, 3600000, 43950, 45589),
+ EUTRAN_ARFCN_FREQUENCY_BAND_44(
+ EutranBand.BAND_44, 703000, 45590, 46589, 703000, 45590, 46589),
+ EUTRAN_ARFCN_FREQUENCY_BAND_45(
+ EutranBand.BAND_45, 1447000, 46590, 46789, 1447000, 46590, 46789),
+ EUTRAN_ARFCN_FREQUENCY_BAND_46(
+ EutranBand.BAND_46, 5150000, 46790, 54539, 5150000, 46790, 54539),
+ EUTRAN_ARFCN_FREQUENCY_BAND_47(
+ EutranBand.BAND_47, 5855000, 54540, 55239, 5855000, 54540, 55239),
+ EUTRAN_ARFCN_FREQUENCY_BAND_48(
+ EutranBand.BAND_48, 3550000, 55240, 56739, 3550000, 55240, 56739),
+ EUTRAN_ARFCN_FREQUENCY_BAND_49(
+ EutranBand.BAND_49, 3550000, 56740, 58239, 3550000, 56740, 58239),
+ EUTRAN_ARFCN_FREQUENCY_BAND_50(
+ EutranBand.BAND_50, 1432000, 58240, 59089, 1432000, 58240, 59089),
+ EUTRAN_ARFCN_FREQUENCY_BAND_51(
+ EutranBand.BAND_51, 1427000, 59090, 59139, 1427000, 59090, 59139),
+ EUTRAN_ARFCN_FREQUENCY_BAND_52(
+ EutranBand.BAND_52, 3300000, 59140, 60139, 3300000, 59140, 60139),
+ EUTRAN_ARFCN_FREQUENCY_BAND_53(
+ EutranBand.BAND_53, 2483500, 60140, 60254, 2483500, 60140, 60254),
+ EUTRAN_ARFCN_FREQUENCY_BAND_65(
+ EutranBand.BAND_65, 2110000, 65536, 66435, 1920000, 131072, 131971),
+ EUTRAN_ARFCN_FREQUENCY_BAND_66(
+ EutranBand.BAND_66, 2110000, 66436, 67335, 1710000, 131972, 132671),
+ EUTRAN_ARFCN_FREQUENCY_BAND_68(
+ EutranBand.BAND_68, 753000, 67536, 67835, 698000, 132672, 132971),
+ EUTRAN_ARFCN_FREQUENCY_BAND_70(
+ EutranBand.BAND_70, 1995000, 68336, 68585, 1695000, 132972, 133121),
+ EUTRAN_ARFCN_FREQUENCY_BAND_71(
+ EutranBand.BAND_71, 617000, 68586, 68935, 663000, 133122, 133471),
+ EUTRAN_ARFCN_FREQUENCY_BAND_72(
+ EutranBand.BAND_72, 461000, 68936, 68985, 451000, 133472, 133521),
+ EUTRAN_ARFCN_FREQUENCY_BAND_73(
+ EutranBand.BAND_73, 460000, 68986, 69035, 450000, 133522, 133571),
+ EUTRAN_ARFCN_FREQUENCY_BAND_74(
+ EutranBand.BAND_74, 1475000, 69036, 69465, 1427000, 133572, 134001),
+ EUTRAN_ARFCN_FREQUENCY_BAND_85(
+ EutranBand.BAND_85, 728000, 70366, 70545, 698000, 134002, 134181),
+ EUTRAN_ARFCN_FREQUENCY_BAND_87(
+ EutranBand.BAND_87, 420000, 70546, 70595, 410000, 134182, 134231),
+ EUTRAN_ARFCN_FREQUENCY_BAND_88(
+ EutranBand.BAND_88, 422000, 70596, 70645, 412000, 134231, 134280);
+
+ EutranBandArfcnFrequency(int band, int downlinkLowKhz, int downlinkOffset,
+ int downlinkRange, int uplinkLowKhz, int uplinkOffset,
+ int uplinkRange) {
+ this.band = band;
+ this.downlinkLowKhz = downlinkLowKhz;
+ this.downlinkOffset = downlinkOffset;
+ this.uplinkLowKhz = uplinkLowKhz;
+ this.uplinkOffset = uplinkOffset;
+ this.downlinkRange = downlinkRange;
+ this.uplinkRange = uplinkRange;
+ }
+
+ int band;
+ int downlinkLowKhz;
+ int downlinkOffset;
+ int uplinkLowKhz;
+ int uplinkOffset;
+ int downlinkRange;
+ int uplinkRange;
+ }
+
+ /**
* Frequency bands for CDMA2000.
* http://www.3gpp2.org/Public_html/Specs/C.S0057-E_v1.0_Bandclass_Specification.pdf
* @hide
@@ -320,7 +693,7 @@
* https://www.etsi.org/deliver/etsi_ts/138100_138199/13810102/15.08.00_60/ts_13810102v150800p.pdf
*/
public static final class NgranBands {
- /** 3GPP TS 38.101-1, Version 16.2.0, Table 5.2-1: FR1 bands */
+ /** 3GPP TS 38.101-1, Version 16.5.0, Table 5.2-1: FR1 bands */
public static final int BAND_1 = android.hardware.radio.V1_5.NgranBands.BAND_1;
public static final int BAND_2 = android.hardware.radio.V1_5.NgranBands.BAND_2;
public static final int BAND_3 = android.hardware.radio.V1_5.NgranBands.BAND_3;
@@ -332,6 +705,7 @@
public static final int BAND_18 = android.hardware.radio.V1_5.NgranBands.BAND_18;
public static final int BAND_20 = android.hardware.radio.V1_5.NgranBands.BAND_20;
public static final int BAND_25 = android.hardware.radio.V1_5.NgranBands.BAND_25;
+ public static final int BAND_26 = android.hardware.radio.V1_6.NgranBands.BAND_26;
public static final int BAND_28 = android.hardware.radio.V1_5.NgranBands.BAND_28;
public static final int BAND_29 = android.hardware.radio.V1_5.NgranBands.BAND_29;
public static final int BAND_30 = android.hardware.radio.V1_5.NgranBands.BAND_30;
@@ -340,9 +714,11 @@
public static final int BAND_39 = android.hardware.radio.V1_5.NgranBands.BAND_39;
public static final int BAND_40 = android.hardware.radio.V1_5.NgranBands.BAND_40;
public static final int BAND_41 = android.hardware.radio.V1_5.NgranBands.BAND_41;
+ public static final int BAND_46 = android.hardware.radio.V1_6.NgranBands.BAND_46;
public static final int BAND_48 = android.hardware.radio.V1_5.NgranBands.BAND_48;
public static final int BAND_50 = android.hardware.radio.V1_5.NgranBands.BAND_50;
public static final int BAND_51 = android.hardware.radio.V1_5.NgranBands.BAND_51;
+ public static final int BAND_53 = android.hardware.radio.V1_6.NgranBands.BAND_53;
public static final int BAND_65 = android.hardware.radio.V1_5.NgranBands.BAND_65;
public static final int BAND_66 = android.hardware.radio.V1_5.NgranBands.BAND_66;
public static final int BAND_70 = android.hardware.radio.V1_5.NgranBands.BAND_70;
@@ -366,6 +742,7 @@
public static final int BAND_93 = android.hardware.radio.V1_5.NgranBands.BAND_93;
public static final int BAND_94 = android.hardware.radio.V1_5.NgranBands.BAND_94;
public static final int BAND_95 = android.hardware.radio.V1_5.NgranBands.BAND_95;
+ public static final int BAND_96 = android.hardware.radio.V1_6.NgranBands.BAND_96;
/** 3GPP TS 38.101-2, Version 16.2.0, Table 5.2-1: FR2 bands */
public static final int BAND_257 = android.hardware.radio.V1_5.NgranBands.BAND_257;
@@ -390,6 +767,7 @@
BAND_18,
BAND_20,
BAND_25,
+ BAND_26,
BAND_28,
BAND_29,
BAND_30,
@@ -398,9 +776,11 @@
BAND_39,
BAND_40,
BAND_41,
+ BAND_46,
BAND_48,
BAND_50,
BAND_51,
+ BAND_53,
BAND_65,
BAND_66,
BAND_70,
@@ -424,6 +804,7 @@
BAND_93,
BAND_94,
BAND_95,
+ BAND_96,
BAND_257,
BAND_258,
BAND_260,
@@ -464,7 +845,8 @@
value = {
FREQUENCY_RANGE_GROUP_UNKNOWN,
FREQUENCY_RANGE_GROUP_1,
- FREQUENCY_RANGE_GROUP_2})
+ FREQUENCY_RANGE_GROUP_2
+ })
public @interface FrequencyRangeGroup {}
/**
@@ -489,6 +871,7 @@
case BAND_18:
case BAND_20:
case BAND_25:
+ case BAND_26:
case BAND_28:
case BAND_29:
case BAND_30:
@@ -497,9 +880,11 @@
case BAND_39:
case BAND_40:
case BAND_41:
+ case BAND_46:
case BAND_48:
case BAND_50:
case BAND_51:
+ case BAND_53:
case BAND_65:
case BAND_66:
case BAND_70:
@@ -523,6 +908,7 @@
case BAND_93:
case BAND_94:
case BAND_95:
+ case BAND_96:
return FREQUENCY_RANGE_GROUP_1;
case BAND_257:
case BAND_258:
@@ -538,6 +924,33 @@
private NgranBands() {}
}
+ /**
+ * 3GPP TS 38.104 Table 5.4.2.1-1 NR-ARFCN parameters for the global frequency raster.
+ *
+ * @hide
+ */
+ enum NgranArfcnFrequency {
+
+ NGRAN_ARFCN_FREQUENCY_RANGE_1(5, 0, 0, 0, 599999),
+ NGRAN_ARFCN_FREQUENCY_RANGE_2(15, 3000000, 600000, 600000, 2016666),
+ NGRAN_ARFCN_FREQUENCY_RANGE_3(60, 24250080, 2016667, 2016667, 3279165);
+
+ NgranArfcnFrequency(int globalKhz, int rangeOffset, int arfcnOffset,
+ int rangeFirst, int rangeLast) {
+ this.globalKhz = globalKhz;
+ this.rangeOffset = rangeOffset;
+ this.arfcnOffset = arfcnOffset;
+ this.rangeFirst = rangeFirst;
+ this.rangeLast = rangeLast;
+ }
+
+ int globalKhz;
+ int rangeOffset;
+ int arfcnOffset;
+ int rangeFirst;
+ int rangeLast;
+ }
+
/** @hide */
private AccessNetworkConstants() {};
}
diff --git a/telephony/java/android/telephony/AccessNetworkUtils.java b/telephony/java/android/telephony/AccessNetworkUtils.java
index 7661a32..f29f3bd 100644
--- a/telephony/java/android/telephony/AccessNetworkUtils.java
+++ b/telephony/java/android/telephony/AccessNetworkUtils.java
@@ -4,12 +4,20 @@
import static android.telephony.ServiceState.DUPLEX_MODE_TDD;
import static android.telephony.ServiceState.DUPLEX_MODE_UNKNOWN;
+import android.telephony.AccessNetworkConstants.EutranBandArfcnFrequency;
import android.telephony.AccessNetworkConstants.EutranBand;
import android.telephony.AccessNetworkConstants.GeranBand;
+import android.telephony.AccessNetworkConstants.GeranBandArfcnFrequency;
+import android.telephony.AccessNetworkConstants.NgranArfcnFrequency;
+import android.telephony.AccessNetworkConstants.NgranBands;
import android.telephony.AccessNetworkConstants.UtranBand;
+import android.telephony.AccessNetworkConstants.UtranBandArfcnFrequency;
import android.telephony.ServiceState.DuplexMode;
+import android.util.Log;
import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
/**
* Utilities to map between radio constants.
@@ -22,9 +30,27 @@
private AccessNetworkUtils() {}
public static final int INVALID_BAND = -1;
+ public static final int INVALID_FREQUENCY = -1;
/** ISO country code of Japan. */
private static final String JAPAN_ISO_COUNTRY_CODE = "jp";
+ private static final String TAG = "AccessNetworkUtils";
+
+ private static final int FREQUENCY_KHZ = 1000;
+ private static final int FREQUENCY_RANGE_LOW_KHZ = 1000000;
+ private static final int FREQUENCY_RANGE_MID_KHZ = 3000000;
+ private static final int FREQUENCY_RANGE_HIGH_KHZ = 6000000;
+
+ private static final Set<Integer> UARFCN_NOT_GENERAL_BAND;
+ static {
+ UARFCN_NOT_GENERAL_BAND = new HashSet<Integer>();
+ UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_A);
+ UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_B);
+ UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_C);
+ UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_D);
+ UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_E);
+ UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_F);
+ }
/**
* Gets the duplex mode for the given EUTRAN operating band.
@@ -325,4 +351,403 @@
}
return INVALID_BAND;
}
+
+ /**
+ * Get geran bands from {@link PhysicalChannelConfig#getBand()}
+ */
+ public static int getFrequencyRangeGroupFromGeranBand(@GeranBand.GeranBands int band) {
+ switch (band) {
+ case GeranBand.BAND_T380:
+ case GeranBand.BAND_T410:
+ case GeranBand.BAND_450:
+ case GeranBand.BAND_480:
+ case GeranBand.BAND_710:
+ case GeranBand.BAND_750:
+ case GeranBand.BAND_T810:
+ case GeranBand.BAND_850:
+ case GeranBand.BAND_P900:
+ case GeranBand.BAND_E900:
+ case GeranBand.BAND_R900:
+ case GeranBand.BAND_ER900:
+ return ServiceState.FREQUENCY_RANGE_LOW;
+ case GeranBand.BAND_DCS1800:
+ case GeranBand.BAND_PCS1900:
+ return ServiceState.FREQUENCY_RANGE_MID;
+ default:
+ return ServiceState.FREQUENCY_RANGE_UNKNOWN;
+ }
+ }
+
+ /**
+ * Get utran bands from {@link PhysicalChannelConfig#getBand()}
+ */
+ public static int getFrequencyRangeGroupFromUtranBand(@UtranBand.UtranBands int band) {
+ switch (band) {
+ case UtranBand.BAND_5:
+ case UtranBand.BAND_6:
+ case UtranBand.BAND_8:
+ case UtranBand.BAND_12:
+ case UtranBand.BAND_13:
+ case UtranBand.BAND_14:
+ case UtranBand.BAND_19:
+ case UtranBand.BAND_20:
+ case UtranBand.BAND_26:
+ return ServiceState.FREQUENCY_RANGE_LOW;
+ case UtranBand.BAND_1:
+ case UtranBand.BAND_2:
+ case UtranBand.BAND_3:
+ case UtranBand.BAND_4:
+ case UtranBand.BAND_7:
+ case UtranBand.BAND_9:
+ case UtranBand.BAND_10:
+ case UtranBand.BAND_11:
+ case UtranBand.BAND_21:
+ case UtranBand.BAND_25:
+ case UtranBand.BAND_A:
+ case UtranBand.BAND_B:
+ case UtranBand.BAND_C:
+ case UtranBand.BAND_D:
+ case UtranBand.BAND_E:
+ case UtranBand.BAND_F:
+ return ServiceState.FREQUENCY_RANGE_MID;
+ case UtranBand.BAND_22:
+ return ServiceState.FREQUENCY_RANGE_HIGH;
+ default:
+ return ServiceState.FREQUENCY_RANGE_UNKNOWN;
+ }
+ }
+
+ /**
+ * Get eutran bands from {@link PhysicalChannelConfig#getBand()}
+ * 3GPP TS 36.101 Table 5.5 EUTRA operating bands
+ */
+ public static int getFrequencyRangeGroupFromEutranBand(@EutranBand.EutranBands int band) {
+ switch (band) {
+ case EutranBand.BAND_5:
+ case EutranBand.BAND_6:
+ case EutranBand.BAND_8:
+ case EutranBand.BAND_12:
+ case EutranBand.BAND_13:
+ case EutranBand.BAND_14:
+ case EutranBand.BAND_17:
+ case EutranBand.BAND_18:
+ case EutranBand.BAND_19:
+ case EutranBand.BAND_20:
+ case EutranBand.BAND_26:
+ case EutranBand.BAND_27:
+ case EutranBand.BAND_28:
+ case EutranBand.BAND_31:
+ case EutranBand.BAND_44:
+ case EutranBand.BAND_50:
+ case EutranBand.BAND_51:
+ case EutranBand.BAND_68:
+ case EutranBand.BAND_71:
+ case EutranBand.BAND_72:
+ case EutranBand.BAND_73:
+ case EutranBand.BAND_85:
+ case EutranBand.BAND_87:
+ case EutranBand.BAND_88:
+ return ServiceState.FREQUENCY_RANGE_LOW;
+ case EutranBand.BAND_1:
+ case EutranBand.BAND_2:
+ case EutranBand.BAND_3:
+ case EutranBand.BAND_4:
+ case EutranBand.BAND_7:
+ case EutranBand.BAND_9:
+ case EutranBand.BAND_10:
+ case EutranBand.BAND_11:
+ case EutranBand.BAND_21:
+ case EutranBand.BAND_23:
+ case EutranBand.BAND_24:
+ case EutranBand.BAND_25:
+ case EutranBand.BAND_30:
+ case EutranBand.BAND_33:
+ case EutranBand.BAND_34:
+ case EutranBand.BAND_35:
+ case EutranBand.BAND_36:
+ case EutranBand.BAND_37:
+ case EutranBand.BAND_38:
+ case EutranBand.BAND_39:
+ case EutranBand.BAND_40:
+ case EutranBand.BAND_41:
+ case EutranBand.BAND_45:
+ case EutranBand.BAND_53:
+ case EutranBand.BAND_65:
+ case EutranBand.BAND_66:
+ case EutranBand.BAND_70:
+ case EutranBand.BAND_74:
+ return ServiceState.FREQUENCY_RANGE_MID;
+ case EutranBand.BAND_22:
+ case EutranBand.BAND_42:
+ case EutranBand.BAND_43:
+ case EutranBand.BAND_46:
+ case EutranBand.BAND_47:
+ case EutranBand.BAND_48:
+ case EutranBand.BAND_49:
+ case EutranBand.BAND_52:
+ return ServiceState.FREQUENCY_RANGE_HIGH;
+ default:
+ return ServiceState.FREQUENCY_RANGE_UNKNOWN;
+ }
+ }
+
+ /**
+ * Get ngran band from {@link PhysicalChannelConfig#getBand()}
+ * 3GPP TS 38.104 Table 5.2-1 NR operating bands in FR1
+ * 3GPP TS 38.104 Table 5.2-2 NR operating bands in FR2
+ */
+ public static int getFrequencyRangeGroupFromNrBand(@NgranBands.NgranBand int band) {
+ switch (band) {
+ case NgranBands.BAND_5:
+ case NgranBands.BAND_8:
+ case NgranBands.BAND_12:
+ case NgranBands.BAND_14:
+ case NgranBands.BAND_18:
+ case NgranBands.BAND_20:
+ case NgranBands.BAND_26:
+ case NgranBands.BAND_28:
+ case NgranBands.BAND_29:
+ case NgranBands.BAND_71:
+ case NgranBands.BAND_81:
+ case NgranBands.BAND_82:
+ case NgranBands.BAND_83:
+ case NgranBands.BAND_89:
+ return ServiceState.FREQUENCY_RANGE_LOW;
+ case NgranBands.BAND_1:
+ case NgranBands.BAND_2:
+ case NgranBands.BAND_3:
+ case NgranBands.BAND_7:
+ case NgranBands.BAND_25:
+ case NgranBands.BAND_30:
+ case NgranBands.BAND_34:
+ case NgranBands.BAND_38:
+ case NgranBands.BAND_39:
+ case NgranBands.BAND_40:
+ case NgranBands.BAND_41:
+ case NgranBands.BAND_50:
+ case NgranBands.BAND_51:
+ case NgranBands.BAND_53:
+ case NgranBands.BAND_65:
+ case NgranBands.BAND_66:
+ case NgranBands.BAND_70:
+ case NgranBands.BAND_74:
+ case NgranBands.BAND_75:
+ case NgranBands.BAND_76:
+ case NgranBands.BAND_80:
+ case NgranBands.BAND_84:
+ case NgranBands.BAND_86:
+ case NgranBands.BAND_90:
+ case NgranBands.BAND_91:
+ case NgranBands.BAND_92:
+ case NgranBands.BAND_93:
+ case NgranBands.BAND_94:
+ case NgranBands.BAND_95:
+ return ServiceState.FREQUENCY_RANGE_MID;
+ case NgranBands.BAND_46:
+ case NgranBands.BAND_48:
+ case NgranBands.BAND_77:
+ case NgranBands.BAND_78:
+ case NgranBands.BAND_79:
+ return ServiceState.FREQUENCY_RANGE_HIGH;
+ case NgranBands.BAND_96:
+ case NgranBands.BAND_257:
+ case NgranBands.BAND_258:
+ case NgranBands.BAND_260:
+ case NgranBands.BAND_261:
+ return ServiceState.FREQUENCY_RANGE_MMWAVE;
+ default:
+ return ServiceState.FREQUENCY_RANGE_UNKNOWN;
+ }
+ }
+
+ /**
+ * 3GPP TS 38.104 Table 5.4.2.1-1 NR-ARFCN parameters for the global frequency raster.
+ * Formula of NR-ARFCN convert to actual frequency:
+ * Actual frequency(kHz) = (RANGE_OFFSET + GLOBAL_KHZ * (ARFCN - ARFCN_OFFSET))
+ */
+ public static int getFrequencyFromNrArfcn(int nrArfcn) {
+
+ int globalKhz = 0;
+ int rangeOffset = 0;
+ int arfcnOffset = 0;
+ for (NgranArfcnFrequency nrArfcnFrequency : AccessNetworkConstants.
+ NgranArfcnFrequency.values()) {
+ if (nrArfcn >= nrArfcnFrequency.rangeFirst
+ && nrArfcn <= nrArfcnFrequency.rangeLast) {
+ globalKhz = nrArfcnFrequency.globalKhz;
+ rangeOffset = nrArfcnFrequency.rangeOffset;
+ arfcnOffset = nrArfcnFrequency.arfcnOffset;
+ break;
+ }
+ }
+ return rangeOffset + globalKhz * (nrArfcn - arfcnOffset);
+ }
+
+ /**
+ * Get actual frequency from E-UTRA ARFCN.
+ */
+ public static int getFrequencyFromEarfcn(int band, int earfcn, boolean isUplink) {
+
+ int low = 0;
+ int offset = 0;
+ for (EutranBandArfcnFrequency earfcnFrequency : EutranBandArfcnFrequency.values()) {
+ if (band == earfcnFrequency.band) {
+ if (isInEarfcnRange(earfcn, earfcnFrequency, isUplink)) {
+ low = isUplink ? earfcnFrequency.uplinkLowKhz : earfcnFrequency.downlinkLowKhz;
+ offset = isUplink ? earfcnFrequency.uplinkOffset
+ : earfcnFrequency.downlinkOffset;
+ break;
+ } else {
+ Log.e(TAG, "Band and the range of EARFCN are not consistent.");
+ return INVALID_FREQUENCY;
+ }
+ }
+ }
+ return convertEarfcnToFrequency(low, earfcn, offset);
+ }
+
+ /**
+ * 3GPP TS 36.101 Table 5.7.3-1 E-UTRA channel numbers.
+ * Formula of E-UTRA ARFCN convert to actual frequency:
+ * Actual frequency(kHz) = (DOWNLINK_LOW + 0.1 * (ARFCN - DOWNLINK_OFFSET)) * FREQUENCY_KHZ
+ * Actual frequency(kHz) = (UPLINK_LOW + 0.1 * (ARFCN - UPLINK_OFFSET)) * FREQUENCY_KHZ
+ */
+ private static int convertEarfcnToFrequency(int low, int earfcn, int offset) {
+ return low + 100 * (earfcn - offset);
+ }
+
+ private static boolean isInEarfcnRange(int earfcn, EutranBandArfcnFrequency earfcnFrequency,
+ boolean isUplink) {
+ if (isUplink) {
+ return earfcn >= earfcnFrequency.uplinkOffset && earfcn <= earfcnFrequency.uplinkRange;
+ } else {
+ return earfcn >= earfcnFrequency.downlinkOffset
+ && earfcn <= earfcnFrequency.downlinkRange;
+ }
+ }
+
+ /**
+ * Get actual frequency from UTRA ARFCN.
+ */
+ public static int getFrequencyFromUarfcn(int band, int uarfcn, boolean isUplink) {
+
+ int offsetKhz = 0;
+ for (UtranBandArfcnFrequency uarfcnFrequency : AccessNetworkConstants.
+ UtranBandArfcnFrequency.values()) {
+ if (band == uarfcnFrequency.band) {
+ if (isInUarfcnRange(uarfcn, uarfcnFrequency, isUplink)) {
+ offsetKhz = isUplink ? uarfcnFrequency.uplinkOffset
+ : uarfcnFrequency.downlinkOffset;
+ break;
+ } else {
+ Log.e(TAG, "Band and the range of UARFCN are not consistent.");
+ return INVALID_FREQUENCY;
+ }
+ }
+ }
+
+ if (!UARFCN_NOT_GENERAL_BAND.contains(band)) {
+ return convertUarfcnToFrequency(offsetKhz, uarfcn);
+ } else {
+ return convertUarfcnTddToFrequency(band, uarfcn);
+ }
+ }
+
+ /**
+ * 3GPP TS 25.101, Table 5.1 UARFCN definition (general).
+ * Formula of UTRA ARFCN convert to actual frequency:
+ * For general bands:
+ * Downlink actual frequency(kHz) = (DOWNLINK_OFFSET + 0.2 * ARFCN) * FREQUENCY_KHZ
+ * Uplink actual frequency(kHz) = (UPLINK_OFFSET + 0.2 * ARFCN) * FREQUENCY_KHZ
+ */
+ private static int convertUarfcnToFrequency(int offsetKhz, int uarfcn) {
+ return offsetKhz + (200 * uarfcn);
+ }
+
+ /**
+ * 3GPP TS 25.102, Table 5.2 UTRA Absolute Radio Frequency Channel Number 1.28 Mcps TDD Option.
+ * For FDD bands A, B, C, E, F:
+ * Actual frequency(kHz) = 5 * ARFCN * FREQUENCY_KHZ
+ * For TDD bands D:
+ * Actual frequency(kHz) = (5 * (ARFCN - 2150.1MHz)) * FREQUENCY_KHZ
+ */
+ private static int convertUarfcnTddToFrequency(int band, int uarfcn) {
+ if (band != UtranBand.BAND_D) {
+ return 5 * uarfcn * FREQUENCY_KHZ;
+ } else {
+ return 5 * ((FREQUENCY_KHZ * uarfcn) - 2150100);
+ }
+ }
+
+ private static boolean isInUarfcnRange(int uarfcn, UtranBandArfcnFrequency uarfcnFrequency,
+ boolean isUplink) {
+ if (isUplink) {
+ return uarfcn >= uarfcnFrequency.uplinkRangeFirst
+ && uarfcn <= uarfcnFrequency.uplinkRangeLast;
+ } else {
+ if (uarfcnFrequency.downlinkRangeFirst != 0 && uarfcnFrequency.downlinkRangeLast != 0) {
+ return uarfcn >= uarfcnFrequency.downlinkRangeFirst
+ && uarfcn <= uarfcnFrequency.downlinkRangeLast;
+ } else {
+ // BAND_C, BAND_D, BAND_E and BAND_F do not have the downlink range.
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Get actual frequency from GERAN ARFCN.
+ */
+ public static int getFrequencyFromArfcn(int band, int arfcn, boolean isUplink) {
+
+ int uplinkFrequencyFirst = 0;
+ int arfcnOffset = 0;
+ int downlinkOffset = 0;
+ int frequency = 0;
+ for (GeranBandArfcnFrequency arfcnFrequency : AccessNetworkConstants.
+ GeranBandArfcnFrequency.values()) {
+ if (band == arfcnFrequency.band) {
+ if (arfcn >= arfcnFrequency.arfcnRangeFirst
+ && arfcn <= arfcnFrequency.arfcnRangeLast) {
+ uplinkFrequencyFirst = arfcnFrequency.uplinkFrequencyFirst;
+ downlinkOffset = arfcnFrequency.downlinkOffset;
+ arfcnOffset = arfcnFrequency.arfcnOffset;
+ frequency = convertArfcnToFrequency(arfcn, uplinkFrequencyFirst,
+ arfcnOffset);
+ break;
+ } else {
+ Log.e(TAG, "Band and the range of ARFCN are not consistent.");
+ return INVALID_FREQUENCY;
+ }
+ }
+ }
+
+ return isUplink ? frequency : frequency + downlinkOffset;
+ }
+
+ /**
+ * 3GPP TS 45.005 Table 2-1 Dynamically mapped ARFCN
+ * Formula of Geran ARFCN convert to actual frequency:
+ * Uplink actual frequency(kHz) =
+ * (UPLINK_FREQUENCY_FIRST + 0.2 * (ARFCN - ARFCN_RANGE_FIRST)) * FREQUENCY_KHZ
+ * Downlink actual frequency(kHz) = Uplink actual frequency + 10
+ */
+ private static int convertArfcnToFrequency(int arfcn, int uplinkFrequencyFirstKhz,
+ int arfcnOffset) {
+ return uplinkFrequencyFirstKhz + 200 * (arfcn - arfcnOffset);
+ }
+
+ public static int getFrequencyRangeFromArfcn(int frequency) {
+ if (frequency < FREQUENCY_RANGE_LOW_KHZ) {
+ return ServiceState.FREQUENCY_RANGE_LOW;
+ } else if (frequency < FREQUENCY_RANGE_MID_KHZ
+ && frequency >= FREQUENCY_RANGE_LOW_KHZ) {
+ return ServiceState.FREQUENCY_RANGE_MID;
+ } else if (frequency < FREQUENCY_RANGE_HIGH_KHZ
+ && frequency >= FREQUENCY_RANGE_MID_KHZ) {
+ return ServiceState.FREQUENCY_RANGE_HIGH;
+ } else {
+ return ServiceState.FREQUENCY_RANGE_MMWAVE;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 7e019cc..426da52 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3591,6 +3591,28 @@
*/
public static final String ENABLE_EAP_METHOD_PREFIX_BOOL = "enable_eap_method_prefix_bool";
+
+ /**
+ * Configs used by ImsServiceEntitlement.
+ */
+ public static final class ImsServiceEntitlement {
+ private ImsServiceEntitlement() {}
+
+ /** Prefix of all ImsServiceEntitlement.KEY_* constants. */
+ public static final String KEY_PREFIX = "imsserviceentitlement.";
+
+
+ /** The address of the entitlement configuration server. */
+ public static final String KEY_AES_URL_STRING = KEY_PREFIX + "aes_url_string";
+
+
+ private static PersistableBundle getDefaults() {
+ PersistableBundle defaults = new PersistableBundle();
+ defaults.putString(KEY_AES_URL_STRING, "");
+ return defaults;
+ }
+ }
+
/**
* GPS configs. See the GNSS HAL documentation for more details.
*/
@@ -4621,6 +4643,13 @@
*/
public static final String KEY_USE_ACS_FOR_RCS_BOOL = "use_acs_for_rcs_bool";
+ /**
+ * Indicates temporarily unmetered mobile data is supported by the carrier.
+ * @hide
+ */
+ public static final String KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL =
+ "network_temp_not_metered_supported_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -5119,6 +5148,7 @@
sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG, 10000);
/* Default value is 60 seconds. */
sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG, 60000);
+ sDefaults.putAll(ImsServiceEntitlement.getDefaults());
sDefaults.putAll(Gps.getDefaults());
sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY,
new int[] {
@@ -5170,6 +5200,7 @@
sDefaults.putString(KEY_CALL_COMPOSER_PICTURE_SERVER_URL_STRING, "");
sDefaults.putBoolean(KEY_USE_LOWER_MTU_VALUE_IF_BOTH_RECEIVED, false);
sDefaults.putBoolean(KEY_USE_ACS_FOR_RCS_BOOL, false);
+ sDefaults.putBoolean(KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL, false);
}
/**
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index ed09d53..1273aa3a 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -478,7 +478,9 @@
/**
* Compare phone numbers a and b, return true if they're identical enough for caller ID purposes.
+ * @deprecated use {@link #areSamePhoneNumber(String, String, String)} instead
*/
+ @Deprecated
public static boolean compare(String a, String b) {
// We've used loose comparation at least Eclair, which may change in the future.
@@ -489,7 +491,9 @@
* Compare phone numbers a and b, and return true if they're identical
* enough for caller ID purposes. Checks a resource to determine whether
* to use a strict or loose comparison algorithm.
+ * @deprecated use {@link #areSamePhoneNumber(String, String, String)} instead
*/
+ @Deprecated
public static boolean compare(Context context, String a, String b) {
boolean useStrict = context.getResources().getBoolean(
com.android.internal.R.bool.config_use_strict_phone_number_comparation);
@@ -3218,7 +3222,7 @@
}
// The conversion map is not defined (this is default). Skip conversion.
- if (sConvertToEmergencyMap == null || sConvertToEmergencyMap.length == 0 ) {
+ if (sConvertToEmergencyMap == null || sConvertToEmergencyMap.length == 0) {
return number;
}
@@ -3254,4 +3258,47 @@
}
return number;
}
+
+ /**
+ * Determines if two phone numbers are the same.
+ * <p>
+ * Matching is based on <a href="https://github.com/google/libphonenumber>libphonenumber</a>.
+ * Unlike {@link #compare(String, String)}, matching takes into account national
+ * dialing plans rather than simply matching the last 7 digits of the two phone numbers. As a
+ * result, it is expected that some numbers which would match using the previous method will no
+ * longer match using this new approach.
+ *
+ * @param number1
+ * @param number2
+ * @param defaultCountryIso The lowercase two letter ISO 3166-1 country code. Used when parsing
+ * the phone numbers where it is not possible to determine the country
+ * associated with a phone number based on the number alone. It
+ * is recommended to pass in
+ * {@link TelephonyManager#getNetworkCountryIso()}.
+ * @return True if the two given phone number are same.
+ */
+ public static boolean areSamePhoneNumber(@NonNull String number1,
+ @NonNull String number2, @NonNull String defaultCountryIso) {
+ PhoneNumberUtil util = PhoneNumberUtil.getInstance();
+ PhoneNumber n1;
+ PhoneNumber n2;
+ defaultCountryIso = defaultCountryIso.toUpperCase();
+ try {
+ n1 = util.parseAndKeepRawInput(number1, defaultCountryIso);
+ n2 = util.parseAndKeepRawInput(number2, defaultCountryIso);
+ } catch (NumberParseException e) {
+ return false;
+ }
+
+ PhoneNumberUtil.MatchType matchType = util.isNumberMatch(n1, n2);
+ if (matchType == PhoneNumberUtil.MatchType.EXACT_MATCH
+ || matchType == PhoneNumberUtil.MatchType.NSN_MATCH) {
+ return true;
+ } else if (matchType == PhoneNumberUtil.MatchType.SHORT_NSN_MATCH) {
+ return (n1.getNationalNumber() == n2.getNationalNumber()
+ && n1.getCountryCode() == n2.getCountryCode());
+ } else {
+ return false;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java
index 95c69ba..b359ebe 100644
--- a/telephony/java/android/telephony/PhysicalChannelConfig.java
+++ b/telephony/java/android/telephony/PhysicalChannelConfig.java
@@ -19,7 +19,6 @@
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
-import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Annotation.NetworkType;
@@ -56,6 +55,18 @@
/** Physical Cell Id is unknown. */
public static final int PHYSICAL_CELL_ID_UNKNOWN = -1;
+ /** Physical Cell Id's maximum value is 1007. */
+ public static final int PHYSICAL_CELL_ID_MAXIMUM_VALUE = 1007;
+
+ /** Cell bandwidth is unknown. */
+ public static final int CELL_BANDWIDTH_UNKNOWN = 0;
+
+ /** The frequency is unknown. */
+ public static final int FREQUENCY_UNKNOWN = -1;
+
+ /** The band is unknown. */
+ public static final int BAND_UNKNOWN = 0;
+
/**
* Connection status of the cell.
*
@@ -65,15 +76,20 @@
private int mCellConnectionStatus;
/**
- * Cell bandwidth, in kHz.
+ * Downlink cell bandwidth, in kHz.
*/
private int mCellBandwidthDownlinkKhz;
/**
+ * Uplink cell bandwidth, in kHz.
+ */
+ private int mCellBandwidthUplinkKhz;
+
+ /**
* The radio technology for this physical channel.
*/
@NetworkType
- private int mRat;
+ private int mNetworkType;
/**
* The rough frequency range for this physical channel.
@@ -82,9 +98,24 @@
private int mFrequencyRange;
/**
- * The absolute radio frequency channel number, {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
+ * The frequency of Downlink.
*/
- private int mChannelNumber;
+ private int mDownlinkFrequency;
+
+ /**
+ * The frequency of Uplink.
+ */
+ private int mUplinkFrequency;
+
+ /**
+ * Downlink Absolute Radio Frequency Channel Number
+ */
+ private int mDownlinkChannelNumber;
+
+ /**
+ * Uplink Absolute Radio Frequency Channel Number
+ */
+ private int mUplinkChannelNumber;
/**
* A list of data calls mapped to this physical channel. An empty list means the physical
@@ -98,6 +129,11 @@
*/
private int mPhysicalCellId;
+ /**
+ * This is the band which is being used.
+ */
+ private int mBand;
+
@Override
public int describeContents() {
return 0;
@@ -107,27 +143,39 @@
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mCellConnectionStatus);
dest.writeInt(mCellBandwidthDownlinkKhz);
- dest.writeInt(mRat);
- dest.writeInt(mChannelNumber);
+ dest.writeInt(mCellBandwidthUplinkKhz);
+ dest.writeInt(mNetworkType);
+ dest.writeInt(mDownlinkChannelNumber);
+ dest.writeInt(mUplinkChannelNumber);
dest.writeInt(mFrequencyRange);
dest.writeIntArray(mContextIds);
dest.writeInt(mPhysicalCellId);
+ dest.writeInt(mBand);
}
/**
- * @return Cell bandwidth, in kHz
+ * @return Downlink cell bandwidth in kHz, {@link #CELL_BANDWIDTH_UNKNOWN} if unknown.
*/
- public int getCellBandwidthDownlink() {
+ @IntRange(from = 1)
+ public int getCellBandwidthDownlinkKhz() {
return mCellBandwidthDownlinkKhz;
}
/**
+ * @return Uplink cell bandwidth in kHz, {@link #CELL_BANDWIDTH_UNKNOWN} if unknown.
+ */
+ @IntRange(from = 1)
+ public int getCellBandwidthUplinkKhz() {
+ return mCellBandwidthUplinkKhz;
+ }
+
+ /**
* Get the list of data call ids mapped to this physical channel. This list is sorted into
* ascending numerical order. Each id in this list must match the id in
* {@link com.android.internal.telephony.dataconnection.DataConnection}. An empty list means the
* physical channel has no data call mapped to it.
*
- * @return an integer list indicates the data call ids.
+ * @return an integer list indicates the data call ids,
* @hide
*/
public int[] getContextIds() {
@@ -135,7 +183,18 @@
}
/**
- * @return the rough frequency range for this physical channel.
+ * @return the absolute radio frequency channel number for this physical channel,
+ * {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
+ * @deprecated Use {@link #getDownlinkChannelNumber()} to get the channel number.
+ */
+ @Deprecated
+ public int getChannelNumber() {
+ return getDownlinkChannelNumber();
+ }
+
+ /**
+ * @return the rough frequency range for this physical channel,
+ * {@link ServiceState#FREQUENCY_RANGE_UNKNOWN} if unknown.
* @see {@link ServiceState#FREQUENCY_RANGE_LOW}
* @see {@link ServiceState#FREQUENCY_RANGE_MID}
* @see {@link ServiceState#FREQUENCY_RANGE_HIGH}
@@ -148,11 +207,48 @@
}
/**
- * @return the absolute radio frequency channel number for this physical channel,
+ * @return Downlink Absolute Radio Frequency Channel Number,
* {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
*/
- public int getChannelNumber() {
- return mChannelNumber;
+ @IntRange(from = 0)
+ public int getDownlinkChannelNumber() {
+ return mDownlinkChannelNumber;
+ }
+
+ /**
+ * @return Uplink Absolute Radio Frequency Channel Number,
+ * {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
+ */
+ @IntRange(from = 0)
+ public int getUplinkChannelNumber() {
+ return mUplinkChannelNumber;
+ }
+
+ /**
+ * The valid bands are {@link AccessNetworkConstants.GeranBand},
+ * {@link AccessNetworkConstants.UtranBand}, {@link AccessNetworkConstants.EutranBand} and
+ * {@link AccessNetworkConstants.NgranBands}.
+ *
+ * @return the frequency band, {@link #BAND_UNKNOWN} if unknown. */
+ @IntRange(from = 1, to = 261)
+ public int getBand() {
+ return mBand;
+ }
+
+ /**
+ * @return The downlink frequency in kHz, {@link #FREQUENCY_UNKNOWN} if unknown.
+ */
+ @IntRange(from = 0)
+ public int getDownlinkFrequencyKhz() {
+ return mDownlinkFrequency;
+ }
+
+ /**
+ * @return The uplink frequency in kHz, {@link #FREQUENCY_UNKNOWN} if unknown.
+ */
+ @IntRange(from = 0)
+ public int getUplinkFrequencyKhz() {
+ return mUplinkFrequency;
}
/**
@@ -173,10 +269,13 @@
return mPhysicalCellId;
}
- /**The radio technology for this physical channel. */
+ /**
+ * @return The network type for this physical channel,
+ * {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if unknown.
+ */
@NetworkType
public int getNetworkType() {
- return mRat;
+ return mNetworkType;
}
/**
@@ -186,7 +285,7 @@
* @see #CONNECTION_SECONDARY_SERVING
* @see #CONNECTION_UNKNOWN
*
- * @return Connection status of the cell
+ * @return Connection status of the cell, {@link #CONNECTION_UNKNOWN} if unknown.
*/
@ConnectionStatus
public int getConnectionStatus() {
@@ -210,6 +309,97 @@
}
}
+ private void setDownlinkFrequency() {
+ switch (mNetworkType) {
+ case TelephonyManager.NETWORK_TYPE_NR:
+ mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromNrArfcn(
+ mDownlinkChannelNumber);
+ break;
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromEarfcn(
+ mBand, mDownlinkChannelNumber, false);
+ break;
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromUarfcn(
+ mBand, mDownlinkChannelNumber, false);
+ break;
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_GSM:
+ mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromArfcn(
+ mBand, mDownlinkChannelNumber, false);
+ break;
+ }
+ }
+
+ private void setUplinkFrequency() {
+ switch (mNetworkType){
+ case TelephonyManager.NETWORK_TYPE_NR:
+ mUplinkFrequency = mDownlinkFrequency;
+ break;
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ mUplinkFrequency = AccessNetworkUtils.getFrequencyFromEarfcn(
+ mBand, mUplinkChannelNumber, true);
+ break;
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ mUplinkFrequency = AccessNetworkUtils.getFrequencyFromUarfcn(
+ mBand, mUplinkChannelNumber, true);
+ break;
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_GSM:
+ mUplinkFrequency = AccessNetworkUtils.getFrequencyFromArfcn(
+ mBand, mUplinkChannelNumber, true);
+ break;
+ }
+ }
+
+ private void setFrequencyRange() {
+ if (mFrequencyRange != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+ return;
+ }
+
+ switch (mNetworkType) {
+ case TelephonyManager.NETWORK_TYPE_NR:
+ mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromNrBand(mBand);
+ break;
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromEutranBand(mBand);
+ break;
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromUtranBand(mBand);
+ break;
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_GSM:
+ mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromGeranBand(mBand);
+ break;
+ default:
+ mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
+ break;
+ }
+
+ if (mFrequencyRange == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+ mFrequencyRange = AccessNetworkUtils.getFrequencyRangeFromArfcn(
+ mDownlinkFrequency);
+ }
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -223,30 +413,37 @@
PhysicalChannelConfig config = (PhysicalChannelConfig) o;
return mCellConnectionStatus == config.mCellConnectionStatus
&& mCellBandwidthDownlinkKhz == config.mCellBandwidthDownlinkKhz
- && mRat == config.mRat
+ && mCellBandwidthUplinkKhz == config.mCellBandwidthUplinkKhz
+ && mNetworkType == config.mNetworkType
&& mFrequencyRange == config.mFrequencyRange
- && mChannelNumber == config.mChannelNumber
+ && mDownlinkChannelNumber == config.mDownlinkChannelNumber
+ && mUplinkChannelNumber == config.mUplinkChannelNumber
&& mPhysicalCellId == config.mPhysicalCellId
- && Arrays.equals(mContextIds, config.mContextIds);
+ && Arrays.equals(mContextIds, config.mContextIds)
+ && mBand == config.mBand
+ && mDownlinkFrequency == config.mDownlinkFrequency
+ && mUplinkFrequency == config.mUplinkFrequency;
}
@Override
public int hashCode() {
return Objects.hash(
- mCellConnectionStatus, mCellBandwidthDownlinkKhz, mRat, mFrequencyRange,
- mChannelNumber, mPhysicalCellId, mContextIds);
+ mCellConnectionStatus, mCellBandwidthDownlinkKhz, mCellBandwidthUplinkKhz,
+ mNetworkType, mFrequencyRange, mDownlinkChannelNumber, mUplinkChannelNumber,
+ mContextIds, mPhysicalCellId, mBand, mDownlinkFrequency, mUplinkFrequency);
}
- public static final @android.annotation.NonNull Parcelable.Creator<PhysicalChannelConfig> CREATOR =
- new Parcelable.Creator<PhysicalChannelConfig>() {
- public PhysicalChannelConfig createFromParcel(Parcel in) {
- return new PhysicalChannelConfig(in);
- }
+ public static final
+ @android.annotation.NonNull Parcelable.Creator<PhysicalChannelConfig> CREATOR =
+ new Parcelable.Creator<PhysicalChannelConfig>() {
+ public PhysicalChannelConfig createFromParcel(Parcel in) {
+ return new PhysicalChannelConfig(in);
+ }
- public PhysicalChannelConfig[] newArray(int size) {
- return new PhysicalChannelConfig[size];
- }
- };
+ public PhysicalChannelConfig[] newArray(int size) {
+ return new PhysicalChannelConfig[size];
+ }
+ };
@Override
public String toString() {
@@ -255,44 +452,64 @@
.append(getConnectionStatusString())
.append(",mCellBandwidthDownlinkKhz=")
.append(mCellBandwidthDownlinkKhz)
- .append(",mRat=")
- .append(TelephonyManager.getNetworkTypeName(mRat))
+ .append(",mCellBandwidthUplinkKhz=")
+ .append(mCellBandwidthUplinkKhz)
+ .append(",mNetworkType=")
+ .append(TelephonyManager.getNetworkTypeName(mNetworkType))
.append(",mFrequencyRange=")
.append(ServiceState.frequencyRangeToString(mFrequencyRange))
- .append(",mChannelNumber=")
- .append(mChannelNumber)
+ .append(",mDownlinkChannelNumber=")
+ .append(mDownlinkChannelNumber)
+ .append(",mUplinkChannelNumber=")
+ .append(mUplinkChannelNumber)
.append(",mContextIds=")
.append(Arrays.toString(mContextIds))
.append(",mPhysicalCellId=")
.append(mPhysicalCellId)
+ .append(",mBand=")
+ .append(mBand)
+ .append(",mDownlinkFrequency=")
+ .append(mDownlinkFrequency)
+ .append(",mUplinkFrequency=")
+ .append(mUplinkFrequency)
.append("}")
.toString();
}
- /** @hide */
- public PhysicalChannelConfig(int status, int bandwidth) {
- mCellConnectionStatus = status;
- mCellBandwidthDownlinkKhz = bandwidth;
- }
-
private PhysicalChannelConfig(Parcel in) {
mCellConnectionStatus = in.readInt();
mCellBandwidthDownlinkKhz = in.readInt();
- mRat = in.readInt();
- mChannelNumber = in.readInt();
+ mCellBandwidthUplinkKhz = in.readInt();
+ mNetworkType = in.readInt();
+ mDownlinkChannelNumber = in.readInt();
+ mUplinkChannelNumber = in.readInt();
mFrequencyRange = in.readInt();
mContextIds = in.createIntArray();
mPhysicalCellId = in.readInt();
+ mBand = in.readInt();
+ if (mBand > BAND_UNKNOWN) {
+ setDownlinkFrequency();
+ setUplinkFrequency();
+ setFrequencyRange();
+ }
}
private PhysicalChannelConfig(Builder builder) {
mCellConnectionStatus = builder.mCellConnectionStatus;
mCellBandwidthDownlinkKhz = builder.mCellBandwidthDownlinkKhz;
- mRat = builder.mRat;
- mChannelNumber = builder.mChannelNumber;
+ mCellBandwidthUplinkKhz = builder.mCellBandwidthUplinkKhz;
+ mNetworkType = builder.mNetworkType;
+ mDownlinkChannelNumber = builder.mDownlinkChannelNumber;
+ mUplinkChannelNumber = builder.mUplinkChannelNumber;
mFrequencyRange = builder.mFrequencyRange;
mContextIds = builder.mContextIds;
mPhysicalCellId = builder.mPhysicalCellId;
+ mBand = builder.mBand;
+ if (mBand > BAND_UNKNOWN) {
+ setDownlinkFrequency();
+ setUplinkFrequency();
+ setFrequencyRange();
+ }
}
/**
@@ -300,61 +517,105 @@
* @hide
*/
public static final class Builder {
- private int mRat;
+ private int mNetworkType;
private int mFrequencyRange;
- private int mChannelNumber;
+ private int mDownlinkChannelNumber;
+ private int mUplinkChannelNumber;
private int mCellBandwidthDownlinkKhz;
+ private int mCellBandwidthUplinkKhz;
private int mCellConnectionStatus;
private int[] mContextIds;
private int mPhysicalCellId;
+ private int mBand;
public Builder() {
- mRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
+ mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
- mChannelNumber = CHANNEL_NUMBER_UNKNOWN;
- mCellBandwidthDownlinkKhz = 0;
+ mDownlinkChannelNumber = CHANNEL_NUMBER_UNKNOWN;
+ mUplinkChannelNumber = CHANNEL_NUMBER_UNKNOWN;
+ mCellBandwidthDownlinkKhz = CELL_BANDWIDTH_UNKNOWN;
+ mCellBandwidthUplinkKhz = CELL_BANDWIDTH_UNKNOWN;
mCellConnectionStatus = CONNECTION_UNKNOWN;
mContextIds = new int[0];
mPhysicalCellId = PHYSICAL_CELL_ID_UNKNOWN;
+ mBand = BAND_UNKNOWN;
}
public PhysicalChannelConfig build() {
return new PhysicalChannelConfig(this);
}
- public Builder setRat(int rat) {
- this.mRat = rat;
+ public @NonNull Builder setNetworkType(@NetworkType int networkType) {
+ if (!TelephonyManager.isNetworkTypeValid(networkType)) {
+ throw new IllegalArgumentException("Network type: " + networkType + " is invalid.");
+ }
+ mNetworkType = networkType;
return this;
}
- public Builder setFrequencyRange(int frequencyRange) {
- this.mFrequencyRange = frequencyRange;
+ public @NonNull Builder setFrequencyRange(int frequencyRange) {
+ if (!ServiceState.isFrequencyRangeValid(frequencyRange)) {
+ throw new IllegalArgumentException("Frequency range: " + frequencyRange +
+ " is invalid.");
+ }
+ mFrequencyRange = frequencyRange;
return this;
}
- public Builder setChannelNumber(int channelNumber) {
- this.mChannelNumber = channelNumber;
+ public @NonNull Builder setDownlinkChannelNumber(int downlinkChannelNumber) {
+ mDownlinkChannelNumber = downlinkChannelNumber;
return this;
}
- public Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) {
- this.mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
+ public @NonNull Builder setUplinkChannelNumber(int uplinkChannelNumber) {
+ mUplinkChannelNumber = uplinkChannelNumber;
return this;
}
- public Builder setCellConnectionStatus(int connectionStatus) {
- this.mCellConnectionStatus = connectionStatus;
+ public @NonNull Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) {
+ if (cellBandwidthDownlinkKhz < CELL_BANDWIDTH_UNKNOWN) {
+ throw new IllegalArgumentException("Cell downlink bandwidth(kHz): " +
+ cellBandwidthDownlinkKhz + " is invalid.");
+ }
+ mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
return this;
}
- public Builder setContextIds(int[] contextIds) {
+ public @NonNull Builder setCellBandwidthUplinkKhz(int cellBandwidthUplinkKhz) {
+ if (cellBandwidthUplinkKhz < CELL_BANDWIDTH_UNKNOWN) {
+ throw new IllegalArgumentException("Cell uplink bandwidth(kHz): "+
+ cellBandwidthUplinkKhz +" is invalid.");
+ }
+ mCellBandwidthUplinkKhz = cellBandwidthUplinkKhz;
+ return this;
+ }
+
+ public @NonNull Builder setCellConnectionStatus(int connectionStatus) {
+ mCellConnectionStatus = connectionStatus;
+ return this;
+ }
+
+ public @NonNull Builder setContextIds(int[] contextIds) {
if (contextIds != null) Arrays.sort(contextIds);
- this.mContextIds = contextIds;
+ mContextIds = contextIds;
return this;
}
- public Builder setPhysicalCellId(int physicalCellId) {
- this.mPhysicalCellId = physicalCellId;
+ public @NonNull Builder setPhysicalCellId(int physicalCellId) {
+ if (physicalCellId > PHYSICAL_CELL_ID_MAXIMUM_VALUE) {
+ throw new IllegalArgumentException("Physical cell Id: " + physicalCellId +
+ " is over limit.");
+ }
+ mPhysicalCellId = physicalCellId;
+ return this;
+ }
+
+ public @NonNull Builder setBand(int band) {
+ if (band <= BAND_UNKNOWN) {
+ throw new IllegalArgumentException("Band: " + band +
+ " is invalid.");
+ }
+ mBand = band;
return this;
}
}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index dedb1af..f110dae 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -2111,4 +2111,23 @@
}
return false;
}
+
+ /**
+ * The frequency range is valid or not.
+ *
+ * @param frequencyRange The frequency range {@link FrequencyRange}.
+ * @return {@code true} if valid, {@code false} otherwise.
+ *
+ * @hide
+ */
+ public static boolean isFrequencyRangeValid(int frequencyRange) {
+ if (frequencyRange == FREQUENCY_RANGE_LOW
+ || frequencyRange == FREQUENCY_RANGE_MID
+ || frequencyRange == FREQUENCY_RANGE_HIGH
+ || frequencyRange == FREQUENCY_RANGE_MMWAVE) {
+ return true;
+ } else {
+ return false;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/SignalThresholdInfo.java b/telephony/java/android/telephony/SignalThresholdInfo.java
index f6f6d75..bb9c0da3 100644
--- a/telephony/java/android/telephony/SignalThresholdInfo.java
+++ b/telephony/java/android/telephony/SignalThresholdInfo.java
@@ -28,101 +28,109 @@
/**
* Defines the threshold value of the signal strength.
- * @hide
*/
-public class SignalThresholdInfo implements Parcelable {
+public final class SignalThresholdInfo implements Parcelable {
+
+ /**
+ * Unknown signal measurement type.
+ */
+ public static final int SIGNAL_MEASUREMENT_TYPE_UNKNOWN = 0;
+
/**
* Received Signal Strength Indication.
* Range: -113 dBm and -51 dBm
- * Used RAN: GERAN, CDMA2000
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#GERAN},
+ * {@link AccessNetworkConstants.AccessNetworkType#CDMA2000}
* Reference: 3GPP TS 27.007 section 8.5.
*/
- public static final int SIGNAL_RSSI = 1;
+ public static final int SIGNAL_MEASUREMENT_TYPE_RSSI = 1;
/**
* Received Signal Code Power.
* Range: -120 dBm to -25 dBm;
- * Used RAN: UTRAN
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#UTRAN}
* Reference: 3GPP TS 25.123, section 9.1.1.1
*/
- public static final int SIGNAL_RSCP = 2;
+ public static final int SIGNAL_MEASUREMENT_TYPE_RSCP = 2;
/**
* Reference Signal Received Power.
* Range: -140 dBm to -44 dBm;
- * Used RAN: EUTRAN
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
* Reference: 3GPP TS 36.133 9.1.4
*/
- public static final int SIGNAL_RSRP = 3;
+ public static final int SIGNAL_MEASUREMENT_TYPE_RSRP = 3;
/**
* Reference Signal Received Quality
- * Range: -20 dB to -3 dB;
- * Used RAN: EUTRAN
+ * Range: -34 dB to 3 dB;
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
* Reference: 3GPP TS 36.133 9.1.7
*/
- public static final int SIGNAL_RSRQ = 4;
+ public static final int SIGNAL_MEASUREMENT_TYPE_RSRQ = 4;
/**
* Reference Signal Signal to Noise Ratio
* Range: -20 dB to 30 dB;
- * Used RAN: EUTRAN
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
*/
- public static final int SIGNAL_RSSNR = 5;
+ public static final int SIGNAL_MEASUREMENT_TYPE_RSSNR = 5;
/**
* 5G SS reference signal received power.
* Range: -140 dBm to -44 dBm.
- * Used RAN: NGRAN
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
* Reference: 3GPP TS 38.215.
*/
- public static final int SIGNAL_SSRSRP = 6;
+ public static final int SIGNAL_MEASUREMENT_TYPE_SSRSRP = 6;
/**
* 5G SS reference signal received quality.
- * Range: -20 dB to -3 dB.
- * Used RAN: NGRAN
- * Reference: 3GPP TS 38.215.
+ * Range: -43 dB to 20 dB.
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
+ * Reference: 3GPP TS 38.133 section 10.1.11.1.
*/
- public static final int SIGNAL_SSRSRQ = 7;
+ public static final int SIGNAL_MEASUREMENT_TYPE_SSRSRQ = 7;
/**
* 5G SS signal-to-noise and interference ratio.
* Range: -23 dB to 40 dB
- * Used RAN: NGRAN
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
* Reference: 3GPP TS 38.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
*/
- public static final int SIGNAL_SSSINR = 8;
+ public static final int SIGNAL_MEASUREMENT_TYPE_SSSINR = 8;
/** @hide */
- @IntDef(prefix = { "SIGNAL_" }, value = {
- SIGNAL_RSSI,
- SIGNAL_RSCP,
- SIGNAL_RSRP,
- SIGNAL_RSRQ,
- SIGNAL_RSSNR,
- SIGNAL_SSRSRP,
- SIGNAL_SSRSRQ,
- SIGNAL_SSSINR
+ @IntDef(prefix = {"SIGNAL_MEASUREMENT_TYPE_"}, value = {
+ SIGNAL_MEASUREMENT_TYPE_UNKNOWN,
+ SIGNAL_MEASUREMENT_TYPE_RSSI,
+ SIGNAL_MEASUREMENT_TYPE_RSCP,
+ SIGNAL_MEASUREMENT_TYPE_RSRP,
+ SIGNAL_MEASUREMENT_TYPE_RSRQ,
+ SIGNAL_MEASUREMENT_TYPE_RSSNR,
+ SIGNAL_MEASUREMENT_TYPE_SSRSRP,
+ SIGNAL_MEASUREMENT_TYPE_SSRSRQ,
+ SIGNAL_MEASUREMENT_TYPE_SSSINR
})
@Retention(RetentionPolicy.SOURCE)
- public @interface SignalMeasurementType {}
+ public @interface SignalMeasurementType {
+ }
@SignalMeasurementType
- private int mSignalMeasurement;
+ private final int mSignalMeasurementType;
/**
* A hysteresis time in milliseconds to prevent flapping.
* A value of 0 disables hysteresis
*/
- private int mHysteresisMs;
+ private final int mHysteresisMs;
/**
* An interval in dB defining the required magnitude change between reports.
* hysteresisDb must be smaller than the smallest threshold delta.
* An interval value of 0 disables hysteresis.
*/
- private int mHysteresisDb;
+ private final int mHysteresisDb;
/**
* List of threshold values.
@@ -130,60 +138,340 @@
* The threshold values for which to apply criteria.
* A vector size of 0 disables the use of thresholds for reporting.
*/
- private int[] mThresholds = null;
+ private final int[] mThresholds;
/**
* {@code true} means modem must trigger the report based on the criteria;
* {@code false} means modem must not trigger the report based on the criteria.
*/
- private boolean mIsEnabled = true;
+ private final boolean mIsEnabled;
+
+ /**
+ * The radio access network type associated with the signal thresholds.
+ */
+ @AccessNetworkConstants.RadioAccessNetworkType
+ private final int mRan;
/**
* Indicates the hysteresisMs is disabled.
+ *
+ * @hide
*/
public static final int HYSTERESIS_MS_DISABLED = 0;
/**
* Indicates the hysteresisDb is disabled.
+ *
+ * @hide
*/
public static final int HYSTERESIS_DB_DISABLED = 0;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSSI}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSSI_MIN_VALUE = -113;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSSI}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSSI_MAX_VALUE = -51;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSCP}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSCP_MIN_VALUE = -120;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSCP}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSCP_MAX_VALUE = -25;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSRP}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSRP_MIN_VALUE = -140;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSRP}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSRP_MAX_VALUE = -44;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSRQ}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSRQ_MIN_VALUE = -34;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSRQ}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSRQ_MAX_VALUE = 3;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSSNR}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSSNR_MIN_VALUE = -20;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSSNR}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSSNR_MAX_VALUE = 30;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSRSRP}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_SSRSRP_MIN_VALUE = -140;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSRSRP}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_SSRSRP_MAX_VALUE = -44;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSRSRQ}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_SSRSRQ_MIN_VALUE = -43;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSRSRQ}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_SSRSRQ_MAX_VALUE = 20;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSSINR}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_SSSINR_MIN_VALUE = -23;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSSINR}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_SSSINR_MAX_VALUE = 40;
+
/**
* Constructor
*
- * @param signalMeasurement Signal Measurement Type
- * @param hysteresisMs hysteresisMs
- * @param hysteresisDb hysteresisDb
- * @param thresholds threshold value
- * @param isEnabled isEnabled
+ * @param ran Radio Access Network type
+ * @param signalMeasurementType Signal Measurement Type
+ * @param hysteresisMs hysteresisMs
+ * @param hysteresisDb hysteresisDb
+ * @param thresholds threshold value
+ * @param isEnabled isEnabled
*/
- public SignalThresholdInfo(@SignalMeasurementType int signalMeasurement,
- int hysteresisMs, int hysteresisDb, @NonNull int [] thresholds, boolean isEnabled) {
- mSignalMeasurement = signalMeasurement;
+ private SignalThresholdInfo(@AccessNetworkConstants.RadioAccessNetworkType int ran,
+ @SignalMeasurementType int signalMeasurementType, int hysteresisMs, int hysteresisDb,
+ @NonNull int[] thresholds, boolean isEnabled) {
+ Objects.requireNonNull(thresholds, "thresholds must not be null");
+ validateRanWithMeasurementType(ran, signalMeasurementType);
+ validateThresholdRange(signalMeasurementType, thresholds);
+
+ mRan = ran;
+ mSignalMeasurementType = signalMeasurementType;
mHysteresisMs = hysteresisMs < 0 ? HYSTERESIS_MS_DISABLED : hysteresisMs;
mHysteresisDb = hysteresisDb < 0 ? HYSTERESIS_DB_DISABLED : hysteresisDb;
- mThresholds = thresholds == null ? null : thresholds.clone();
+ mThresholds = thresholds;
mIsEnabled = isEnabled;
}
- public @SignalMeasurementType int getSignalMeasurement() {
- return mSignalMeasurement;
+ /**
+ * Builder class to create {@link SignalThresholdInfo} objects.
+ */
+ public static final class Builder {
+ private int mRan = AccessNetworkConstants.AccessNetworkType.UNKNOWN;
+ private int mSignalMeasurementType = SIGNAL_MEASUREMENT_TYPE_UNKNOWN;
+ private int mHysteresisMs = HYSTERESIS_MS_DISABLED;
+ private int mHysteresisDb = HYSTERESIS_DB_DISABLED;
+ private int[] mThresholds = null;
+ private boolean mIsEnabled = false;
+
+ /**
+ * Set the radio access network type for the builder instance.
+ *
+ * @param ran The radio access network type
+ * @return the builder to facilitate the chaining
+ */
+ public @NonNull Builder setRadioAccessNetworkType(
+ @AccessNetworkConstants.RadioAccessNetworkType int ran) {
+ mRan = ran;
+ return this;
+ }
+
+ /**
+ * Set the signal measurement type for the builder instance.
+ *
+ * @param signalMeasurementType The signal measurement type
+ * @return the builder to facilitate the chaining
+ */
+ public @NonNull Builder setSignalMeasurementType(
+ @SignalMeasurementType int signalMeasurementType) {
+ mSignalMeasurementType = signalMeasurementType;
+ return this;
+ }
+
+ /**
+ * Set the hysteresis time in milliseconds to prevent flapping. A value of 0 disables
+ * hysteresis.
+ *
+ * @param hysteresisMs the hysteresis time in milliseconds
+ * @return the builder to facilitate the chaining
+ * @hide
+ */
+ public @NonNull Builder setHysteresisMs(int hysteresisMs) {
+ mHysteresisMs = hysteresisMs;
+ return this;
+ }
+
+ /**
+ * Set the interval in dB defining the required magnitude change between reports. A value of
+ * zero disabled dB-based hysteresis restrictions.
+ *
+ * @param hysteresisDb the interval in dB
+ * @return the builder to facilitate the chaining
+ * @hide
+ */
+ public @NonNull Builder setHysteresisDb(int hysteresisDb) {
+ mHysteresisDb = hysteresisDb;
+ return this;
+ }
+
+ /**
+ * Set the signal strength thresholds of the corresponding signal measurement type.
+ *
+ * The range and unit must reference specific SignalMeasurementType.
+ *
+ * @param thresholds array of integer as the signal threshold values
+ * @return the builder to facilitate the chaining
+ *
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSSI
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSCP
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSRP
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSRQ
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSSNR
+ * @see #SIGNAL_MEASUREMENT_TYPE_SSRSRP
+ * @see #SIGNAL_MEASUREMENT_TYPE_SSRSRQ
+ * @see #SIGNAL_MEASUREMENT_TYPE_SSSINR
+ * @see #getThresholds() for more details on signal strength thresholds
+ */
+ public @NonNull Builder setThresholds(@NonNull int[] thresholds) {
+ Objects.requireNonNull(thresholds, "thresholds must not be null");
+ mThresholds = thresholds.clone();
+ Arrays.sort(mThresholds);
+ return this;
+ }
+
+ /**
+ * Set if the modem should trigger the report based on the criteria.
+ *
+ * @param isEnabled true if the modem should trigger the report based on the criteria
+ * @return the builder to facilitate the chaining
+ * @hide
+ */
+ public @NonNull Builder setIsEnabled(boolean isEnabled) {
+ mIsEnabled = isEnabled;
+ return this;
+ }
+
+ /**
+ * Build {@link SignalThresholdInfo} object.
+ *
+ * @return the SignalThresholdInfo object build out
+ *
+ * @throws IllegalArgumentException if the signal measurement type is invalid, any value in
+ * the thresholds is out of range, or the RAN is not allowed to set with the signal
+ * measurement type
+ */
+ public @NonNull SignalThresholdInfo build() {
+ return new SignalThresholdInfo(mRan, mSignalMeasurementType, mHysteresisMs,
+ mHysteresisDb, mThresholds, mIsEnabled);
+ }
}
+ /**
+ * Get the radio access network type.
+ *
+ * @return radio access network type
+ */
+ public @AccessNetworkConstants.RadioAccessNetworkType int getRadioAccessNetworkType() {
+ return mRan;
+ }
+
+ /**
+ * Get the signal measurement type.
+ *
+ * @return the SignalMeasurementType value
+ */
+ public @SignalMeasurementType int getSignalMeasurementType() {
+ return mSignalMeasurementType;
+ }
+
+ /** @hide */
public int getHysteresisMs() {
return mHysteresisMs;
}
+ /** @hide */
public int getHysteresisDb() {
return mHysteresisDb;
}
+ /** @hide */
public boolean isEnabled() {
return mIsEnabled;
}
- public int[] getThresholds() {
- return mThresholds == null ? null : mThresholds.clone();
+ /**
+ * Get the signal strength thresholds.
+ *
+ * Signal strength thresholds are a list of integer used for suggesting signal level and signal
+ * reporting criteria. The range and unit must reference specific SignalMeasurementType.
+ *
+ * Please refer to https://source.android.com/devices/tech/connect/signal-strength on how signal
+ * strength thresholds are used for signal strength reporting.
+ *
+ * @return array of integer of the signal thresholds
+ *
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSSI
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSCP
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSRP
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSRQ
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSSNR
+ * @see #SIGNAL_MEASUREMENT_TYPE_SSRSRP
+ * @see #SIGNAL_MEASUREMENT_TYPE_SSRSRQ
+ * @see #SIGNAL_MEASUREMENT_TYPE_SSSINR
+ */
+ public @NonNull int[] getThresholds() {
+ return mThresholds.clone();
}
@Override
@@ -192,8 +480,9 @@
}
@Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mSignalMeasurement);
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeInt(mRan);
+ out.writeInt(mSignalMeasurementType);
out.writeInt(mHysteresisMs);
out.writeInt(mHysteresisDb);
out.writeIntArray(mThresholds);
@@ -201,7 +490,8 @@
}
private SignalThresholdInfo(Parcel in) {
- mSignalMeasurement = in.readInt();
+ mRan = in.readInt();
+ mSignalMeasurementType = in.readInt();
mHysteresisMs = in.readInt();
mHysteresisDb = in.readInt();
mThresholds = in.createIntArray();
@@ -217,7 +507,8 @@
}
SignalThresholdInfo other = (SignalThresholdInfo) o;
- return mSignalMeasurement == other.mSignalMeasurement
+ return mRan == other.mRan
+ && mSignalMeasurementType == other.mSignalMeasurementType
&& mHysteresisMs == other.mHysteresisMs
&& mHysteresisDb == other.mHysteresisDb
&& Arrays.equals(mThresholds, other.mThresholds)
@@ -226,8 +517,8 @@
@Override
public int hashCode() {
- return Objects.hash(
- mSignalMeasurement, mHysteresisMs, mHysteresisDb, mThresholds, mIsEnabled);
+ return Objects.hash(mRan, mSignalMeasurementType, mHysteresisMs, mHysteresisDb, mThresholds,
+ mIsEnabled);
}
public static final @NonNull Parcelable.Creator<SignalThresholdInfo> CREATOR =
@@ -246,11 +537,83 @@
@Override
public String toString() {
return new StringBuilder("SignalThresholdInfo{")
- .append("mSignalMeasurement=").append(mSignalMeasurement)
- .append("mHysteresisMs=").append(mSignalMeasurement)
- .append("mHysteresisDb=").append(mHysteresisDb)
- .append("mThresholds=").append(Arrays.toString(mThresholds))
- .append("mIsEnabled=").append(mIsEnabled)
- .append("}").toString();
+ .append("mRan=").append(mRan)
+ .append(" mSignalMeasurementType=").append(mSignalMeasurementType)
+ .append(" mHysteresisMs=").append(mHysteresisMs)
+ .append(" mHysteresisDb=").append(mHysteresisDb)
+ .append(" mThresholds=").append(Arrays.toString(mThresholds))
+ .append(" mIsEnabled=").append(mIsEnabled)
+ .append("}").toString();
+ }
+
+ /**
+ * Return true if signal measurement type is valid and the threshold value is in range.
+ */
+ private static boolean isValidThreshold(@SignalMeasurementType int type, int threshold) {
+ switch (type) {
+ case SIGNAL_MEASUREMENT_TYPE_RSSI:
+ return threshold >= SIGNAL_RSSI_MIN_VALUE && threshold <= SIGNAL_RSSI_MAX_VALUE;
+ case SIGNAL_MEASUREMENT_TYPE_RSCP:
+ return threshold >= SIGNAL_RSCP_MIN_VALUE && threshold <= SIGNAL_RSCP_MAX_VALUE;
+ case SIGNAL_MEASUREMENT_TYPE_RSRP:
+ return threshold >= SIGNAL_RSRP_MIN_VALUE && threshold <= SIGNAL_RSRP_MAX_VALUE;
+ case SIGNAL_MEASUREMENT_TYPE_RSRQ:
+ return threshold >= SIGNAL_RSRQ_MIN_VALUE && threshold <= SIGNAL_RSRQ_MAX_VALUE;
+ case SIGNAL_MEASUREMENT_TYPE_RSSNR:
+ return threshold >= SIGNAL_RSSNR_MIN_VALUE && threshold <= SIGNAL_RSSNR_MAX_VALUE;
+ case SIGNAL_MEASUREMENT_TYPE_SSRSRP:
+ return threshold >= SIGNAL_SSRSRP_MIN_VALUE && threshold <= SIGNAL_SSRSRP_MAX_VALUE;
+ case SIGNAL_MEASUREMENT_TYPE_SSRSRQ:
+ return threshold >= SIGNAL_SSRSRQ_MIN_VALUE && threshold <= SIGNAL_SSRSRQ_MAX_VALUE;
+ case SIGNAL_MEASUREMENT_TYPE_SSSINR:
+ return threshold >= SIGNAL_SSSINR_MIN_VALUE && threshold <= SIGNAL_SSSINR_MAX_VALUE;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Return true if the radio access type is allowed to set with the measurement type.
+ */
+ private static boolean isValidRanWithMeasurementType(
+ @AccessNetworkConstants.RadioAccessNetworkType int ran,
+ @SignalMeasurementType int type) {
+ switch (type) {
+ case SIGNAL_MEASUREMENT_TYPE_RSSI:
+ return ran == AccessNetworkConstants.AccessNetworkType.GERAN
+ || ran == AccessNetworkConstants.AccessNetworkType.CDMA2000;
+ case SIGNAL_MEASUREMENT_TYPE_RSCP:
+ return ran == AccessNetworkConstants.AccessNetworkType.UTRAN;
+ case SIGNAL_MEASUREMENT_TYPE_RSRP:
+ case SIGNAL_MEASUREMENT_TYPE_RSRQ:
+ case SIGNAL_MEASUREMENT_TYPE_RSSNR:
+ return ran == AccessNetworkConstants.AccessNetworkType.EUTRAN;
+ case SIGNAL_MEASUREMENT_TYPE_SSRSRP:
+ case SIGNAL_MEASUREMENT_TYPE_SSRSRQ:
+ case SIGNAL_MEASUREMENT_TYPE_SSSINR:
+ return ran == AccessNetworkConstants.AccessNetworkType.NGRAN;
+ default:
+ return false;
+ }
+ }
+
+ private void validateRanWithMeasurementType(
+ @AccessNetworkConstants.RadioAccessNetworkType int ran,
+ @SignalMeasurementType int signalMeasurement) {
+ if (!isValidRanWithMeasurementType(ran, signalMeasurement)) {
+ throw new IllegalArgumentException(
+ "invalid RAN: " + ran + " with signal measurement type: " + signalMeasurement);
+ }
+ }
+
+ private void validateThresholdRange(@SignalMeasurementType int signalMeasurement,
+ int[] thresholds) {
+ for (int threshold : thresholds) {
+ if (!isValidThreshold(signalMeasurement, threshold)) {
+ throw new IllegalArgumentException(
+ "invalid signal measurement type: " + signalMeasurement
+ + " with threshold: " + threshold);
+ }
+ }
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index bfd37cd..2f577a9 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -131,10 +131,12 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -564,9 +566,10 @@
/**
* Indicates the maximum size of the call composure picture.
*
- * Pictures sent via {@link #uploadCallComposerPicture(InputStream, Executor, OutcomeReceiver)}
- * or {@link #uploadCallComposerPicture(Path, Executor, OutcomeReceiver)} must not exceed this
- * size, or an error will be returned via the callback in those methods.
+ * Pictures sent via
+ * {@link #uploadCallComposerPicture(InputStream, String, Executor, OutcomeReceiver)}
+ * or {@link #uploadCallComposerPicture(Path, String, Executor, OutcomeReceiver)} must not
+ * exceed this size, or an error will be returned via the callback in those methods.
*
* @return Maximum file size in bytes.
*/
@@ -4310,6 +4313,15 @@
*/
public static final int ERROR_IO_EXCEPTION = 5;
+ /**
+ * Indicates that the device is currently not connected to a network that's capable of
+ * reaching a carrier's RCS servers.
+ *
+ * Clients should prompt the user to remedy the issue by moving to an area with better
+ * signal, by connecting to a different network, or to retry at another time.
+ */
+ public static final int ERROR_NETWORK_UNAVAILABLE = 6;
+
/** @hide */
@IntDef(prefix = {"ERROR_"}, value = {
ERROR_UNKNOWN,
@@ -4318,7 +4330,9 @@
ERROR_AUTHENTICATION_FAILED,
ERROR_INPUT_CLOSED,
ERROR_IO_EXCEPTION,
+ ERROR_NETWORK_UNAVAILABLE,
})
+
@Retention(RetentionPolicy.SOURCE)
public @interface CallComposerError {}
@@ -4355,14 +4369,16 @@
/**
* Uploads a picture to the carrier network for use with call composer.
*
- * @see #uploadCallComposerPicture(InputStream, Executor, OutcomeReceiver)
+ * @see #uploadCallComposerPicture(InputStream, String, Executor, OutcomeReceiver)
* @param pictureToUpload Path to a local file containing the picture to upload.
+ * @param contentType The MIME type of the picture you're uploading (e.g. image/jpeg)
* @param executor The {@link Executor} on which the {@code pictureToUpload} file will be read
* from disk, as well as on which {@code callback} will be called.
* @param callback A callback called when the upload operation terminates, either in success
* or in error.
*/
public void uploadCallComposerPicture(@NonNull Path pictureToUpload,
+ @NonNull String contentType,
@CallbackExecutor @NonNull Executor executor,
@NonNull OutcomeReceiver<ParcelUuid, CallComposerException> callback) {
Objects.requireNonNull(pictureToUpload);
@@ -4390,7 +4406,7 @@
}
InputStream fileStream = Files.newInputStream(pictureToUpload);
try {
- uploadCallComposerPicture(fileStream, executor,
+ uploadCallComposerPicture(fileStream, contentType, executor,
new OutcomeReceiver<ParcelUuid, CallComposerException>() {
@Override
public void onResult(ParcelUuid result) {
@@ -4455,12 +4471,14 @@
* of {@link #getMaximumCallComposerPictureSize()}, the upload will be
* aborted and the callback will be called with an exception containing
* {@link CallComposerException#ERROR_FILE_TOO_LARGE}.
+ * @param contentType The MIME type of the picture you're uploading (e.g. image/jpeg)
* @param executor The {@link Executor} on which the {@code pictureToUpload} stream will be
* read, as well as on which the callback will be called.
* @param callback A callback called when the upload operation terminates, either in success
* or in error.
*/
public void uploadCallComposerPicture(@NonNull InputStream pictureToUpload,
+ @NonNull String contentType,
@CallbackExecutor @NonNull Executor executor,
@NonNull OutcomeReceiver<ParcelUuid, CallComposerException> callback) {
Objects.requireNonNull(pictureToUpload);
@@ -4488,7 +4506,7 @@
try {
telephony.uploadCallComposerPicture(getSubId(), mContext.getOpPackageName(),
- readFd, new ResultReceiver(null) {
+ contentType, readFd, new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle result) {
if (resultCode != CallComposerException.SUCCESS) {
@@ -9029,11 +9047,18 @@
*/
public static final int CALL_COMPOSER_STATUS_ON = 1;
+ /**
+ * Call composer status indicating that sending/receiving pictures is disabled.
+ * All other attachments are still enabled in this state.
+ */
+ public static final int CALL_COMPOSER_STATUS_ON_NO_PICTURES = 2;
+
/** @hide */
@IntDef(prefix = {"CALL_COMPOSER_STATUS_"},
value = {
CALL_COMPOSER_STATUS_ON,
CALL_COMPOSER_STATUS_OFF,
+ CALL_COMPOSER_STATUS_ON_NO_PICTURES,
})
public @interface CallComposerStatus {}
@@ -9041,8 +9066,9 @@
* Set the user-set status for enriched calling with call composer.
*
* @param status user-set status for enriched calling with call composer;
- * it must be a value of either {@link #CALL_COMPOSER_STATUS_ON}
- * or {@link #CALL_COMPOSER_STATUS_OFF}.
+ * it must be any of {@link #CALL_COMPOSER_STATUS_ON}
+ * {@link #CALL_COMPOSER_STATUS_OFF},
+ * or {@link #CALL_COMPOSER_STATUS_ON_NO_PICTURES}
*
* <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
* given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
@@ -9052,7 +9078,8 @@
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setCallComposerStatus(@CallComposerStatus int status) {
- if (status != CALL_COMPOSER_STATUS_ON && status != CALL_COMPOSER_STATUS_OFF) {
+ if (status > CALL_COMPOSER_STATUS_ON_NO_PICTURES
+ || status < CALL_COMPOSER_STATUS_OFF) {
throw new IllegalArgumentException("requested status is invalid");
}
try {
@@ -9074,8 +9101,9 @@
*
* @throws SecurityException if the caller does not have the permission.
*
- * @return the user-set status for enriched calling with call composer either
- * {@link #CALL_COMPOSER_STATUS_ON} or {@link #CALL_COMPOSER_STATUS_OFF}.
+ * @return the user-set status for enriched calling with call composer, any of
+ * {@link #CALL_COMPOSER_STATUS_ON}, {@link #CALL_COMPOSER_STATUS_OFF}, or
+ * {@link #CALL_COMPOSER_STATUS_ON_NO_PICTURES}.
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @CallComposerStatus int getCallComposerStatus() {
@@ -15159,4 +15187,17 @@
e.execute(() -> callback.onAuthenticationFailure(GBA_FAILURE_REASON_FEATURE_NOT_READY));
}
}
+
+ /**
+ * The network type is valid or not.
+ *
+ * @param networkType The network type {@link NetworkType}.
+ * @return {@code true} if valid, {@code false} otherwise.
+ *
+ * @hide
+ */
+ public static boolean isNetworkTypeValid(@NetworkType int networkType) {
+ return networkType >= TelephonyManager.NETWORK_TYPE_UNKNOWN &&
+ networkType <= TelephonyManager.NETWORK_TYPE_NR;
+ }
}
diff --git a/telephony/java/android/telephony/euicc/DownloadableSubscription.java b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
index 3412079..a5150b0 100644
--- a/telephony/java/android/telephony/euicc/DownloadableSubscription.java
+++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
@@ -121,25 +121,21 @@
}
public Builder(@NonNull String encodedActivationCode) {
- Preconditions.checkNotNull(encodedActivationCode, "Activation code may not be null");
this.encodedActivationCode = encodedActivationCode;
}
/**
- * Builds a {@link DownloadableSubscription} object. If the encoded activation code is
- * {@code null}, a {@link NullPointerException} will be thrown.
+ * Builds a {@link DownloadableSubscription} object.
* @return a non-null {@link DownloadableSubscription} object.
*/
@NonNull
public DownloadableSubscription build() {
- Preconditions.checkNotNull(encodedActivationCode, "Activation code may not be null");
return new DownloadableSubscription(encodedActivationCode, confirmationCode,
carrierName, accessRules);
}
/**
- * Sets the encoded activation code. If the encoded activation code is {@code null}, a
- * {@link NullPointerException} will be thrown.
+ * Sets the encoded activation code.
* @param value the activation code to use. An activation code can be parsed from a user
* scanned QR code. The format of activation code is defined in SGP.22. For
* example, "1$SMDP.GSMA.COM$04386-AGYFT-A74Y8-3F815$1.3.6.1.4.1.31746". For
@@ -147,7 +143,6 @@
*/
@NonNull
public Builder setEncodedActivationCode(@NonNull String value) {
- Preconditions.checkNotNull(encodedActivationCode, "Activation code may not be null");
encodedActivationCode = value;
return this;
}
diff --git a/telephony/java/android/telephony/ims/DelegateRegistrationState.java b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
index 66281ed..fd206c1 100644
--- a/telephony/java/android/telephony/ims/DelegateRegistrationState.java
+++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
@@ -320,4 +320,11 @@
public int hashCode() {
return Objects.hash(mRegisteredTags, mDeregisteringTags, mDeregisteredTags);
}
+
+ @Override
+ public String toString() {
+ return "DelegateRegistrationState{ registered={" + mRegisteredTags
+ + "}, deregistering={" + mDeregisteringTags + "}, deregistered={"
+ + mDeregisteredTags + "}}";
+ }
}
diff --git a/telephony/java/android/telephony/ims/SipMessage.java b/telephony/java/android/telephony/ims/SipMessage.java
index 1539224..006cca8 100644
--- a/telephony/java/android/telephony/ims/SipMessage.java
+++ b/telephony/java/android/telephony/ims/SipMessage.java
@@ -22,6 +22,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.telephony.SipMessageParsingUtils;
+
import java.util.Arrays;
import java.util.Objects;
@@ -38,9 +40,6 @@
// Should not be set to true for production!
private static final boolean IS_DEBUGGING = Build.IS_ENG;
- private static final String[] SIP_REQUEST_METHODS = new String[] {"INVITE", "ACK", "OPTIONS",
- "BYE", "CANCEL", "REGISTER"};
-
private final String mStartLine;
private final String mHeaderSection;
private final byte[] mContent;
@@ -72,6 +71,7 @@
mContent = new byte[source.readInt()];
source.readByteArray(mContent);
}
+
/**
* @return The start line of the SIP message, which contains either the request-line or
* status-line.
@@ -128,34 +128,25 @@
} else {
b.append(sanitizeStartLineRequest(mStartLine));
}
- b.append("], [");
- b.append("Header: [");
+ b.append("], Header: [");
if (IS_DEBUGGING) {
b.append(mHeaderSection);
} else {
// only identify transaction id/call ID when it is available.
b.append("***");
}
- b.append("], ");
- b.append("Content: [NOT SHOWN]");
+ b.append("], Content: ");
+ b.append(getContent().length == 0 ? "[NONE]" : "[NOT SHOWN]");
return b.toString();
}
/**
- * Start lines containing requests are formatted: METHOD SP Request-URI SP SIP-Version CRLF.
* Detect if this is a REQUEST and redact Request-URI portion here, as it contains PII.
*/
private String sanitizeStartLineRequest(String startLine) {
+ if (!SipMessageParsingUtils.isSipRequest(startLine)) return startLine;
String[] splitLine = startLine.split(" ");
- if (splitLine == null || splitLine.length == 0) {
- return "(INVALID STARTLINE)";
- }
- for (String method : SIP_REQUEST_METHODS) {
- if (splitLine[0].contains(method)) {
- return splitLine[0] + " <Request-URI> " + splitLine[2];
- }
- }
- return startLine;
+ return splitLine[0] + " <Request-URI> " + splitLine[2];
}
@Override
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
index 522ad81..9d91901 100644
--- a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
@@ -28,6 +28,10 @@
import android.telephony.ims.SipDelegateManager;
import android.telephony.ims.SipMessage;
import android.telephony.ims.stub.SipDelegate;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.telephony.SipMessageParsingUtils;
import java.util.ArrayList;
import java.util.Set;
@@ -40,6 +44,7 @@
* @hide
*/
public class SipDelegateAidlWrapper implements DelegateStateCallback, DelegateMessageCallback {
+ private static final String LOG_TAG = "SipDelegateAW";
private final ISipDelegate.Stub mDelegateBinder = new ISipDelegate.Stub() {
@Override
@@ -183,11 +188,15 @@
}
private void notifyLocalMessageFailedToBeReceived(SipMessage m, int reason) {
- //TODO: parse transaction ID or throw IllegalArgumentException if the SipMessage
- // transaction ID can not be parsed.
+ String transactionId = SipMessageParsingUtils.getTransactionId(m.getHeaderSection());
+ if (TextUtils.isEmpty(transactionId)) {
+ Log.w(LOG_TAG, "failure to parse SipMessage.");
+ throw new IllegalArgumentException("Malformed SipMessage, can not determine "
+ + "transaction ID.");
+ }
SipDelegate d = mDelegate;
if (d != null) {
- mExecutor.execute(() -> d.notifyMessageReceiveError(null, reason));
+ mExecutor.execute(() -> d.notifyMessageReceiveError(transactionId, reason));
}
}
}
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
index a35039b..c877aca 100644
--- a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
@@ -28,9 +28,12 @@
import android.telephony.ims.stub.DelegateConnectionMessageCallback;
import android.telephony.ims.stub.DelegateConnectionStateCallback;
import android.telephony.ims.stub.SipDelegate;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
+import com.android.internal.telephony.SipMessageParsingUtils;
+
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.Executor;
@@ -265,9 +268,13 @@
}
private void notifyLocalMessageFailedToSend(SipMessage m, int reason) {
- //TODO: parse transaction ID or throw IllegalArgumentException if the SipMessage
- // transaction ID can not be parsed.
+ String transactionId = SipMessageParsingUtils.getTransactionId(m.getHeaderSection());
+ if (TextUtils.isEmpty(transactionId)) {
+ Log.w(LOG_TAG, "sendMessage detected a malformed SipMessage and can not get a "
+ + "transaction ID.");
+ throw new IllegalArgumentException("Could not send SipMessage due to malformed header");
+ }
mExecutor.execute(() ->
- mMessageCallback.onMessageSendFailure(null, reason));
+ mMessageCallback.onMessageSendFailure(transactionId, reason));
}
}
diff --git a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
index d2cb976..d9734a7 100644
--- a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
+++ b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
@@ -18,15 +18,12 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.net.Uri;
import android.telephony.ims.ImsException;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.RcsFeature;
-import java.util.List;
-
/**
* The interface of the capabilities event listener for ImsService to notify the framework of the
* UCE request and status updated.
@@ -84,25 +81,4 @@
* Telephony stack has crashed.
*/
void onUnpublish() throws ImsException;
-
- /**
- * Inform the framework of a query for this device's UCE capabilities.
- * <p>
- * The framework will respond via the
- * {@link OptionsRequestCallback#onRespondToCapabilityRequest} or
- * {@link OptionsRequestCallback#onRespondToCapabilityRequestWithError}
- * @param contactUri The URI associated with the remote contact that is
- * requesting capabilities.
- * @param remoteCapabilities The remote contact's capability information.
- * @param callback The callback of this request which is sent from the remote user.
- * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not
- * currently connected to the framework. This can happen if the {@link RcsFeature} is not
- * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received
- * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare
- * cases when the Telephony stack has crashed.
- * @hide
- */
- void onRemoteCapabilityRequest(@NonNull Uri contactUri,
- @NonNull List<String> remoteCapabilities,
- @NonNull OptionsRequestCallback callback) throws ImsException;
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 83fb38b..46c9dde 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1262,7 +1262,7 @@
int getRadioAccessFamily(in int phoneId, String callingPackage);
void uploadCallComposerPicture(int subscriptionId, String callingPackage,
- in ParcelFileDescriptor fd, in ResultReceiver callback);
+ String contentType, in ParcelFileDescriptor fd, in ResultReceiver callback);
/**
* Enables or disables video calling.
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 9a2def9..1a940c7 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -1016,6 +1016,15 @@
</intent-filter>
</activity>
+ <activity android:name="RippleActivity"
+ android:label="Animation/Ripple Animation"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="com.android.test.hwui.TEST"/>
+ </intent-filter>
+ </activity>
+
<activity android:name="MultiProducerActivity"
android:label="Threads/Multiple Producers"
android:exported="true">
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
index b53b78a..8be3b7e 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
@@ -35,9 +35,6 @@
import android.os.Bundle;
import android.view.View;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
@SuppressWarnings({"UnusedDeclaration"})
public class ColorFiltersMutateActivity extends Activity {
@Override
@@ -54,11 +51,13 @@
private final Paint mLightingPaint;
private final Paint mBlendPaint;
private final Paint mShaderPaint;
+ private final RuntimeShader mRuntimeShader;
private float mSaturation = 0.0f;
private int mLightAdd = 0;
private int mLightMul = 0;
private int mPorterDuffColor = 0;
+ private float mShaderParam1 = 0.0f;
static final String sSkSL =
"in shader bitmapShader;\n"
@@ -67,8 +66,6 @@
+ " return half4(sample(bitmapShader, xy).rgb, param1);\n"
+ "}\n";
- private byte[] mUniforms = new byte[4];
-
BitmapsView(Context c) {
super(c);
@@ -86,11 +83,13 @@
mBlendPaint = new Paint();
mBlendPaint.setColorFilter(new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_OVER));
+ mRuntimeShader = new RuntimeShader(sSkSL, false);
+ mRuntimeShader.setUniform("param1", mShaderParam1);
+ mRuntimeShader.setInputShader("bitmapShader", new BitmapShader(mBitmap1,
+ Shader.TileMode.CLAMP,
+ Shader.TileMode.CLAMP));
mShaderPaint = new Paint();
- Shader[] inputShaders = { new BitmapShader(mBitmap1, Shader.TileMode.CLAMP,
- Shader.TileMode.CLAMP) };
- mShaderPaint.setShader(new RuntimeShader(sSkSL, mUniforms, inputShaders, true));
- setShaderParam1(0.0f);
+ mShaderPaint.setShader(mRuntimeShader);
ObjectAnimator sat = ObjectAnimator.ofFloat(this, "saturation", 1.0f);
sat.setDuration(1000);
@@ -177,20 +176,15 @@
}
public void setShaderParam1(float value) {
- RuntimeShader shader = (RuntimeShader) mShaderPaint.getShader();
- ByteBuffer buffer = ByteBuffer.wrap(mUniforms);
- buffer.order(ByteOrder.LITTLE_ENDIAN);
- buffer.putFloat(value);
- shader.updateUniforms(mUniforms);
+ mShaderParam1 = value;
+ mRuntimeShader.setUniform("param1", mShaderParam1);
invalidate();
}
// If either valueFrom or valueTo is null, then a getter function will also be derived
// and called by the animator class.
public float getShaderParam1() {
- ByteBuffer buffer = ByteBuffer.wrap(mUniforms);
- buffer.order(ByteOrder.LITTLE_ENDIAN);
- return buffer.getFloat();
+ return mShaderParam1;
}
@Override
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java
new file mode 100644
index 0000000..f6d9a73
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
+import android.graphics.Paint;
+import android.graphics.RecordingCanvas;
+import android.graphics.RuntimeShader;
+import android.os.Bundle;
+import android.os.Trace;
+import android.view.RenderNodeAnimator;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
+
+import java.util.ArrayList;
+
+public class RippleActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final LinearLayout layout = new LinearLayout(this);
+ layout.setOrientation(LinearLayout.VERTICAL);
+ layout.addView(new RippleView(this),
+ new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+
+ setContentView(layout);
+ }
+
+ static class RippleView extends View {
+ static final int DURATION = 1000;
+ static final int MAX_RADIUS = 250;
+
+ private boolean mToggle = false;
+ ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<RenderNodeAnimator>();
+
+ CanvasProperty<Float> mX;
+ CanvasProperty<Float> mY;
+ CanvasProperty<Float> mRadius;
+ CanvasProperty<Float> mProgress;
+ CanvasProperty<Paint> mPaint;
+ RuntimeShader mRuntimeShader;
+
+ static final String sSkSL = ""
+ + "uniform float2 in_origin;"
+ + "uniform float in_progress;\n"
+ + "uniform float in_maxRadius;\n"
+ + "uniform shader in_paintColor;\n"
+ + "float dist2(float2 p0, float2 pf) { return sqrt((pf.x - p0.x) * (pf.x - p0.x) + "
+ + "(pf.y - p0.y) * (pf.y - p0.y)); }\n"
+ + "float mod2(float a, float b) { return a - (b * floor(a / b)); }\n"
+ + "float rand(float2 src) { return fract(sin(dot(src.xy, float2(12.9898, 78.233)))"
+ + " * 43758.5453123); }\n"
+ + "float4 main(float2 p)\n"
+ + "{\n"
+ + " float fraction = in_progress;\n"
+ + " float2 fragCoord = p;//sk_FragCoord.xy;\n"
+ + " float maxDist = in_maxRadius;\n"
+ + " float fragDist = dist2(in_origin, fragCoord.xy);\n"
+ + " float circleRadius = maxDist * fraction;\n"
+ + " float colorVal = (fragDist - circleRadius) / maxDist;\n"
+ + " float d = fragDist < circleRadius \n"
+ + " ? 1. - abs(colorVal * 2. * smoothstep(0., 1., fraction)) \n"
+ + " : 1. - abs(colorVal * 3.);\n"
+ + " d = smoothstep(0., 1., d);\n"
+ + " float divider = 2.;\n"
+ + " float x = floor(fragCoord.x / divider);\n"
+ + " float y = floor(fragCoord.y / divider);\n"
+ + " float density = .95;\n"
+ + " d = rand(float2(x, y)) > density ? d : d * .2;\n"
+ + " d = d * rand(float2(fraction, x * y));\n"
+ + " float alpha = 1. - pow(fraction, 3.);\n"
+ + " return float4(sample(in_paintColor).rgb, d * alpha);\n"
+ + "}";
+
+ RippleView(Context c) {
+ super(c);
+ setClickable(true);
+
+ mX = CanvasProperty.createFloat(200.0f);
+ mY = CanvasProperty.createFloat(200.0f);
+ mRadius = CanvasProperty.createFloat(150.0f);
+ mProgress = CanvasProperty.createFloat(0.0f);
+
+ Paint p = new Paint();
+ p.setAntiAlias(true);
+ p.setColor(0xFFFF0000);
+ mPaint = CanvasProperty.createPaint(p);
+
+ mRuntimeShader = new RuntimeShader(sSkSL, false);
+ mRuntimeShader.setUniform("in_maxRadius", MAX_RADIUS);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (canvas.isHardwareAccelerated()) {
+ RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;
+ recordingCanvas.drawRipple(mX, mY, mRadius, mPaint, mProgress, mRuntimeShader);
+ }
+ }
+
+ @Override
+ public boolean performClick() {
+ for (int i = 0; i < mRunningAnimations.size(); i++) {
+ mRunningAnimations.get(i).cancel();
+ }
+ mRunningAnimations.clear();
+
+ mToggle = !mToggle;
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mX, mToggle ? 400.0f : 200.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mY, mToggle ? 600.0f : 200.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mRadius, mToggle ? MAX_RADIUS : 150.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mProgress, mToggle ? 1.0f : 0.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mPaint, RenderNodeAnimator.PAINT_ALPHA, 64.0f));
+
+ // Will be "chained" to run after the above
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mPaint, RenderNodeAnimator.PAINT_ALPHA, 255.0f));
+
+ for (int i = 0; i < mRunningAnimations.size(); i++) {
+ RenderNodeAnimator anim = mRunningAnimations.get(i);
+ anim.setDuration(DURATION);
+ anim.setTarget(this);
+ if (i == (mRunningAnimations.size() - 1)) {
+ // "chain" test
+ anim.setStartValue(64.0f);
+ anim.setStartDelay(anim.getDuration());
+ }
+ anim.start();
+ }
+
+ if (mToggle) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "pretendBusy");
+ try {
+ Thread.sleep(DURATION);
+ } catch (InterruptedException e) {
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ });
+ }
+ return true;
+ }
+ }
+}
diff --git a/tests/StagedInstallTest/OWNERS b/tests/StagedInstallTest/OWNERS
index d825dfd..aac68e9 100644
--- a/tests/StagedInstallTest/OWNERS
+++ b/tests/StagedInstallTest/OWNERS
@@ -1 +1,5 @@
include /services/core/java/com/android/server/pm/OWNERS
+
+dariofreni@google.com
+ioffe@google.com
+olilan@google.com
diff --git a/tests/net/common/java/android/net/CaptivePortalDataTest.kt b/tests/net/common/java/android/net/CaptivePortalDataTest.kt
index 8710d23..2cb16d3372 100644
--- a/tests/net/common/java/android/net/CaptivePortalDataTest.kt
+++ b/tests/net/common/java/android/net/CaptivePortalDataTest.kt
@@ -18,12 +18,15 @@
import android.os.Build
import androidx.test.filters.SmallTest
+import com.android.modules.utils.build.SdkLevel
import com.android.testutils.assertParcelSane
import com.android.testutils.assertParcelingIsLossless
+import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertEquals
@@ -33,6 +36,9 @@
@RunWith(DevSdkIgnoreRunner::class)
@IgnoreUpTo(Build.VERSION_CODES.Q)
class CaptivePortalDataTest {
+ @Rule @JvmField
+ val ignoreRule = DevSdkIgnoreRule()
+
private val data = CaptivePortalData.Builder()
.setRefreshTime(123L)
.setUserPortalUrl(Uri.parse("https://portal.example.com/test"))
@@ -41,7 +47,11 @@
.setBytesRemaining(456L)
.setExpiryTime(789L)
.setCaptive(true)
- .setVenueFriendlyName("venue friendly name")
+ .apply {
+ if (SdkLevel.isAtLeastS()) {
+ setVenueFriendlyName("venue friendly name")
+ }
+ }
.build()
private fun makeBuilder() = CaptivePortalData.Builder(data)
@@ -67,8 +77,11 @@
assertNotEqualsAfterChange { it.setBytesRemaining(789L) }
assertNotEqualsAfterChange { it.setExpiryTime(12L) }
assertNotEqualsAfterChange { it.setCaptive(false) }
- assertNotEqualsAfterChange { it.setVenueFriendlyName("another friendly name") }
- assertNotEqualsAfterChange { it.setVenueFriendlyName(null) }
+
+ if (SdkLevel.isAtLeastS()) {
+ assertNotEqualsAfterChange { it.setVenueFriendlyName("another friendly name") }
+ assertNotEqualsAfterChange { it.setVenueFriendlyName(null) }
+ }
}
@Test
@@ -111,7 +124,7 @@
assertFalse(makeBuilder().setCaptive(false).build().isCaptive)
}
- @Test
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
fun testVenueFriendlyName() {
assertEquals("venue friendly name", data.venueFriendlyName)
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 6953100..f3a3c01 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -290,13 +290,16 @@
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@@ -411,9 +414,6 @@
private class MockContext extends BroadcastInterceptingContext {
private final MockContentResolver mContentResolver;
- // Contains all registered receivers since this object was created. Useful to clear
- // them when needed, as BroadcastInterceptingContext does not provide this facility.
- private final List<BroadcastReceiver> mRegisteredReceivers = new ArrayList<>();
@Spy private Resources mResources;
private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
@@ -550,19 +550,6 @@
public void setPermission(String permission, Integer granted) {
mMockedPermissions.put(permission, granted);
}
-
- @Override
- public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
- mRegisteredReceivers.add(receiver);
- return super.registerReceiver(receiver, filter);
- }
-
- public void clearRegisteredReceivers() {
- // super.unregisterReceiver is a no-op for receivers that are not registered (because
- // they haven't been registered or because they have already been unregistered).
- // For the same reason, don't bother clearing mRegisteredReceivers.
- for (final BroadcastReceiver rcv : mRegisteredReceivers) unregisterReceiver(rcv);
- }
}
private void waitForIdle() {
@@ -591,10 +578,10 @@
}
// Bring up a network that we can use to send messages to ConnectivityService.
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
Network n = mWiFiNetworkAgent.getNetwork();
assertNotNull(n);
@@ -611,10 +598,10 @@
@Ignore
public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
// Bring up a network that we can use to send messages to ConnectivityService.
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
Network n = mWiFiNetworkAgent.getNetwork();
assertNotNull(n);
@@ -1514,29 +1501,79 @@
}
/**
- * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
- * broadcasts are received.
+ * Class to simplify expecting broadcasts using BroadcastInterceptingContext.
+ * Ensures that the receiver is unregistered after the expected broadcast is received. This
+ * cannot be done in the BroadcastReceiver itself because BroadcastInterceptingContext runs
+ * the receivers' receive method while iterating over the list of receivers, and unregistering
+ * the receiver during iteration throws ConcurrentModificationException.
*/
- private ConditionVariable registerConnectivityBroadcast(final int count) {
+ private class ExpectedBroadcast extends CompletableFuture<Intent> {
+ private final BroadcastReceiver mReceiver;
+
+ ExpectedBroadcast(BroadcastReceiver receiver) {
+ mReceiver = receiver;
+ }
+
+ public Intent expectBroadcast(int timeoutMs) throws Exception {
+ try {
+ return get(timeoutMs, TimeUnit.MILLISECONDS);
+ } catch (TimeoutException e) {
+ fail("Expected broadcast not received after " + timeoutMs + " ms");
+ return null;
+ } finally {
+ mServiceContext.unregisterReceiver(mReceiver);
+ }
+ }
+
+ public Intent expectBroadcast() throws Exception {
+ return expectBroadcast(TIMEOUT_MS);
+ }
+
+ public void expectNoBroadcast(int timeoutMs) throws Exception {
+ waitForIdle();
+ try {
+ final Intent intent = get(timeoutMs, TimeUnit.MILLISECONDS);
+ fail("Unexpected broadcast: " + intent.getAction());
+ } catch (TimeoutException expected) {
+ } finally {
+ mServiceContext.unregisterReceiver(mReceiver);
+ }
+ }
+ }
+
+ /** Expects that {@code count} CONNECTIVITY_ACTION broadcasts are received. */
+ private ExpectedBroadcast registerConnectivityBroadcast(final int count) {
return registerConnectivityBroadcastThat(count, intent -> true);
}
- private ConditionVariable registerConnectivityBroadcastThat(final int count,
+ private ExpectedBroadcast registerConnectivityBroadcastThat(final int count,
@NonNull final Predicate<Intent> filter) {
- final ConditionVariable cv = new ConditionVariable();
final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
+ // AtomicReference allows receiver to access expected even though it is constructed later.
+ final AtomicReference<ExpectedBroadcast> expectedRef = new AtomicReference<>();
final BroadcastReceiver receiver = new BroadcastReceiver() {
- private int remaining = count;
- public void onReceive(Context context, Intent intent) {
- if (!filter.test(intent)) return;
- if (--remaining == 0) {
- cv.open();
- mServiceContext.unregisterReceiver(this);
- }
- }
- };
+ private int mRemaining = count;
+ public void onReceive(Context context, Intent intent) {
+ final int type = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
+ final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
+ Log.d(TAG, "Received CONNECTIVITY_ACTION type=" + type + " ni=" + ni);
+ if (!filter.test(intent)) return;
+ if (--mRemaining == 0) {
+ expectedRef.get().complete(intent);
+ }
+ }
+ };
+ final ExpectedBroadcast expected = new ExpectedBroadcast(receiver);
+ expectedRef.set(expected);
mServiceContext.registerReceiver(receiver, intentFilter);
- return cv;
+ return expected;
+ }
+
+ private ExpectedBroadcast expectConnectivityAction(int type, NetworkInfo.DetailedState state) {
+ return registerConnectivityBroadcastThat(1, intent ->
+ type == intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) && state.equals(
+ ((NetworkInfo) intent.getParcelableExtra(EXTRA_NETWORK_INFO))
+ .getDetailedState()));
}
@Test
@@ -1560,10 +1597,9 @@
// Connect the cell agent and wait for the connected broadcast.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL);
- final ConditionVariable cv1 = registerConnectivityBroadcastThat(1,
- intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
mCellNetworkAgent.connect(true);
- waitFor(cv1);
+ b.expectBroadcast();
// Build legacy request for SUPL.
final NetworkCapabilities legacyCaps = new NetworkCapabilities();
@@ -1573,27 +1609,17 @@
ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
// File request, withdraw it and make sure no broadcast is sent
- final ConditionVariable cv2 = registerConnectivityBroadcast(1);
+ b = registerConnectivityBroadcast(1);
final TestNetworkCallback callback = new TestNetworkCallback();
mCm.requestNetwork(legacyRequest, callback);
callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
mCm.unregisterNetworkCallback(callback);
- assertFalse(cv2.block(800)); // 800ms long enough to at least flake if this is sent
- // As the broadcast did not fire, the receiver was not unregistered. Do this now.
- mServiceContext.clearRegisteredReceivers();
+ b.expectNoBroadcast(800); // 800ms long enough to at least flake if this is sent
- // Disconnect the network and expect mobile disconnected broadcast. Use a small hack to
- // check that has been sent.
- final AtomicBoolean vanillaAction = new AtomicBoolean(false);
- final ConditionVariable cv3 = registerConnectivityBroadcastThat(1, intent -> {
- if (intent.getAction().equals(CONNECTIVITY_ACTION)) {
- vanillaAction.set(true);
- }
- return !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected();
- });
+ // Disconnect the network and expect mobile disconnected broadcast.
+ b = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
mCellNetworkAgent.disconnect();
- waitFor(cv3);
- assertTrue(vanillaAction.get());
+ b.expectBroadcast();
}
@Test
@@ -1604,9 +1630,9 @@
assertNull(mCm.getActiveNetworkInfo());
assertNull(mCm.getActiveNetwork());
// Test bringing up validated cellular.
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
mCellNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
assertLength(2, mCm.getAllNetworks());
assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
@@ -1614,9 +1640,9 @@
assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
// Test bringing up validated WiFi.
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
assertLength(2, mCm.getAllNetworks());
assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
@@ -1631,9 +1657,9 @@
assertLength(1, mCm.getAllNetworks());
assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
// Test WiFi disconnect.
- cv = registerConnectivityBroadcast(1);
+ b = registerConnectivityBroadcast(1);
mWiFiNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
verifyNoNetwork();
}
@@ -1641,9 +1667,9 @@
public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
// Test bringing up unvalidated WiFi
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
mWiFiNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up unvalidated cellular
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
@@ -1656,19 +1682,19 @@
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up validated cellular
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mCellNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test cellular disconnect.
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mCellNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test WiFi disconnect.
- cv = registerConnectivityBroadcast(1);
+ b = registerConnectivityBroadcast(1);
mWiFiNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
verifyNoNetwork();
}
@@ -1676,25 +1702,25 @@
public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
// Test bringing up unvalidated cellular.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
mCellNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test bringing up unvalidated WiFi.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test WiFi disconnect.
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test cellular disconnect.
- cv = registerConnectivityBroadcast(1);
+ b = registerConnectivityBroadcast(1);
mCellNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
verifyNoNetwork();
}
@@ -1702,24 +1728,24 @@
public void testUnlingeringDoesNotValidate() throws Exception {
// Test bringing up unvalidated WiFi.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
mWiFiNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
// Test bringing up validated cellular.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mCellNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
// Test cellular disconnect.
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mCellNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Unlingering a network should not cause it to be marked as validated.
assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
@@ -1730,25 +1756,25 @@
public void testCellularOutscoresWeakWifi() throws Exception {
// Test bringing up validated cellular.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
mCellNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test bringing up validated WiFi.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test WiFi getting really weak.
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.adjustScore(-11);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test WiFi restoring signal strength.
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.adjustScore(11);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
}
@@ -1766,9 +1792,9 @@
mCellNetworkAgent.expectDisconnected();
// Test bringing up validated WiFi.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- final ConditionVariable cv = registerConnectivityBroadcast(1);
+ final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
mWiFiNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up unvalidated cellular.
// Expect it to be torn down because it could never be the highest scoring network
@@ -1785,33 +1811,33 @@
public void testCellularFallback() throws Exception {
// Test bringing up validated cellular.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
mCellNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test bringing up validated WiFi.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Reevaluate WiFi (it'll instantly fail DNS).
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
// Should quickly fall back to Cellular.
- waitFor(cv);
+ b.expectBroadcast();
assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Reevaluate cellular (it'll instantly fail DNS).
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
// Should quickly fall back to WiFi.
- waitFor(cv);
+ b.expectBroadcast();
assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
@@ -1823,23 +1849,23 @@
public void testWiFiFallback() throws Exception {
// Test bringing up unvalidated WiFi.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
mWiFiNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up validated cellular.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mCellNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Reevaluate cellular (it'll instantly fail DNS).
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
// Should quickly fall back to WiFi.
- waitFor(cv);
+ b.expectBroadcast();
assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
verifyActiveNetwork(TRANSPORT_WIFI);
@@ -1909,13 +1935,13 @@
mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
// Test unvalidated networks
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(false);
genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
- waitFor(cv);
+ b.expectBroadcast();
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
// This should not trigger spurious onAvailable() callbacks, b/21762680.
@@ -1924,28 +1950,28 @@
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
- waitFor(cv);
+ b.expectBroadcast();
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.disconnect();
genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
cellNetworkCallback.assertNoCallback();
- waitFor(cv);
+ b.expectBroadcast();
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
- cv = registerConnectivityBroadcast(1);
+ b = registerConnectivityBroadcast(1);
mCellNetworkAgent.disconnect();
genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
- waitFor(cv);
+ b.expectBroadcast();
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
// Test validated networks
@@ -2666,9 +2692,9 @@
// Test bringing up validated WiFi.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- final ConditionVariable cv = registerConnectivityBroadcast(1);
+ final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
mWiFiNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Register MMS NetworkRequest
@@ -2694,9 +2720,9 @@
public void testMMSonCell() throws Exception {
// Test bringing up cellular without MMS
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
mCellNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Register MMS NetworkRequest
@@ -4304,9 +4330,9 @@
}
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
mWiFiNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
mWiFiNetworkAgent.sendLinkProperties(lp);
waitForIdle();
@@ -4862,10 +4888,10 @@
assertNotPinnedToWifi();
// Disconnect cell and wifi.
- ConditionVariable cv = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down.
+ ExpectedBroadcast b = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down.
mCellNetworkAgent.disconnect();
mWiFiNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
// Pinning takes effect even if the pinned network is the default when the pin is set...
TestNetworkPinner.pin(mServiceContext, wifiRequest);
@@ -4875,10 +4901,10 @@
assertPinnedToWifiWithWifiDefault();
// ... and is maintained even when that network is no longer the default.
- cv = registerConnectivityBroadcast(1);
+ b = registerConnectivityBroadcast(1);
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mCellNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
assertPinnedToWifiWithCellDefault();
}
@@ -4978,7 +5004,7 @@
@Test
public void testNetworkInfoOfTypeNone() throws Exception {
- ConditionVariable broadcastCV = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
verifyNoNetwork();
TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
@@ -5011,9 +5037,7 @@
mCm.unregisterNetworkCallback(callback);
verifyNoNetwork();
- if (broadcastCV.block(10)) {
- fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
- }
+ b.expectNoBroadcast(10);
}
@Test
@@ -7250,11 +7274,11 @@
// prefix discovery is never started.
LinkProperties lp = new LinkProperties(baseLp);
lp.setNat64Prefix(pref64FromRa);
- mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
- mCellNetworkAgent.connect(false);
- final Network network = mCellNetworkAgent.getNetwork();
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
+ mWiFiNetworkAgent.connect(false);
+ final Network network = mWiFiNetworkAgent.getNetwork();
int netId = network.getNetId();
- callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
@@ -7263,8 +7287,8 @@
// If the RA prefix is withdrawn, clatd is stopped and prefix discovery is started.
lp.setNat64Prefix(null);
- mCellNetworkAgent.sendLinkProperties(lp);
- expectNat64PrefixChange(callback, mCellNetworkAgent, null);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
@@ -7272,8 +7296,8 @@
// If the RA prefix appears while DNS discovery is in progress, discovery is stopped and
// clatd is started with the prefix from the RA.
lp.setNat64Prefix(pref64FromRa);
- mCellNetworkAgent.sendLinkProperties(lp);
- expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromRa);
inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
@@ -7281,21 +7305,21 @@
// Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS
// discovery has succeeded.
lp.setNat64Prefix(null);
- mCellNetworkAgent.sendLinkProperties(lp);
- expectNat64PrefixChange(callback, mCellNetworkAgent, null);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */,
pref64FromDnsStr, 96);
- expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns);
inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString());
// If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix
// discovery is not stopped, and there are no callbacks.
lp.setNat64Prefix(pref64FromDns);
- mCellNetworkAgent.sendLinkProperties(lp);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
callback.assertNoCallback();
inOrder.verify(mMockNetd, never()).clatdStop(iface);
inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
@@ -7305,7 +7329,7 @@
// If the RA is later withdrawn, nothing happens again.
lp.setNat64Prefix(null);
- mCellNetworkAgent.sendLinkProperties(lp);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
callback.assertNoCallback();
inOrder.verify(mMockNetd, never()).clatdStop(iface);
inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
@@ -7315,8 +7339,8 @@
// If the RA prefix changes, clatd is restarted and prefix discovery is stopped.
lp.setNat64Prefix(pref64FromRa);
- mCellNetworkAgent.sendLinkProperties(lp);
- expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromRa);
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
@@ -7330,8 +7354,8 @@
// If the RA prefix changes, clatd is restarted and prefix discovery is not started.
lp.setNat64Prefix(newPref64FromRa);
- mCellNetworkAgent.sendLinkProperties(lp);
- expectNat64PrefixChange(callback, mCellNetworkAgent, newPref64FromRa);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, newPref64FromRa);
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
inOrder.verify(mMockNetd).clatdStart(iface, newPref64FromRa.toString());
@@ -7341,7 +7365,7 @@
// If the RA prefix changes to the same value, nothing happens.
lp.setNat64Prefix(newPref64FromRa);
- mCellNetworkAgent.sendLinkProperties(lp);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
callback.assertNoCallback();
assertEquals(newPref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
inOrder.verify(mMockNetd, never()).clatdStop(iface);
@@ -7355,19 +7379,19 @@
// If the same prefix is learned first by DNS and then by RA, and clat is later stopped,
// (e.g., because the network disconnects) setPrefix64(netid, "") is never called.
lp.setNat64Prefix(null);
- mCellNetworkAgent.sendLinkProperties(lp);
- expectNat64PrefixChange(callback, mCellNetworkAgent, null);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */,
pref64FromDnsStr, 96);
- expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns);
inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString());
inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any());
lp.setNat64Prefix(pref64FromDns);
- mCellNetworkAgent.sendLinkProperties(lp);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
callback.assertNoCallback();
inOrder.verify(mMockNetd, never()).clatdStop(iface);
inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
@@ -7378,10 +7402,10 @@
// When tearing down a network, clat state is only updated after CALLBACK_LOST is fired, but
// before CONNECTIVITY_ACTION is sent. Wait for CONNECTIVITY_ACTION before verifying that
// clat has been stopped, or the test will be flaky.
- ConditionVariable cv = registerConnectivityBroadcast(1);
- mCellNetworkAgent.disconnect();
- callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
- waitFor(cv);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
+ mWiFiNetworkAgent.disconnect();
+ callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+ b.expectBroadcast();
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
@@ -7456,10 +7480,10 @@
.destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
// Disconnect wifi
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
reset(mNetworkManagementService);
mWiFiNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
// Clean up
@@ -8405,6 +8429,7 @@
mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
+ waitForIdle();
final ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
@@ -8466,4 +8491,20 @@
assertVpnUidRangesUpdated(true, newRanges, VPN_UID);
assertVpnUidRangesUpdated(false, vpnRanges, VPN_UID);
}
+
+ @Test
+ public void testInvalidRequestTypes() {
+ final int[] invalidReqTypeInts = new int[] {-1, NetworkRequest.Type.NONE.ordinal(),
+ NetworkRequest.Type.LISTEN.ordinal(), NetworkRequest.Type.values().length};
+ final NetworkCapabilities nc = new NetworkCapabilities().addTransportType(TRANSPORT_WIFI);
+
+ for (int reqTypeInt : invalidReqTypeInts) {
+ assertThrows("Expect throws for invalid request type " + reqTypeInt,
+ IllegalArgumentException.class,
+ () -> mService.requestNetwork(nc, reqTypeInt, null, 0, null,
+ ConnectivityManager.TYPE_NONE, mContext.getPackageName(),
+ getAttributionTag())
+ );
+ }
+ }
}
diff --git a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
new file mode 100644
index 0000000..3156190
--- /dev/null
+++ b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.vcn;
+
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+
+import android.net.wifi.WifiInfo;
+import android.os.Parcel;
+
+import org.junit.Test;
+
+public class VcnTransportInfoTest {
+ private static final int SUB_ID = 1;
+ private static final int NETWORK_ID = 5;
+ private static final WifiInfo WIFI_INFO =
+ new WifiInfo.Builder().setNetworkId(NETWORK_ID).build();
+
+ private static final VcnTransportInfo CELL_UNDERLYING_INFO = new VcnTransportInfo(SUB_ID);
+ private static final VcnTransportInfo WIFI_UNDERLYING_INFO = new VcnTransportInfo(WIFI_INFO);
+
+ @Test
+ public void testGetWifiInfo() {
+ assertEquals(WIFI_INFO, WIFI_UNDERLYING_INFO.getWifiInfo());
+
+ assertNull(CELL_UNDERLYING_INFO.getWifiInfo());
+ }
+
+ @Test
+ public void testGetSubId() {
+ assertEquals(SUB_ID, CELL_UNDERLYING_INFO.getSubId());
+
+ assertEquals(INVALID_SUBSCRIPTION_ID, WIFI_UNDERLYING_INFO.getSubId());
+ }
+
+ @Test
+ public void testEquals() {
+ assertEquals(CELL_UNDERLYING_INFO, CELL_UNDERLYING_INFO);
+ assertEquals(WIFI_UNDERLYING_INFO, WIFI_UNDERLYING_INFO);
+ assertNotEquals(CELL_UNDERLYING_INFO, WIFI_UNDERLYING_INFO);
+ }
+
+ @Test
+ public void testParcelUnparcel() {
+ verifyParcelingIsNull(CELL_UNDERLYING_INFO);
+ verifyParcelingIsNull(WIFI_UNDERLYING_INFO);
+ }
+
+ private void verifyParcelingIsNull(VcnTransportInfo vcnTransportInfo) {
+ Parcel parcel = Parcel.obtain();
+ vcnTransportInfo.writeToParcel(parcel, 0 /* flags */);
+ assertNull(VcnTransportInfo.CREATOR.createFromParcel(parcel));
+ }
+}