diff options
519 files changed, 10740 insertions, 2192 deletions
diff --git a/apex/appsearch/framework/api/current.txt b/apex/appsearch/framework/api/current.txt index 9fa4b8e5a4e7..f9ff9dd5fd5b 100644 --- a/apex/appsearch/framework/api/current.txt +++ b/apex/appsearch/framework/api/current.txt @@ -80,7 +80,8 @@ package android.app.appsearch { 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 73a4a196b90a..56b7ffd35385 100644 --- a/apex/appsearch/framework/api/system-current.txt +++ b/apex/appsearch/framework/api/system-current.txt @@ -9,7 +9,8 @@ package android.app.appsearch { 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 d4872e815134..042757797dce 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 android.util.Log; 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 @@ import java.util.function.Consumer; * * 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 @@ public final class AppSearchSession { } /** - * 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 95f7d796d007..9e3461675031 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.SystemApi; 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 @@ import java.util.function.Consumer; * @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 @@ public class GlobalSearchSession { 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 a9ca7308b25f..26b5abed745c 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 @@ public final class JobServiceContext implements ServiceConnection { 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 ce3bcbede4c7..103bb47fca23 100644 --- a/apex/media/framework/api/current.txt +++ b/apex/media/framework/api/current.txt @@ -6,9 +6,11 @@ package android.media { 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 @@ package android.media { 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 36f6b94b16ad..25ccec2930f1 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.net.Uri; 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 @@ import java.util.Set; 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 @@ public final class ApplicationMediaCapabilities implements Parcelable { 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 final class ApplicationMediaCapabilities implements Parcelable { 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 @@ public final class ApplicationMediaCapabilities implements Parcelable { }; /* - * 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 @@ public final class ApplicationMediaCapabilities implements Parcelable { } /* - * 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 @@ public final class ApplicationMediaCapabilities implements Parcelable { } /* + * 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 @@ public final class ApplicationMediaCapabilities implements Parcelable { /** 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 @@ public final class ApplicationMediaCapabilities implements Parcelable { 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 @@ public final class ApplicationMediaCapabilities implements Parcelable { @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 @@ public final class ApplicationMediaCapabilities implements Parcelable { * * @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 @@ public final class ApplicationMediaCapabilities implements Parcelable { 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 @@ public final class ApplicationMediaCapabilities implements Parcelable { 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 3d706e40bc0b..5d212b8e4745 100644 --- a/apex/media/framework/java/android/media/MediaTranscodeManager.java +++ b/apex/media/framework/java/android/media/MediaTranscodeManager.java @@ -980,8 +980,15 @@ public final class MediaTranscodeManager { 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 index 753bc69be95b..753bc69be95b 100644 --- a/config/hiddenapi-temp-blocklist.txt +++ b/config/hiddenapi-max-target-r-loprio.txt diff --git a/core/api/current.txt b/core/api/current.txt index ba3f6364f646..1eeb9275b0b2 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -393,6 +393,7 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android { 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 @@ package android.app { 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 @@ package android.content { 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 @@ package android.graphics { 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 @@ package android.media.tv { } 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 @@ package android.media.tv { 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 @@ package android.media.tv { 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 @@ package android.media.tv { 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 @@ package android.os { 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 @@ package android.provider { 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 @@ package android.telephony { 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 @@ package android.telephony { 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 @@ package android.telephony { 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 @@ package android.telephony { 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 @@ package android.telephony { 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 @@ package android.telephony { 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 @@ package android.telephony { 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 @@ package android.telephony { 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 @@ package android.telephony { 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 @@ package android.telephony { 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 21a6ba1a78aa..eab4d649eecd 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -893,6 +893,8 @@ package android.app.admin { 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 @@ package android.content { 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 @@ package android.location { 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 @@ package android.location { 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 @@ package android.location { 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 @@ package android.location { 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 @@ package android.media.tv.tuner { 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 @@ package android.os { } 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 62c660cbcb6c..775ded777f43 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -385,18 +385,35 @@ package android.app.admin { 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 @@ package android.app.admin { 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.prediction { 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.graphics.drawable { } +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 @@ package android.location { 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 @@ package android.location { 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 3bd88a47f30d..216d34069083 100644 --- a/core/api/test-lint-baseline.txt +++ b/core/api/test-lint-baseline.txt @@ -468,6 +468,8 @@ GetterSetterNames: android.location.GnssMeasurement#setBasebandCn0DbHz(double): 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 b1890b075c59..f7f42a6e2713 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -98,11 +98,15 @@ public abstract class ActivityManagerInternal { 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 class ActivityManagerInternal { 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 f541e1a7dab0..d0d5df91a2a3 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -54,6 +54,7 @@ import android.view.RemoteAnimationAdapter; 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 @@ public class ActivityOptions { 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 @@ public class ActivityOptions { 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 @@ public class ActivityOptions { 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 @@ public class ActivityOptions { } 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 @@ public class ActivityOptions { } /** @hide */ + public IRemoteTransition getRemoteTransition() { + return mRemoteTransition; + } + + /** @hide */ public static ActivityOptions fromBundle(Bundle bOptions) { return bOptions != null ? new ActivityOptions(bOptions) : null; } @@ -1724,6 +1750,9 @@ public class ActivityOptions { 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 dd016a2cf78e..fe13fd48109a 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -31,7 +31,6 @@ import android.app.contentsuggestions.IContentSuggestionsManager; 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 @@ public final class SystemServiceRegistry { 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 ab0901da632f..a866082896a9 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -605,6 +605,7 @@ public class WallpaperManager { * 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 71af5e33cc6a..54e1ac43f208 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2536,6 +2536,22 @@ public class DevicePolicyManager { "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 class DevicePolicyManager { 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 @@ public class DevicePolicyManager { /** @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 @@ public class DevicePolicyManager { 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 @@ public class DevicePolicyManager { * 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 8dde2c55d7d3..ba1f61290631 100644 --- a/core/java/android/app/role/RoleControllerManager.java +++ b/core/java/android/app/role/RoleControllerManager.java @@ -20,8 +20,6 @@ import android.Manifest; 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 @@ import java.util.function.Consumer; * * @hide */ -@SystemService(Context.ROLE_CONTROLLER_SERVICE) -@TestApi public class RoleControllerManager { private static final String LOG_TAG = RoleControllerManager.class.getSimpleName(); @@ -199,32 +195,11 @@ public class RoleControllerManager { } /** - * @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 @@ public class RoleControllerManager { * @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 8b2e07b09701..0fcf44d2dda6 100644 --- a/core/java/android/app/role/RoleManager.java +++ b/core/java/android/app/role/RoleManager.java @@ -174,6 +174,9 @@ public final class RoleManager { @NonNull private final Object mListenersLock = new Object(); + @NonNull + private final RoleControllerManager mRoleControllerManager; + /** * @hide */ @@ -181,6 +184,7 @@ public final class RoleManager { mContext = context; mService = IRoleManager.Stub.asInterface(ServiceManager.getServiceOrThrow( Context.ROLE_SERVICE)); + mRoleControllerManager = new RoleControllerManager(context); } /** @@ -676,6 +680,44 @@ public final class RoleManager { } } + /** + * 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 000000000000..92835c2b0626 --- /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 5ccceca9a69d..eb70ae11f38b 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4833,16 +4833,6 @@ public abstract class Context { 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 @@ public abstract class Context { * 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 fd32efccbcec..f0def80505ce 100644 --- a/core/java/android/content/pm/OWNERS +++ b/core/java/android/content/pm/OWNERS @@ -6,5 +6,6 @@ patb@google.com 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 17c4d25d82d7..03d4d5e10e64 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3513,6 +3513,17 @@ public abstract class PackageManager { 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 ae801b639d51..41d1e2523a9b 100644 --- a/core/java/android/hardware/CameraStreamStats.java +++ b/core/java/android/hardware/CameraStreamStats.java @@ -19,7 +19,6 @@ import android.os.Parcel; 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 @@ import java.util.ArrayList; * @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 @@ public class CameraStreamStats implements Parcelable { 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 @@ public class CameraStreamStats implements Parcelable { mStartLatencyMs = 0; mMaxHalBuffers = 0; mMaxAppBuffers = 0; + mHistogramType = HISTOGRAM_TYPE_UNKNOWN; } public CameraStreamStats(int width, int height, int format, @@ -70,6 +75,7 @@ public class CameraStreamStats implements Parcelable { mStartLatencyMs = startLatencyMs; mMaxHalBuffers = maxHalBuffers; mMaxAppBuffers = maxAppBuffers; + mHistogramType = HISTOGRAM_TYPE_UNKNOWN; } public static final @android.annotation.NonNull Parcelable.Creator<CameraStreamStats> CREATOR = @@ -112,6 +118,9 @@ public class CameraStreamStats implements Parcelable { 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 @@ public class CameraStreamStats implements Parcelable { 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 class CameraStreamStats implements Parcelable { 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 f7c4c2c5ca15..ec6c23384859 100644 --- a/core/java/android/hardware/Sensor.java +++ b/core/java/android/hardware/Sensor.java @@ -881,7 +881,11 @@ public final class Sensor { } } - 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 8497525f85b3..e165ad694fcc 100644 --- a/core/java/android/hardware/SensorPrivacyManager.java +++ b/core/java/android/hardware/SensorPrivacyManager.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; 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 @@ import java.lang.annotation.RetentionPolicy; * * @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 @@ public final class SensorPrivacyManager { * 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 @@ public final class SensorPrivacyManager { /** * Returns the single instance of the SensorPrivacyManager. + * + * @hide */ public static SensorPrivacyManager getInstance(Context context) { synchronized (sInstanceLock) { @@ -121,6 +131,8 @@ public final class SensorPrivacyManager { * 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 @@ public final class SensorPrivacyManager { * * @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 @@ public final class SensorPrivacyManager { * @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 @@ public final class SensorPrivacyManager { * * @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 @@ public final class SensorPrivacyManager { * 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 @@ public final class SensorPrivacyManager { * 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 @@ public final class SensorPrivacyManager { * * @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 @@ public final class SensorPrivacyManager { * * @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 56c2cddcbf15..89db857b860b 100644 --- a/core/java/android/hardware/input/InputDeviceSensorManager.java +++ b/core/java/android/hardware/input/InputDeviceSensorManager.java @@ -25,6 +25,7 @@ import android.hardware.SensorEvent; 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.MemoryFile; 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 @@ public class InputDeviceSensorManager implements InputManager.InputDeviceListene @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 @@ public class InputDeviceSensorManager implements InputManager.InputDeviceListene @Override public void onInputDeviceChanged(int deviceId) { synchronized (mInputSensorLock) { - if (mSensors.containsKey(deviceId)) { - mSensors.remove(deviceId); - } + mSensors.remove(deviceId); updateInputDeviceSensorInfoLocked(deviceId); } } @@ -196,16 +196,21 @@ public class InputDeviceSensorManager implements InputManager.InputDeviceListene + " 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 @@ public class InputDeviceSensorManager implements InputManager.InputDeviceListene 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 @@ public class InputDeviceSensorManager implements InputManager.InputDeviceListene // 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 @@ public class InputDeviceSensorManager implements InputManager.InputDeviceListene } } 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 @@ public class InputDeviceSensorManager implements InputManager.InputDeviceListene } /** + * 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 @@ public class InputDeviceSensorManager implements InputManager.InputDeviceListene } /** - * 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 c029deae09df..cad0db257ef6 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -160,7 +160,7 @@ public class NetworkPolicyManager { /** @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 000000000000..4d8cf91621ba --- /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 33736d3bf9f3..305c686f8657 100644 --- a/core/java/android/os/BugreportManager.java +++ b/core/java/android/os/BugreportManager.java @@ -22,6 +22,7 @@ import android.annotation.IntDef; 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.Retention; 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 @@ public final class BugreportManager { 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 @@ public final class BugreportManager { /** * 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 @@ public final class BugreportManager { * 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 @@ public final class BugreportManager { * 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 @@ public final class BugreportManager { 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 @@ public final class BugreportManager { } /** + * 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 @@ public final class BugreportManager { * 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 @@ public final class BugreportManager { 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 final class BugreportManager { 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 final class BugreportManager { 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 final class BugreportManager { 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 @@ public final class BugreportManager { 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 e5997764ce43..c28b59ba9aac 100644 --- a/core/java/android/permission/PermissionUsageHelper.java +++ b/core/java/android/permission/PermissionUsageHelper.java @@ -183,8 +183,9 @@ public class PermissionUsageHelper { } 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 @@ public class PermissionUsageHelper { 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 @@ public class PermissionUsageHelper { 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 @@ public class PermissionUsageHelper { 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 @@ public class PermissionUsageHelper { * 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 @@ public class PermissionUsageHelper { * 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 @@ public class PermissionUsageHelper { 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 @@ public class PermissionUsageHelper { 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 @@ public class PermissionUsageHelper { 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 @@ public class PermissionUsageHelper { } } - 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; + } + + List<PackageAttribution> toRemoveProxies = new ArrayList<>(); + for (List<PackageAttribution> proxyList: proxies) { + PackageAttribution lastLink = proxyList.get(proxyList.size() - 1); + if (!specialAttributions.contains(lastLink)) { + continue; + } + for (int proxyNum = 0; proxyNum < proxyList.size(); proxyNum++) { + if (!proxyList.get(proxyNum).equals(lastLink)) { + toRemoveProxies.add(proxyList.get(proxyNum)); + } + } } for (int usageNum = 0; usageNum < rawUsages.size(); usageNum++) { - PackageAttribution usageAttr = rawUsages.get(usageNum).toPackageAttr(); + OpUsage usage = rawUsages.get(usageNum); + // If this attribution has a special attribution, do not remove it - if (specialAttributions.contains(usageAttr)) { + 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 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; + + // 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; + } } } - } - for (int i = 0; i < toRemove.size(); i++) { - rawUsages.remove(toRemove.get(i)); + 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 9db7ca0cad6b..27ba72b97d7c 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1018,6 +1018,20 @@ public final class Settings { "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 @@ public final class Settings { "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 000000000000..92835c2b0626 --- /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 ac5d14e97c85..258a72cbcab4 100644 --- a/core/java/android/view/RemoteAnimationTarget.java +++ b/core/java/android/view/RemoteAnimationTarget.java @@ -270,7 +270,7 @@ public class RemoteAnimationTarget implements Parcelable { 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 @@ public class RemoteAnimationTarget implements Parcelable { 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 4f7e841bd072..45fa41b252aa 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -663,24 +663,34 @@ public interface WindowManager extends ViewManager { } /** - * 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 ac80d9f4cdd0..4bcdeea472e3 100644 --- a/core/java/android/view/textclassifier/OWNERS +++ b/core/java/android/view/textclassifier/OWNERS @@ -6,3 +6,5 @@ svetoslavganov@android.com 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 e4de4001c3e2..ed20d26a8b47 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -196,11 +196,6 @@ public class ImageView extends View { 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 @@ public class ImageView extends View { 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 000000000000..e0ddf056653f --- /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 55d47cb7ed8b..af37fbc6310f 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 @@ oneway interface ITransitionPlayer { * 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 index edf96ddd4e5a..19c76d153be0 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 000000000000..4421f06460a0 --- /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/core/java/android/window/TransitionRequestInfo.aidl b/core/java/android/window/TransitionRequestInfo.aidl new file mode 100644 index 000000000000..d2b9ccfd657e --- /dev/null +++ b/core/java/android/window/TransitionRequestInfo.aidl @@ -0,0 +1,19 @@ +/* + * 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; + +parcelable TransitionRequestInfo; diff --git a/core/java/android/window/TransitionRequestInfo.java b/core/java/android/window/TransitionRequestInfo.java new file mode 100644 index 000000000000..cc493ab63e22 --- /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 cca39ea3287d..ae566c3988cd 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 302ac3cad65d..8dc56ed15d6f 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -1946,7 +1946,7 @@ static jint convertAudioMixToNative(JNIEnv *env, 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 2ff474b140e0..4dc81214b95e 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -1784,7 +1784,7 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, 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 51fb264cfeb8..b705a016c5e3 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 ef54db1a422c..be7ecfc00f01 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 1845faacc891..529db3f53b42 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 c3164abbb015..bac50f1b2c07 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 5715b31b94bc..317a76fa2913 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 c72a0cd63b36..12acfd7cf830 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 912db1e835dc..696aa11618ff 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 05ff21853131..465ea172b1c0 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.Charset; 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 @@ public class TypefaceSystemFallbackTest { } 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 000000000000..9a30e826a24f --- /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 000000000000..24561c59bba6 --- /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 000000000000..46b3cb8824a0 --- /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 fb8b17c1f159..201f649cde52 100644 --- a/data/etc/Android.bp +++ b/data/etc/Android.bp @@ -102,6 +102,14 @@ prebuilt_etc { } 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 000000000000..4fd91c3ea58e --- /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 73fff7207c45..af100c96f6f5 100644 --- a/graphics/java/android/graphics/FontListParser.java +++ b/graphics/java/android/graphics/FontListParser.java @@ -31,6 +31,7 @@ import java.io.IOException; 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 @@ public class FontListParser { * 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 @@ public class FontListParser { 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 @@ public class FontListParser { * 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 @@ public class FontListParser { 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 @@ public class FontListParser { 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 @@ public class FontListParser { } } 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 61a47493c2ff..cf2f970e3d58 100644 --- a/graphics/java/android/graphics/Point.java +++ b/graphics/java/android/graphics/Point.java @@ -20,8 +20,6 @@ import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; -import java.io.PrintWriter; - /** * Point holds two integer coordinates */ @@ -72,17 +70,6 @@ public class Point implements Parcelable { 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 2d626b9a622f..8dd7f317c842 100644 --- a/graphics/java/android/graphics/RecordingCanvas.java +++ b/graphics/java/android/graphics/RecordingCanvas.java @@ -220,7 +220,7 @@ public final class RecordingCanvas extends BaseRecordingCanvas { 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 7f2e503ac8fd..1ace32277f0a 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 @@ public class RuntimeShader extends Shader { 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 @@ public class RuntimeShader extends Shader { * 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)); + public RuntimeShader(@NonNull String sksl, boolean isOpaque) { + super(ColorSpace.get(ColorSpace.Named.SRGB)); + mIsOpaque = isOpaque; + mNativeInstanceRuntimeShaderBuilder = nativeCreateBuilder(sksl); + NoImagePreloadHolder.sRegistry.registerNativeAllocation( + this, mNativeInstanceRuntimeShaderBuilder); } /** - * Creates a new RuntimeShader. + * 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 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. + * @param uniformName name matching the uniform declared in the SKSL shader + * @param value */ - public RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms, - @Nullable Shader[] shaderInputs, boolean isOpaque) { - this(sksl, uniforms, shaderInputs, isOpaque, ColorSpace.get(ColorSpace.Named.SRGB)); + public void setUniform(@NonNull String uniformName, float value) { + setUniform(uniformName, new float[] {value}); } - private RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms, - @Nullable Shader[] shaderInputs, boolean isOpaque, - ColorSpace colorSpace) { - super(colorSpace); - mUniforms = uniforms; - mInputShaders = shaderInputs; - mIsOpaque = isOpaque; - mNativeInstanceRuntimeShaderFactory = nativeCreateShaderFactory(sksl); - NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, - mNativeInstanceRuntimeShaderFactory); + /** + * 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 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 a vecN/floatN where N is + * the size of the values array 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 values */ - public void updateUniforms(@Nullable byte[] uniforms) { - mUniforms = uniforms; + 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 16a53c25db08..93b1fcc3ba1f 100644 --- a/graphics/java/android/graphics/fonts/SystemFonts.java +++ b/graphics/java/android/graphics/fonts/SystemFonts.java @@ -92,7 +92,7 @@ public final class SystemFonts { 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 @@ public final class SystemFonts { } /** - * @see #buildSystemFallback(String, String, String, FontCustomizationParser.Result, Map) + * @see #buildSystemFallback(String, String, Map, FontCustomizationParser.Result, Map) * @hide */ @VisibleForTesting @@ -236,7 +236,7 @@ public final class SystemFonts { @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 @@ public final class SystemFonts { * @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 @@ public final class SystemFonts { @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 @@ public final class SystemFonts { /** @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 6c733ba712d5..33e8dede9f5c 100644 --- a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java +++ b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java @@ -139,7 +139,9 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS 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 0290d9f4b316..2cfb13e7dea6 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 0146b728bcad..7aedc1b50db0 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 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener { @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 94b2cc0455bd..d066cf92650c 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.os.IBinder; 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 @@ public class SplitScreenTransitions implements Transitions.TransitionHandler { } @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 4cd2c504c83e..f1e06f7f5724 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.Animator; 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 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { @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 000000000000..cf141c6a4826 --- /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 3b2ac70007e4..c085168a3317 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 static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPI 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.internal.protolog.common.ProtoLog; 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 @@ import java.util.Arrays; /** 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 @@ public class Transitions { 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 @@ public class Transitions { 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 @@ public class Transitions { 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 @@ public class Transitions { 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 @@ public class Transitions { 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 @@ public class Transitions { } } 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 @@ public class Transitions { 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 @@ public class Transitions { 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 @@ public class Transitions { * 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 @@ public class Transitions { /** * 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 @@ public class Transitions { } @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 c46e59ad396a..f3bee4ba27e8 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 static org.mockito.Mockito.verify; 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 @@ public class ShellTransitionTests { 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 @@ public class ShellTransitionTests { @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 @@ public class ShellTransitionTests { .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 @@ public class ShellTransitionTests { // 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 @@ public class ShellTransitionTests { // 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 @@ public class ShellTransitionTests { 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 @@ public class ShellTransitionTests { @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 @@ public class ShellTransitionTests { 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 815ffdeade45..1ebc48900349 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -819,10 +819,10 @@ void SkiaCanvas::drawRipple(uirenderer::CanvasPropertyPrimitive* x, 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 e6fc9da0a9d3..82b7de4a616b 100644 --- a/libs/hwui/SkiaCanvas.h +++ b/libs/hwui/SkiaCanvas.h @@ -152,7 +152,7 @@ public: 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 ea9fea974d06..fa0c45b5221c 100644 --- a/libs/hwui/canvas/CanvasOps.h +++ b/libs/hwui/canvas/CanvasOps.h @@ -161,7 +161,7 @@ struct CanvasOp<CanvasOpType::DrawRippleProperty> { } 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 9304b7af9cd9..184b11e735bb 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 @@ public: 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 aaec60baaa4a..ad3fd552204e 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 ComposeShader_create(JNIEnv* env, jobject o, jlong matrixPtr, /////////////////////////////////////////////////////////////////////////////////////////////// -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 gComposeShaderMethods[] = { }; 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 a74e56183bfd..926e23349a05 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_drawCircleProps(CRITICAL_JNI_PARAMS_C 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 @@ static void android_view_DisplayListCanvas_drawRippleProps(CRITICAL_JNI_PARAMS_C 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 3142d927d4c4..78591450f10a 100644 --- a/libs/hwui/pipeline/skia/AnimatedDrawables.h +++ b/libs/hwui/pipeline/skia/AnimatedDrawables.h @@ -61,13 +61,13 @@ public: 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 @@ protected: } 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 5f35155c2b5a..9e91dff9e28e 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -90,9 +90,9 @@ void SkiaRecordingCanvas::drawRipple(uirenderer::CanvasPropertyPrimitive* x, 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 ee308f0832a2..32c179191ec6 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h @@ -71,7 +71,7 @@ public: 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 000000000000..eca35dd69362 --- /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 b650a9fd0416..a5e28158ab78 100644 --- a/location/java/android/location/GnssCapabilities.java +++ b/location/java/android/location/GnssCapabilities.java @@ -58,6 +58,8 @@ public final class GnssCapabilities implements Parcelable { /** @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 @@ public final class GnssCapabilities implements Parcelable { 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 @@ public final class GnssCapabilities implements Parcelable { } /** + * 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 @@ public final class GnssCapabilities implements Parcelable { if (hasAntennaInfo()) { builder.append("ANTENNA_INFO "); } + if (hasMeasurementCorrelationVectors()) { + builder.append("MEASUREMENT_CORRELATION_VECTORS "); + } if (hasMeasurementCorrectionsLosSats()) { builder.append("LOS_SATS "); } @@ -720,6 +737,17 @@ public final class GnssCapabilities implements Parcelable { } /** + * 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 5509a6c65614..3d188c0acce3 100644 --- a/location/java/android/location/GnssMeasurement.java +++ b/location/java/android/location/GnssMeasurement.java @@ -38,6 +38,9 @@ import android.os.Parcelable; 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 @@ public final class GnssMeasurement implements Parcelable { 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 @@ public final class GnssMeasurement implements Parcelable { 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 @@ public final class GnssMeasurement implements Parcelable { * @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 @@ public final class GnssMeasurement implements Parcelable { mSatelliteInterSignalBiasUncertaintyNanos = measurement.mSatelliteInterSignalBiasUncertaintyNanos; mSatellitePvt = measurement.mSatellitePvt; + mReadOnlyCorrelationVectors = measurement.mReadOnlyCorrelationVectors; } /** @@ -1712,6 +1718,7 @@ public final class GnssMeasurement implements Parcelable { * * <p>The value is only available if {@link #hasSatellitePvt()} is * {@code true}. + * * @hide */ @Nullable @@ -1745,6 +1752,58 @@ public final class GnssMeasurement implements Parcelable { 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 @@ public final class GnssMeasurement implements Parcelable { 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 @@ public final class GnssMeasurement implements Parcelable { 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 @@ public final class GnssMeasurement implements Parcelable { builder.append(mSatellitePvt.toString()); } + if (hasCorrelationVectors()) { + for (CorrelationVector correlationVector : mReadOnlyCorrelationVectors) { + builder.append(correlationVector.toString()); + builder.append("\n"); + } + } + return builder.toString(); } @@ -1958,6 +2040,7 @@ public final class GnssMeasurement implements Parcelable { 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 613f5918b708..f509252e7542 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 @@ public final class GnssMeasurementRequest implements Parcelable { @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 @@ public final class GnssMeasurementRequest implements Parcelable { @Override public void writeToParcel(@NonNull Parcel parcel, int flags) { parcel.writeBoolean(mFullTracking); + parcel.writeBoolean(mCorrelationVectorOutputsEnabled); } @NonNull @@ -78,6 +97,9 @@ public final class GnssMeasurementRequest implements Parcelable { if (mFullTracking) { s.append("FullTracking"); } + if (mCorrelationVectorOutputsEnabled) { + s.append(", CorrelationVectorOutPuts"); + } s.append(']'); return s.toString(); } @@ -90,13 +112,15 @@ public final class GnssMeasurementRequest implements Parcelable { 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 @@ public final class GnssMeasurementRequest implements Parcelable { /** Builder for {@link GnssMeasurementRequest} */ public static final class Builder { + private boolean mCorrelationVectorOutputsEnabled; private boolean mFullTracking; /** @@ -118,10 +143,25 @@ public final class GnssMeasurementRequest implements Parcelable { * 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 @@ public final class GnssMeasurementRequest implements Parcelable { /** 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 2dc9eb44236f..0ce1ad0d9380 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -3171,7 +3171,9 @@ public class LocationManager { 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 1027f9c0a7be..a6a0e7aa24ff 100644 --- a/location/java/android/location/LocationManagerInternal.java +++ b/location/java/android/location/LocationManagerInternal.java @@ -80,4 +80,12 @@ public abstract class LocationManagerInternal { */ // 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 221147dcad8f..0c733482b2b5 100644 --- a/media/java/android/media/audiopolicy/AudioMix.java +++ b/media/java/android/media/audiopolicy/AudioMix.java @@ -218,7 +218,7 @@ public class AudioMix { /** @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 @@ public class AudioMix { } } } - 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 de153135eeb9..1f07705a4d94 100644 --- a/media/java/android/media/audiopolicy/AudioMixingRule.java +++ b/media/java/android/media/audiopolicy/AudioMixingRule.java @@ -46,11 +46,11 @@ import java.util.Objects; 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 @@ public class AudioMixingRule { 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 class AudioMixingRule { 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 @@ public class AudioMixingRule { * @return the same Builder instance. */ public @NonNull Builder allowPrivilegedPlaybackCapture(boolean allow) { - mAllowPrivilegedPlaybackCapture = allow; + mAllowPrivilegedMediaPlaybackCapture = allow; return this; } @@ -639,7 +643,7 @@ public class AudioMixingRule { */ 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 697d80c6b78e..ede68bd5022b 100644 --- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java +++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java @@ -97,7 +97,7 @@ public class AudioPolicyConfig implements Parcelable { 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 @@ public class AudioPolicyConfig implements Parcelable { 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 47debe90c854..52d952c5066d 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 @@ import android.media.metrics.PlaybackMetrics; 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/metrics/NetworkEvent.aidl b/media/java/android/media/metrics/NetworkEvent.aidl new file mode 100644 index 000000000000..2b7fa02aae64 --- /dev/null +++ b/media/java/android/media/metrics/NetworkEvent.aidl @@ -0,0 +1,19 @@ +/* + * 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; + +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 000000000000..a330bc0b66df --- /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/metrics/PlaybackErrorEvent.aidl b/media/java/android/media/metrics/PlaybackErrorEvent.aidl new file mode 100644 index 000000000000..b0d6b4beae57 --- /dev/null +++ b/media/java/android/media/metrics/PlaybackErrorEvent.aidl @@ -0,0 +1,19 @@ +/* + * 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; + +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 000000000000..db7000536299 --- /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 82a58036cfa4..070b4e4aa14b 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 @@ import java.util.Objects; * @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 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; } - public int getStreamSourceType() { - return mStreamSourceType; + /** + * 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 boolean equals(@Nullable Object o) { + 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 @@ public final class PlaybackMetrics implements Parcelable { /** @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 createFromParcel(@NonNull Parcel in) { - return new PlaybackMetrics(in); - } - }; + @Override + public PlaybackMetrics[] newArray(int size) { + return new PlaybackMetrics[size]; + } + + @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 d51ff473696d..63a50ae31134 100644 --- a/media/java/android/media/metrics/PlaybackMetricsManager.java +++ b/media/java/android/media/metrics/PlaybackMetricsManager.java @@ -48,6 +48,29 @@ public class PlaybackMetricsManager { 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 @@ public class PlaybackMetricsManager { 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 4ad89067952c..061e66532d55 100644 --- a/media/java/android/media/metrics/PlaybackSession.java +++ b/media/java/android/media/metrics/PlaybackSession.java @@ -50,6 +50,27 @@ public final class PlaybackSession implements AutoCloseable { 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/metrics/PlaybackStateEvent.aidl b/media/java/android/media/metrics/PlaybackStateEvent.aidl new file mode 100644 index 000000000000..8b8d05bd4093 --- /dev/null +++ b/media/java/android/media/metrics/PlaybackStateEvent.aidl @@ -0,0 +1,19 @@ +/* + * 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; + +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 000000000000..6ce5bf0f0f33 --- /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 ed99fad5088a..d8d1ba1341bb 100644 --- a/media/java/android/media/tv/ITvInputManager.aidl +++ b/media/java/android/media/tv/ITvInputManager.aidl @@ -94,6 +94,8 @@ interface ITvInputManager { // 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 24b87d50b33e..158cf211d9f0 100644 --- a/media/java/android/media/tv/ITvInputSession.aidl +++ b/media/java/android/media/tv/ITvInputSession.aidl @@ -58,4 +58,6 @@ oneway interface ITvInputSession { // 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 e89d33d70d5c..abccf8da9cfc 100644 --- a/media/java/android/media/tv/ITvInputSessionWrapper.java +++ b/media/java/android/media/tv/ITvInputSessionWrapper.java @@ -68,6 +68,8 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand 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 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand 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 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand 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 b12f7c551288..1249e0d3cb0f 100644 --- a/media/java/android/media/tv/TvInputHardwareInfo.java +++ b/media/java/android/media/tv/TvInputHardwareInfo.java @@ -188,6 +188,17 @@ public final class TvInputHardwareInfo implements Parcelable { 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 195ad5bc10f9..54cb2bff5566 100644 --- a/media/java/android/media/tv/TvInputInfo.java +++ b/media/java/android/media/tv/TvInputInfo.java @@ -143,6 +143,7 @@ public final class TvInputInfo implements Parcelable { // 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 @@ public final class TvInputInfo implements Parcelable { 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 @@ public final class TvInputInfo implements Parcelable { mIconDisconnected = iconDisconnected; mSetupActivity = setupActivity; mCanRecord = canRecord; + mCanPauseRecording = canPauseRecording; mTunerCount = tunerCount; mHdmiDeviceInfo = hdmiDeviceInfo; mIsConnectedToHdmiSwitch = isConnectedToHdmiSwitch; @@ -386,6 +388,14 @@ public final class TvInputInfo implements Parcelable { } /** + * 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 @@ public final class TvInputInfo implements Parcelable { && 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 @@ public final class TvInputInfo implements Parcelable { 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 @@ public final class TvInputInfo implements Parcelable { 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 @@ public final class TvInputInfo implements Parcelable { 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 @@ public final class TvInputInfo implements Parcelable { } /** + * 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 @@ public final class TvInputInfo implements Parcelable { 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 @@ public final class TvInputInfo implements Parcelable { 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 e9959be249ec..98b9ad8ec2b3 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -2523,6 +2523,40 @@ public final class TvInputManager { } /** + * 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 945fb3bff936..77fb2b236698 100755 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -1873,6 +1873,28 @@ public abstract class TvInputService extends Service { /** + * 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 @@ public abstract class TvInputService extends Service { } /** + * 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 23fadac8a72b..180e2bd6845b 100644 --- a/media/java/android/media/tv/TvRecordingClient.java +++ b/media/java/android/media/tv/TvRecordingClient.java @@ -30,6 +30,7 @@ import android.util.Log; import android.util.Pair; import java.util.ArrayDeque; +import java.util.Objects; import java.util.Queue; /** @@ -49,6 +50,8 @@ public class TvRecordingClient { 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 @@ public class TvRecordingClient { 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 @@ public class TvRecordingClient { mSession.release(); mIsTuned = false; mIsRecordingStarted = false; + mIsPaused = false; + mIsRecordingStopping = false; mSession = null; } } @@ -169,7 +179,8 @@ public class TvRecordingClient { * * @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 @@ public class TvRecordingClient { * @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 @@ public class TvRecordingClient { } 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 @@ public class TvRecordingClient { 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 @@ public class TvRecordingClient { } mIsTuned = false; mIsRecordingStarted = false; + mIsPaused = false; + mIsRecordingStopping = false; mSessionCallback = null; mSession = null; if (mCallback != null) { @@ -398,7 +517,13 @@ public class TvRecordingClient { 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 46b29f5bc90a..7192c0737b77 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -988,9 +988,11 @@ public class Tuner implements AutoCloseable { } /** - * 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 @@ public class Tuner implements AutoCloseable { } /** - * 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 02390bb7c31b..c38d9194df44 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 @@ aidl_interface { local_include_dir: "aidl", backend: { java: { - sdk_version: "current", + enabled: true, }, cpp: { enabled: true, @@ -33,4 +24,5 @@ aidl_interface { 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 6f7adbc65318..e399fbdfabcf 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.RequiresFeature; 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 a1f6687a1b81..483d9720b430 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 14761a6f92a8..d6d64f6f2c8e 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 @@ FrontendClient::~FrontendClient() { 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 @@ Status TunerFrontendCallback::onEvent(int frontendEventType) { 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> HidlFrontendCallback::onScanMessageExt1_1(FrontendScanMessageTypeEx } 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 32356744c839..4f95c22bd3c7 100644 --- a/media/jni/tuner/FrontendClient.h +++ b/media/jni/tuner/FrontendClient.h @@ -30,7 +30,7 @@ using Status = ::ndk::ScopedAStatus; 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 @@ public: 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 @@ private: 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 @@ private: sp<HidlFrontendCallback> mHidlCallback; int mId; + int mType; }; } // namespace android diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp index 39e6ba27e56f..f5e35248fcfd 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 @@ sp<FrontendClient> TunerClient::openFrontend(int frontendHandle) { // 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 @@ sp<FrontendClient> TunerClient::openFrontend(int frontendHandle) { 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 @@ void TunerClient::updateFrontendResources() { } 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 @@ vector<int> TunerClient::getLnbHandles() { 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 a3d2d02c7ef6..8a1181a38fe2 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 @@ private: 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 0ecd56d512a2..aa86c74e16c9 100644 --- a/native/android/include_platform/android/activity_manager.h +++ b/native/android/include_platform/android/activity_manager.h @@ -115,8 +115,6 @@ enum { AACTIVITYMANAGER_IMPORTANCE_GONE = 1000, }; -#if __ANDROID_API__ >= 31 - /** * Adds a UidImportanceListener to the ActivityManager. * @@ -169,8 +167,6 @@ bool AActivityManager_isUidActive(uid_t uid) __INTRODUCED_IN(31); */ 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 4120a7326817..3751564ca465 100644 --- a/native/graphics/jni/Android.bp +++ b/native/graphics/jni/Android.bp @@ -22,22 +22,20 @@ cc_library_shared { "-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 @@ cc_library_shared { 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 @@ cc_fuzz { 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 Binary files differnew file mode 100644 index 000000000000..4fd63d5794ff --- /dev/null +++ b/native/graphics/jni/corpus/webp-color-profile-lossless.webp diff --git a/native/graphics/jni/fuzz_imagedecoder.cpp b/native/graphics/jni/fuzz_imagedecoder.cpp index f2cd1a8f4eb9..015aca70e4e0 100644 --- a/native/graphics/jni/fuzz_imagedecoder.cpp +++ b/native/graphics/jni/fuzz_imagedecoder.cpp @@ -73,6 +73,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 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 5973790e48fd..eab5f4143968 100644 --- a/native/graphics/jni/imagedecoder.cpp +++ b/native/graphics/jni/imagedecoder.cpp @@ -121,8 +121,12 @@ int AImageDecoder_createFromAAsset(AAsset* asset, AImageDecoder** outDecoder) { } *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 8fc353191441..d366a0be94a5 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 ff31454cba08..68e816adf726 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 aedf0f3f94b2..184837f692e8 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 f0c3ee890a41..116d63b3d8d5 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 64bea4da663b..bc719a340074 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 3f067227fa47..a0e52989c964 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 25e235c98106..96a513dff683 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 264ce27b76d6..3775dbe87b38 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 65f92c908b86..1e8fd0be40c3 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 f8e24b7a1cf4..133aea35753e 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 ae8ca9f7efab..cf26b08c949b 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 675bd2945382..389ccd0ccc95 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 a6720fca2df7..30a331a9e699 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 eb2631f2f425..ead68e3ba18e 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 cb31866cc36f..4867a8ed98e6 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 a30c199fa2d1..a0e50917fdc1 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 a30c199fa2d1..a0e50917fdc1 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 a30c199fa2d1..a0e50917fdc1 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 a30c199fa2d1..a0e50917fdc1 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 ea39d0a6c01a..f3c4b1dcb434 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 63097dc786ff..5780fb407524 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 784c30d48e36..78cfa5a74a67 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 b5058701cc8a..3f29da0caaa0 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 826556da33de..30907a2fabf7 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 66eafc3f320f..9e1ecb195f61 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 d4a20d9421f1..4a1f13fd9346 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 e91ccf4de04f..ce5e262d867a 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 756727a7f3f9..e15639b032ec 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 7849e42a5bf1..1205e46933ac 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 1f1edd14b967..e99a3cdef2e3 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 6e280b551b24..80c0d953f6d0 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 beacbfdf38b9..b574ff690ac1 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 cd2900642b9b..b271b122a58e 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 b0037aa74c2d..e8656907bf9a 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 cc05490981b4..2d4fd4a5e6e4 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 d3ada7427553..8698bfb5ea35 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 2632509278e1..beb1482f77c3 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 ae9d6f483150..33950eb373c7 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 3fb0140bb702..b50c56a33ebf 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 5b36106f3baf..4ab0abdf4ac8 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 6ff3f830e2db..fcfe030ddb0e 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 cdcebada0709..e70800445139 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 47cf76cd1a11..f4ae18f77847 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 f29041389686..299d586045e8 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 9cce298b528c..35ee34db59f7 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 5fcbf7dfd802..a27bc15cc850 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 56930d3edf59..11510acad919 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 a9d215157c52..6a85c836bb49 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 5cc18c5b793b..6fed96bcdf6d 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 b6734e8d1282..6b071cd54950 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 cd4fdbf572c3..4d048cb81ad9 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 65bf262d5bcf..68f9109762fe 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 d17041f3b6cb..1188922607b9 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 23f165a9259c..b16869dece36 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 090f2a20820c..cac087f45d69 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 e885674fb2db..e390161bb22a 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 5a7fb3a1bb4f..2153770e169d 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 03fae5c5c01c..d1aa50b6c30f 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 33135b2488c5..ff211f2550d5 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 a82837030f23..b16d0458055a 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 4258e705e7d1..40f9d2d7310e 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 45b03d604a64..745d1630dd86 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 4258e705e7d1..40f9d2d7310e 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 060e9965f2f9..6040adf969f3 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 7982507c434e..9939a8255d0b 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 8bbc1a6827cb..6e6b0293cfa8 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 1037a9693da2..520aa0900e4d 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 f2d4c6fb03d0..f60cab8e4710 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 c9336b3b4433..4c308e8c5b67 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 5298194bc422..da08d879940f 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 caacba098208..a73cbfa85e40 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 ae8ade7ef075..5865ec97bbb6 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 373ed4543cc9..f9d640128e9c 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 f73e7136b5f0..82616cc8bc19 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 8c1848a1e582..77a9fff1f2fc 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 8fcc3d27d5d5..6d6264236e46 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 255eca50d2b2..2c30ea743d8c 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 b5827f2c78ad..f68fd9230c71 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 2bbffdcb7c2d..967b7f9b5a25 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 96c49f2fed3c..c8c4b22c51df 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 d67db4141fe9..f0234a4e7d9f 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 a1abd98dfa1b..caf232169267 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 57d2173a2d2a..5ec64a513844 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 c9a2fd85edcc..b8c2ed0f952a 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 c811037bd24c..7df0869f19c7 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 77d252d65a42..eb95466580fc 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 fc93650a6b85..723caf2ce0a1 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 @@ public class AdaptiveIcon extends LayerDrawable { 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 b1553e9f463f..7e3ce9d3595c 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 defbf54ccb10..6f4f72aae8ca 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 1326c5190a79..3f5df34b07b0 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 702a41948eb2..0351d946c05c 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 c5dbda907cef..0f7db8f1e966 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 b18b1c416588..0855d17e8c70 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 d92f171bd049..3386fe8649ea 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 57d9a554fef0..6ac2172496c4 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 4d4b392f1feb..19ed5bdd5688 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 88fb83f3b295..b0e9342c19c6 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 6925d044f6c9..9377624d6d26 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 dd3a8118510a..a2a7770e7db7 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 6b8914d457dc..4db4d5c81e3f 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 c8b4e2b5d42c..b76afa5c42d6 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 eb87a585cfdd..c608a629a80d 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 ad16c89d3871..e67c3d1ddc5a 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 451590847147..b0830fc40e2e 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 ad16c89d3871..e67c3d1ddc5a 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 ad16c89d3871..e67c3d1ddc5a 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 f8903bb23877..4c0af75fada6 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 26cffd20a0e7..9ae77819029b 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 5a58a20fb63b..203726a5d557 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 2d5d0b5f4eb3..379ed6cb9065 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 c7b376a4bd3d..2582854924fe 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 ae99c010ec39..cb598e523100 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 6dd3a21db0fd..31dfe1829133 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 58ea7957b68f..ed536b4f51d4 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 cf8ec408106b..46bd71b9b382 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 ddcfc5804ba5..9cae3112cd48 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 f7d2bec35406..83bb2d1e7732 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 883e2a42ea93..9f184c7052f5 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 de9e4dd87dcf..cd6cbf3bc396 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 e4f56e6e45da..3b8091872562 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 d5d828928097..ce9e66522aaf 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 55c03b6fbe08..93b24a0bf066 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 6bbfa16d6597..ab678092dd9c 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 d97926b8ae76..08133056c408 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 6cceef600759..16ee9c00fa18 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 f069d1530c0c..5b47381758f7 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 3841e3bec853..fd63dcb343ae 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 75b731b18fdd..a9c3f316f4c2 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 115937677c2d..bc3656f0846f 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 3e3f3176d423..8408c93459a6 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 279980be8c77..1dcfcf7bbb36 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 f36adc6b7bb1..3d9b78acf6ed 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 31e5b7c9f275..0674f118c04b 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 485a228da344..1455669fbc85 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 6ce0a7dee163..f13cb0b03884 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 c1a246f2dd74..f5be76ebd228 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 1ba076dc6f49..9527793b179e 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 61374e8b25ba..1dcb3cfd349d 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 fe6204bdd434..13f69c1b793e 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 c0e9fe56e118..5795cc9b6d92 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 b7ea8a09c6e4..718ce5de62f8 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 ac1ccb612896..41e84f9e1a84 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 fc26f5906309..f24b52bb409c 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 7ff1ba4a9f92..42ad0fece020 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 fc26f5906309..f24b52bb409c 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 be0193ce9a1e..0743fe99056c 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 fad3591d7b36..d19438aceb16 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 69a918a898be..15fe8c8370e8 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 f98237c27537..ee53b7cfbcec 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 710fbdb14901..66d33a7bf51a 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 b4e5db9baff4..d5c0231f7652 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 d134f8ad5c3e..ce74b84aa1e4 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 e90a915c81b3..eacb7a80cdb8 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 653beef22c5c..e7045a72b51b 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 b75818a873b0..06c7ccb98120 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 a010c1072884..6316452511b4 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 4485384d8880..0aabbe5f96ab 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 081a11515bd0..44c8f13acb96 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 b4e533d39f3a..7851111910d2 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 4787aeb90a7c..c2a96c6a810e 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 df975b316b8a..259642466187 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 e1b6047793d1..60afd6d8352f 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 e095afd2f3f7..925f73870ea3 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 a1dc7f1515b7..e40d3519788d 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 a04f47cfc629..c304c14f6073 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 c63cf06cf75c..2b5e9cdc017d 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 53e67e153c74..fbc71f100b40 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 @@ public class SecureSettingsValidators { 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 e22f2649d540..07a5a4455f27 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -742,7 +742,6 @@ public class SettingsBackupTest { 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 a1bb66ea640a..41cc835ead82 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 f21b80bc759b..51298bbda34b 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 000000000000..0161bcbd1937 --- /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 000000000000..0ce7a581a7e5 --- /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 000000000000..3d6ca7acda87 --- /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 0beb286b6f63..317e0e89118b 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 f56e84ae1606..b7b24db814b4 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 aaaf7788c5c3..ca823eda6e60 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 7e3e3cb04280..8e6fd519f05f 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 6c22cc34b83e..d9a2ae17f1b4 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 2f3d6d28526e..ef3a1cf27515 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 925e86a8916b..a1804d12ab76 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 6a683c742931..6b59b2484f6f 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 953ec006016b..a6344d0c45b0 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 6bf185230602..0dc97fabeae1 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 71105cc55b50..bd5815a6c675 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 65e676737ca2..41a33ef0d51b 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 e50aa57e70cb..3d8b027396dc 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 3cdebf9c80d9..a0e535fb4ca2 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 c6ae7f4b0c51..13dafa019f72 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 ea25ec6e771c..dcee89d5ef4b 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 a373a5c0061d..3217d1c058ad 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 ea25ec6e771c..dcee89d5ef4b 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 ea25ec6e771c..dcee89d5ef4b 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 101d11245ffc..00fa58477291 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 1fc1609c7dcc..a552c7647333 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 dd36a64812ab..4277c6316922 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 fb27be994265..64299318c819 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 d8b21c633dfa..664ae9816066 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 df306f83e16e..578fe887619d 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 4e0af373f572..d73b2eb7b1ac 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 8c944a4a0e0f..df0e36c7d364 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 7ad239dc4ee2..64a232874f42 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 145b3c06b387..75db845b2e0f 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 ea7af17dcb6a..c0d2557a45a6 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 a8bed5b26401..0bfa5aef27c6 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 4ffa5b2e04ff..33d0534d47c6 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 cff5b0dc65b3..22b8fde2ff51 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 91ffe7308a91..5e51c627f88b 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 f9e7397993dc..9a217ce0c966 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 db5dac43a42a..3f8e8fb68c06 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 86e65bbc3629..72cc5aadefd1 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 8548dae09ee2..d8c148aada43 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 6cd560854960..40a93231f3a1 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 52d9f0e77451..6ab551015704 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 fcf87434ad3b..bda2f1a6b6c4 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 e92bf9bda905..275a73a59155 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 d7a0adc85935..778ccca0c8cf 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 54bcfb978ac9..e602ede4e1ad 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 d513380f9355..0a2e8aeb9e02 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 7e595cd83176..0f320a50b88b 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 e0c27a96de44..29f615eb022b 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 ff36f51b5603..f209ba836e0a 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 203d8b90ae52..001e6a0514a9 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 77925ae0c268..e2ca3bbc61c7 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 c772294a6bdf..0b1a1ff35120 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 965b8958b458..9ed6bb345c6d 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 d3e360147d0f..81c15b066290 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 0c1f9cbbc060..6bccb33550ad 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 565e7fea215d..90defaa3561d 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 9d95cf042dad..0e86b94d58de 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 f598fa3fae09..a216c499844c 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 1e07dd4b785e..ed38d141cb04 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 7d5bc96830a5..3026a18cdde5 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 561e70dd14cb..12422e9851d7 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 7fe53d348e15..0d65c0130c6e 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 dd154e8ad684..0932a96819a8 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 7fe53d348e15..0d65c0130c6e 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 317fc098d522..e1819451aba5 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 bbb014e82b07..5d08e3a79f62 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 a7a2bb7dbbff..7230a06f5eba 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 7eb5297a43f1..1454884e14da 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 6d23f26a6c8d..2cecff72906a 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 7e89b93cec82..3179e99e9b8f 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 af5175c2bbf6..ea862bc6061c 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 41bca7c90b32..66685e9dda2b 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 f122013cc150..1563c768ef16 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 c076a031b93f..a54b1a26d75c 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 fca51077d06f..01c3d7d15549 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 c909d379dedc..e51c3082d095 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 2e75fa3de905..7b8070b2e102 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 98552b1b135d..f9e78c7bcdac 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 b70d36af64c2..72046e1c2eb7 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 bbadf6a7d5f1..9ccc133093f1 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 a20676dca577..67d801b4096e 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 5de7df6a5d69..1d836e897f60 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 7f3f3943e3c5..fa6a5109fbc5 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 485f1cf786be..b69d09796aae 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 1edeacd1a843..2fb0b865625f 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 58baebc27cc6..e9e1a75c7fa4 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 101124ec2a2e..93d2f751e754 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 72dd72410af3..ae55d95b6b52 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 7cdd8b1b80ca..ac2e342b3c34 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 6eec5dc9e1c1..902de23a9e2a 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 364403234e29..937c1df10315 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 class QuickStepContract { 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 @@ public class QuickStepContract { 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 @@ public class QuickStepContract { 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 302a2620aac0..59e81cf96bb2 100644 --- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java +++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java @@ -85,8 +85,8 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie } 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 e6ad1cb9ea88..13da2b06c976 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 @@ public class SystemActions extends SystemUI { 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 dcb6ea3ef5b7..1cafb4c2c313 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 @@ class UdfpsController implements DozeReceiver { 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 @@ class UdfpsController implements DozeReceiver { } 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 a42ab58487b9..c2f80d4d2a5b 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 @@ public class UdfpsView extends View implements DozeReceiver, 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 @@ public class UdfpsView extends View implements DozeReceiver, } canvas.restore(); + + if (mShowScrimAndDot && mRunAfterShowingScrimAndDot != null) { + post(mRunAfterShowingScrimAndDot); + mRunAfterShowingScrimAndDot = null; + } } RectF getSensorRect() { @@ -294,6 +303,10 @@ public class UdfpsView extends View implements DozeReceiver, 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 7ca8e63bfae1..239a77eb2f45 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.ALLOW_NOTIFICATION_LONG_PRESS_NAME 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.ConfigurationController; 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 @@ public abstract class SystemUIDefaultModule { 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 5d184efaa59e..a23b07c5d685 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.internal.config.sysui.SystemUiDeviceConfigFlags.NAV_BA 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 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mNavigationBarView.setNavigationIconHints(hints); } checkBarModes(); + updateSystemUiStateFlags(-1); } @Override @@ -1315,6 +1317,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, 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 065920c9778b..a8761a63f6ad 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 @@ public class PeopleSpaceActivity extends Activity { 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 @@ public class PeopleSpaceActivity extends Activity { 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 1d2e74703b42..eec69f98b9be 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 @@ class PrivacyChipBuilder(private val context: Context, itemsList: List<PrivacyIt 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 e9207f1feff3..bba8579c4f86 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.QSPanel.QSTileLayout; 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 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha 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 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha private TouchAnimator mBrightnessAnimator; private boolean mNeedsAnimatorUpdate = false; + private boolean mToShowing; private boolean mOnKeyguard; private boolean mAllowFancy; @@ -133,6 +137,18 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha } } + 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 16e95900052f..562ac6414997 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 @@ public class QSContainerImpl extends FrameLayout { 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 dbdd04a1e3ba..9a0827d78e62 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 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca (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 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca @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 ba71fa6a8fb3..9b3775e72f9a 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.external.CustomTile; 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.FlashlightTile; 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 @@ public class QSFactoryImpl implements QSFactory { 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 @@ public class QSFactoryImpl implements QSFactory { 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 @@ public class QSFactoryImpl implements QSFactory { mUiModeNightTileProvider = uiModeNightTileProvider; mScreenRecordTileProvider = screenRecordTileProvider; mReduceBrightColorsTileProvider = reduceBrightColorsTileProvider; + mCameraToggleTileProvider = cameraToggleTileProvider; + mMicrophoneToggleTileProvider = microphoneToggleTileProvider; } public QSTile createTile(String tileSpec) { @@ -198,6 +206,10 @@ public class QSFactoryImpl implements QSFactory { 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 000000000000..98740a20a7c0 --- /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 000000000000..8cc0d7b4e8b8 --- /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 000000000000..12205d6483a8 --- /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 357702ada82b..41c2098d2505 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.View; 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 @@ public class ScreenshotView extends FrameLayout implements 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 @@ public class ScreenshotView extends FrameLayout implements mDisplayMetrics = new DisplayMetrics(); mContext.getDisplay().getRealMetrics(mDisplayMetrics); + + mAccessibilityManager = AccessibilityManager.getInstance(mContext); } /** @@ -331,8 +335,10 @@ public class ScreenshotView extends FrameLayout implements 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 f0efed332c7f..00acd7bb6707 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.StatusBarMobileView; 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 interface StatusBarIconController { 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 2870152ed853..5e8d59041fab 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.demomode.DemoModeController; 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 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu } } + /** + * 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 88d0035b333d..36a0e63db19f 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 android.os.UserHandle; 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 @@ public class StatusBarIconHolder { 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 1fdd8161914a..d11e8641f987 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 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba 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 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba 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 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba 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 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba } @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 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba } } + 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 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba 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 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba // 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 1cc312adcbf0..5e88cd5c2423 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 @@ public class CallbackHandler extends Handler implements EmergencyListener, Signa } @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 000000000000..a76d08a438f2 --- /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 000000000000..231fe08e6a99 --- /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 101e3c6f1bc6..24b820669beb 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 @@ public class MobileSignalController extends SignalController<MobileState, Mobile 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 a9c601601961..f2b0d762b6fc 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 @@ public interface NetworkController extends CallbackController<SignalCallback>, D */ 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 1d778419cbaf..4f4a504ddc9c 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; 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 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi 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 6d5ce60ef621..4a09234325ca 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 @@ public interface SensorPrivacyController extends 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 20cc46ff6bbd..a2334f3a23d6 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 @@ import javax.inject.Inject; 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 a05fe1f1b0c2..554145e9773e 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 @@ public abstract class SignalController<T extends State, I extends IconGroup> { } } + 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 069b4051af50..7a4b912d4071 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 @@ public interface StatusBarPolicyModule { /** */ @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 56a4c203e840..df889f2c2ca6 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.ALLOW_NOTIFICATION_LONG_PRESS_NAME 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.ConfigurationController; 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 @@ public abstract class TvSystemUIModule { 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 08cd6e383897..8d77c4a194a9 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 @@ public interface WakeLock { 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 @@ public interface WakeLock { 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 b24f4ab9880d..c052563b36a5 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 @@ public class UdfpsControllerTest extends SysuiTestCase { @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 @@ public class UdfpsControllerTest extends SysuiTestCase { 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 @@ public class UdfpsControllerTest extends SysuiTestCase { 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 2e874a6c2140..c0af15b1f96d 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.internal.statusbar.StatusBarIcon; 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 @@ public class FakeStatusBarIconController extends BaseLeakChecker<IconManager> } @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 446d3f2f72a0..8b86403b554e 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 @@ public class WMShellTest extends SysuiTestCase { 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 000000000000..f48a95c5b3a3 --- /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 9ba71dc5f4f7..e99bb245a2e0 100644 --- a/services/core/java/com/android/server/SensorPrivacyService.java +++ b/services/core/java/com/android/server/SensorPrivacyService.java @@ -283,11 +283,16 @@ public final class SensorPrivacyService extends SystemService { mIndividualEnabled.put(userId, userIndividualEnabled); if (!enable) { - // Remove any notifications prompting the user to disable sensory privacy - NotificationManager notificationManager = - mContext.getSystemService(NotificationManager.class); - - notificationManager.cancel(sensor); + long token = Binder.clearCallingIdentity(); + try { + // Remove any notifications prompting the user to disable sensory privacy + NotificationManager notificationManager = + mContext.getSystemService(NotificationManager.class); + + 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 b76f32788f6c..dde182b90517 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -564,8 +564,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 25f7fb673ce7..b587f1b2599d 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 @@ public class ActivityManagerService extends IActivityManager.Stub */ @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 @@ public class ActivityManagerService extends IActivityManager.Stub } 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 @@ public class ActivityManagerService extends IActivityManager.Stub } } - tempWhitelistUidLocked(targetUid, duration, tag, - BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED); + tempWhitelistUidLocked(targetUid, duration, tag, type); } /** @@ -15949,9 +15952,9 @@ public class ActivityManagerService extends IActivityManager.Stub @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 @@ public class ActivityManagerService extends IActivityManager.Stub @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 2ae3d355a7ed..42172bf7e1df 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 @@ public class PendingIntentController { } 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 fbfed34d1bf0..631b6327e7ad 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 static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NA 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.TransactionTooLargeException; 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 class PendingIntentRecord extends IIntentSender.Stub { 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 @@ public final class PendingIntentRecord extends IIntentSender.Stub { 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 @@ public final class PendingIntentRecord extends IIntentSender.Stub { 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 @@ public final class PendingIntentRecord extends IIntentSender.Stub { 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 @@ public final class PendingIntentRecord extends IIntentSender.Stub { 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 @@ public final class PendingIntentRecord extends IIntentSender.Stub { 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 @@ public final class PendingIntentRecord extends IIntentSender.Stub { } 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 08eeda20b4ba..17627fa23a96 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 @@ public class AudioService extends IAudioService.Stub } 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 @@ public class AudioService extends IAudioService.Stub 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 8abeef65bf9f..5e7ddeb64fb4 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 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { @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 7a1219644eb4..6cc8687b3426 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 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider @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 2a814268da25..40d20734eb50 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 com.android.server.wm.WindowManagerInternal; 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 @@ public class CameraServiceProxy extends SystemService 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 @@ public class CameraServiceProxy extends SystemService + ", 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 @@ public class CameraServiceProxy extends SystemService 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 aadaf4d9584f..5dc8c1a00eaf 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 @@ public class PacProxyInstaller { 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 @@ public class PacProxyInstaller { private volatile boolean mHasSentBroadcast; private volatile boolean mHasDownloaded; - private Handler mConnectivityHandler; + private final Handler mConnectivityHandler; private final int mProxyMessage; /** @@ -102,6 +99,13 @@ public class PacProxyInstaller { 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 class PacProxyInstaller { } } - 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 @@ public class PacProxyInstaller { * 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 @@ public class PacProxyInstaller { 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 class PacProxyInstaller { 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 @@ public class PacProxyInstaller { 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 d83ff837d9be..b618d2b99a63 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 @@ public class ProxyTracker { 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 @@ public class ProxyTracker { } } + 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 60e4595a7679..55103ca6cd1c 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.database.ContentObserver; 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.media.projection.IMediaProjectionManager; 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.util.Spline; 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.DisplayThread; 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 @@ public final class DisplayManagerService extends SystemService { // 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 @@ public final class DisplayManagerService extends SystemService { 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 @@ public final class DisplayManagerService extends SystemService { } } - 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 a12785889bd3..bb2fbed354aa 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 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { 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 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { 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 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { } } + 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 521ce6973522..633c0c417192 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.NonNull; 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 @@ public final class FontManagerService { 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 @@ public final class FontManagerService { } } - @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 @@ public final class FontManagerService { @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 @@ public final class FontManagerService { } 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 000000000000..7306471e68c2 --- /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 a207a96f4663..3e0d040e1cf1 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 @@ public class InputManagerService extends IInputManager.Stub @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 e8052289cca4..83b6ecae7780 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 @@ public class LocationManagerService extends ILocationManager.Stub { @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 @@ public class LocationManagerService extends ILocationManager.Stub { 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 63a42f845cee..dc1a26ae6fea 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.Context; 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 @@ public class ContextHubService extends IContextHubService.Stub { // 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 @@ public class ContextHubService extends IContextHubService.Stub { } }, 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 @@ public class ContextHubService extends IContextHubService.Stub { 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 4242d72239e2..c11e289c116b 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 class IContextHubWrapper { */ 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 @@ public abstract class IContextHubWrapper { return false; } + public boolean supportsMicrophoneDisableSettingNotifications() { + return false; + } + public void onLocationSettingChanged(boolean enabled) { } @@ -160,6 +176,9 @@ public abstract class IContextHubWrapper { public void onAirplaneModeSettingChanged(boolean enabled) { } + + public void onMicrophoneDisableSettingChanged(boolean enabled) { + } } private static class ContextHubWrapperV1_1 extends IContextHubWrapper { @@ -185,6 +204,10 @@ public abstract class IContextHubWrapper { return false; } + public boolean supportsMicrophoneDisableSettingNotifications() { + return false; + } + public void onLocationSettingChanged(boolean enabled) { try { mHub.onSettingChanged(Setting.LOCATION, @@ -199,6 +222,9 @@ public abstract class IContextHubWrapper { public void onAirplaneModeSettingChanged(boolean enabled) { } + + public void onMicrophoneDisableSettingChanged(boolean enabled) { + } } private static class ContextHubWrapperV1_2 extends IContextHubWrapper { @@ -224,6 +250,10 @@ public abstract class IContextHubWrapper { return true; } + public boolean supportsMicrophoneDisableSettingNotifications() { + return true; + } + public void onLocationSettingChanged(boolean enabled) { sendSettingChanged(Setting.LOCATION, enabled ? SettingValue.ENABLED : SettingValue.DISABLED); @@ -239,6 +269,11 @@ public abstract class IContextHubWrapper { 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 92957aaf2976..b6695c20bd97 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 @@ public class GnssManagerService { 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 b623e279d9ae..305bc9b69e39 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 @@ public final class GnssMeasurementsProvider extends @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 @@ public final class GnssMeasurementsProvider extends 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 402e84b959c6..7e2f089d32c9 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 @@ public class GnssNative { /** * 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 @@ public class GnssNative { 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 @@ public class GnssNative { 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 5d0544b33cd7..7dd961a6e4e4 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 @@ class LockSettingsStorage { 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 289290bab4dc..fbec91576ca1 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 @@ class RebootEscrowManager { 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 @@ class RebootEscrowManager { } 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 1b27ef4c6e1c..c0381e4b1715 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 @@ public class MediaSessionService extends SystemService implements Monitor { 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 @@ public class MediaSessionService extends SystemService implements Monitor { 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 @@ public class MediaSessionService extends SystemService implements Monitor { } } }, null /* handler */); - mContentResolver = mContext.getContentResolver(); mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_LEANBACK); @@ -831,6 +833,7 @@ public class MediaSessionService extends SystemService implements Monitor { */ 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 @@ public class MediaSessionService extends SystemService implements Monitor { 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 @@ public class MediaSessionService extends SystemService implements Monitor { 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 9c68349af7d5..2a3cc907d675 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 @@ package com.android.server.media.metrics; 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 @@ public final class PlaybackMetricsManagerService extends SystemService { 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 @@ public final class PlaybackMetricsManagerService extends SystemService { 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 ed7e5fbbea5c..61b218ce7196 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.AlarmManager; 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 @@ public class NotificationManagerService extends SystemService { 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 01eeb31dff2b..ef0f0eeb56f8 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.annotation.RequiresPermission; 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.ServiceManager; 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 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub { 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 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub { 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 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub { 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 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub { } @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 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub { } } + 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 608580cd9747..b65fc7358471 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { break; } case IDataLoaderStatusListener.DATA_LOADER_IMAGE_READY: { - synchronized (mLock) { - mDataLoaderFinished = true; - } + mDataLoaderFinished = true; if (hasParentSessionId()) { mSessionProvider.getSession( getParentSessionId()).dispatchSessionSealed(); @@ -3622,9 +3619,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { 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 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // 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 b95c5efca6d5..000000000000 --- 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 000000000000..097f332a2637 --- /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/LegacyRoleStateProvider.java index ed0d67563132..ec4cfc176a8d 100644 --- a/services/core/java/com/android/server/role/LegacyRoleHolderProvider.java +++ b/services/core/java/com/android/server/role/LegacyRoleStateProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * 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. @@ -19,22 +19,25 @@ package com.android.server.role; import android.annotation.NonNull; import android.annotation.UserIdInt; -import java.util.List; +import java.util.Map; +import java.util.Set; /** - * A provider for migrating legacy "role"s to their actual role implementation. + * 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 LegacyRoleHolderProvider { +public interface LegacyRoleStateProvider { /** - * 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. + * Get the legacy role state stored in the platform. * - * @param roleName the name of the role * @param userId the user ID - * @return a list of holders for the given role + * @return a mapping of role name to its set of holders */ @NonNull - List<String> getLegacyRoleHolders(@NonNull String roleName, @UserIdInt int userId); + 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 4e42f16b68bf..bc5ddd3aae95 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 @@ public class RoleManagerService extends SystemService implements RoleUserState.C 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 @@ public class RoleManagerService extends SystemService implements RoleUserState.C 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 @@ public class RoleManagerService extends SystemService implements RoleUserState.C 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 @@ public class RoleManagerService extends SystemService implements RoleUserState.C 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 @@ public class RoleManagerService extends SystemService implements RoleUserState.C 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 @@ public class RoleManagerService extends SystemService implements RoleUserState.C getContext().enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); } - if (mPackageManagerInternal.getInstantAppPackageName(callingUid) != null) { + if (isInstantApp(callingUid)) { return null; } @@ -676,6 +649,25 @@ public class RoleManagerService extends SystemService implements RoleUserState.C } } + 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 3a5ed5c6425f..f5a79eabaf5a 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.NonNull; 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.internal.util.function.pooled.PooledLambda; 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 @@ class RoleUserState { 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 @@ class RoleUserState { * 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 @@ class RoleUserState { private void readFile() { synchronized (mLock) { - RolesState roles = mPersistence.readForUser(UserHandle.of(mUserId)); - if (roles == null) { - readLegacyFileLocked(); - scheduleWriteFileLocked(); - return; - } - - mVersion = roles.getVersion(); - mPackagesHash = roles.getPackagesHash(); + 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); + } 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; - } - } - 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); + if (roleState == null) { + scheduleWriteFileLocked(); } } - - return roleHolders; } /** @@ -549,11 +461,6 @@ class RoleUserState { } } - @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 42f12eb23d39..07725038255e 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 @@ final class TvInputHal implements Handler.Callback { 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 @@ final class TvInputHal implements Handler.Callback { 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 @@ final class TvInputHal implements Handler.Callback { 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 @@ final class TvInputHal implements Handler.Callback { 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 a036bd196b23..38ae51fc2c1b 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 @@ class TvInputHardwareManager implements TvInputHal.Callback { 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 @@ class TvInputHardwareManager implements TvInputHal.Callback { } @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 @@ class TvInputHardwareManager implements TvInputHal.Callback { 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 @@ class TvInputHardwareManager implements TvInputHal.Callback { } 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 @@ class TvInputHardwareManager implements TvInputHal.Callback { 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 @@ class TvInputHardwareManager implements TvInputHal.Callback { + " }"; } + 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 @@ class TvInputHardwareManager implements TvInputHal.Callback { 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 ff5b65b61807..a1d2f8a927f7 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 @@ public final class TvInputManagerService extends SystemService { } @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 072bdd2d1506..988582da53ea 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.app.ActivityManager.RunningAppProcessInfo; 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.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; import android.media.tv.tunerresourcemanager.TunerResourceManager; @@ -578,7 +578,7 @@ public class TunerResourceManagerService extends SystemService implements IBinde } 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 a34a50737ec5..536375f1311d 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.provider.Settings; 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 @@ public final class VibrationSettings { 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 @@ public final class VibrationSettings { * 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 @@ public final class VibrationSettings { 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 @@ public final class VibrationSettings { } /** 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 03cf021d0e9b..6bca4843e009 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 @@ class ActivityMetricsLogger { 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 @@ class ActivityMetricsLogger { + " 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 a9c54741fcf6..0b5bd7a1b566 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; 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 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A 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 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A 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 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (options.getAnimationType() == ANIM_REMOTE_ANIMATION) { mPendingRemoteAnimation = options.getRemoteAnimationAdapter(); } + mPendingRemoteTransition = options.getRemoteTransition(); } void applyOptionsAnimation() { @@ -4064,6 +4070,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A void clearOptionsAnimation() { mPendingOptions = null; mPendingRemoteAnimation = null; + mPendingRemoteTransition = null; } ActivityOptions getOptions() { @@ -4078,6 +4085,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return opts; } + IRemoteTransition takeRemoteTransition() { + IRemoteTransition out = mPendingRemoteTransition; + mPendingRemoteTransition = null; + return out; + } + boolean allowMoveToFront() { return mPendingOptions == null || !mPendingOptions.getAvoidMoveToFront(); } @@ -6479,8 +6492,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mLastReportedConfiguration.setConfiguration(global, override); } - boolean hasCompatDisplayInsets() { - return mCompatDisplayInsets != null; + @Nullable + CompatDisplayInsets getCompatDisplayInsets() { + return mCompatDisplayInsets; } /** @@ -6569,7 +6583,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } 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 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A /** * 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 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A 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 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A 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 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A 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 20625c83a924..e67210e42cc8 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.ArraySet; 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 @@ class ActivityStarter { 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 @@ class ActivityStarter { } 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 599bf3748dd9..a68f55750c18 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 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { 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 fc8747d24abe..6d2b0bf4fb5c 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 @@ class Task extends WindowContainer<WindowContainer> { 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 @@ class Task extends WindowContainer<WindowContainer> { * {@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 @@ class Task extends WindowContainer<WindowContainer> { 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 @@ class Task extends WindowContainer<WindowContainer> { 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 @@ class Task extends WindowContainer<WindowContainer> { 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 9a83ac7ffe00..65247d0b9937 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 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { 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 b37e3c42f568..46aea23beaf6 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.util.Slog; 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 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe 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 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe 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 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe 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 0fe0afa54dd3..5f46ffe604a6 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.IBinder; 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 @@ class TransitionController { } /** - * @see #requestTransitionIfNeeded(int, int) + * @see #requestTransitionIfNeeded(int, int, WindowContainer, IRemoteTransition) */ @Nullable Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type, @@ -148,9 +150,19 @@ class TransitionController { 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 @@ class TransitionController { */ @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 @@ class TransitionController { 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 @@ class TransitionController { /** 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 @@ class TransitionController { 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 13c67523a7d6..dc15b0749bb1 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 @@ static struct { 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 35aad3e268ed..b2d6b15a4930 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_is_measurement_supported(JN } 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 @@ static jboolean android_location_gnss_hal_GnssNative_start_measurement_collectio 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 @@ static const JNINativeMethod sMeasurementMethods[] = { /* 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 631e185fffce..7b379e54a40e 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 MagicType INCR = 0x52434e49; // BE INCR 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 @@ private: 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 @@ private: 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 @@ private: 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 4e1a23416330..a5311f33eb36 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 @@ public: 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 @@ void JTvInputHal::onDeviceUnavailable(int deviceId) { 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 @@ void JTvInputHal::onStreamConfigurationsChanged(int deviceId) { 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 @@ void JTvInputHal::NotifyHandler::handleMessage(const Message& message) { 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 @@ int register_android_server_tv_TvInputHal(JNIEnv* env) { "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 2261c38fb185..663d839ff159 100644 --- a/services/core/jni/gnss/GnssMeasurement.cpp +++ b/services/core/jni/gnss/GnssMeasurement.cpp @@ -50,8 +50,9 @@ GnssMeasurement::GnssMeasurement(const sp<IGnssMeasurementInterface>& iGnssMeasu : 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 @@ GnssMeasurement_V1_0::GnssMeasurement_V1_0(const sp<IGnssMeasurement_V1_0>& iGns : 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_1::GnssMeasurement_V1_1(const sp<IGnssMeasurement_V1_1>& iGns : 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_V2_0::GnssMeasurement_V2_0(const sp<IGnssMeasurement_V2_0>& iGns : 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_1::GnssMeasurement_V2_1(const sp<IGnssMeasurement_V2_1>& iGns : 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 e64336fb67ac..f0752cd3ab5b 100644 --- a/services/core/jni/gnss/GnssMeasurement.h +++ b/services/core/jni/gnss/GnssMeasurement.h @@ -38,7 +38,7 @@ class GnssMeasurementInterface { 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 @@ class GnssMeasurement : public GnssMeasurementInterface { 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 8cba77328248..757381dff80a 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 @@ void GnssMeasurement_class_init_once(JNIEnv* env, jclass& clazz) { 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 @@ void GnssMeasurement_class_init_once(JNIEnv* env, jclass& clazz) { 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 @@ void GnssMeasurementCallbackAidl::translateSingleGnssMeasurement(JNIEnv* env, 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 4fe275250ddf..2975800f4cf1 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(); Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle)); + checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REMOVE_ACTIVE_ADMIN); enforceUserUnlocked(userHandle); synchronized (getLockObject()) { @@ -5143,6 +5144,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(who); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); checkAllUsersAreAffiliatedWithDevice(); + checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REQUEST_BUGREPORT); if (mBugreportCollectionManager.requestBugreport()) { DevicePolicyEventLogger @@ -7506,6 +7515,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (parent) { Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)); } + checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_CAMERA_DISABLED); final int userHandle = caller.getUserId(); synchronized (getLockObject()) { @@ -9256,6 +9266,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 94df1851aa87..57b3e8da8885 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.UserManagerService; 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 @@ public final class SystemServer implements Dumpable { // 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 16b9165915e2..091e688743dd 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 @@ public class PeopleService extends SystemService { 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 e4daddca4564..0a85f7fc3662 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 @@ abstract class AbstractProtoDiskReadWriter<T> { } @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 @@ abstract class AbstractProtoDiskReadWriter<T> { } /** - * 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 000000000000..c631026f4389 --- /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 28e3d4b5b744..6faeb8053621 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 @@ class ConversationStore { * 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 @@ class ConversationStore { * 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 @@ class ConversationStore { } @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 @@ class ConversationStore { } @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 @@ class ConversationStore { 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 @@ class ConversationStore { } } - @MainThread private synchronized void updateConversationsInMemory( @NonNull ConversationInfo conversationInfo) { mConversationInfoMap.put(conversationInfo.getShortcutId(), conversationInfo); @@ -273,12 +284,15 @@ class ConversationStore { /** 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 e04e287d80f6..752141598c9d 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 @@ public class DataManager { private PackageManagerInternal mPackageManagerInternal; private NotificationManagerInternal mNotificationManagerInternal; private UserManager mUserManager; + private ConversationStatusExpirationBroadcastReceiver mStatusExpReceiver; public DataManager(Context context) { this(context, new Injector()); @@ -145,6 +146,10 @@ public class DataManager { 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 @@ public class DataManager { } /** + * 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 @@ public class DataManager { 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 @@ public class DataManager { 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 000000000000..92835c2b0626 --- /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 6de3d4e160ec..23ed278e04ef 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 @@ class VerifyReceiverTest { 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 @@ class VerifyReceiverTest { 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 675274bf82c4..69fe140a7863 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 @@ public final class FakeGnssHal extends GnssNative.GnssHal { 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 @@ public final class FakeGnssHal extends GnssNative.GnssHal { } @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 @@ public final class FakeGnssHal extends GnssNative.GnssHal { 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 99aab5c7a6af..392535e8eea1 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 @@ public class Face10Test { } @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 b2aeb33039f5..61cc8e6e8ea3 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 @@ public class Fingerprint21Test { } @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 000000000000..0cf0af39dc1e --- /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 b7d9a56c9c76..a7b32ac5c387 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.provider.Settings; 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 @@ public class BackgroundRestrictionsTest { 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 be8a99c5ce36..63330d518297 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.doAnswer; 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 @@ public final class DataManagerTest { @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 @@ public final class DataManagerTest { private DataManager mDataManager; private CancellationSignal mCancellationSignal; private ShortcutChangeCallback mShortcutChangeCallback; - private BroadcastReceiver mShutdownBroadcastReceiver; private ShortcutInfo mShortcutInfo; private TestInjector mInjector; @@ -187,10 +189,15 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { 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 @@ public final class DataManagerTest { } @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 @@ public final class DataManagerTest { .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 385837009b2f..aadab6ea4fd9 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.content.ContextWrapper; 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.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; import android.media.tv.tunerresourcemanager.TunerResourceManager; @@ -88,7 +88,7 @@ public class TunerResourceManagerServiceTest { } 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 @@ public class TunerResourceManagerServiceTest { 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 7c65dc03a57e..b40d59c14b8d 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 @@ public class WatcherTest { 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 @@ public class WatcherTest { 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 @@ public class WatcherTest { 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 @@ public class WatcherTest { 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 @@ public class WatcherTest { 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 @@ public class WatcherTest { 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 ecdb8bc71bd8..1e112da8fe7c 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.verify; 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.media.AudioManager; 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 @@ public class VibrationSettingsTest { } @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 @@ public class VibrationSettingsTest { 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 f1dc098fccf6..6b69ee921c8b 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 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { } @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 e19024825b38..22430a110ca3 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.RESIZE_MODE_UNRESIZEABLE; 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.assertNotEquals; 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 @@ public class SizeCompatTests extends WindowTestsBase { // 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 @@ public class SizeCompatTests extends WindowTestsBase { // 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 @@ public class SizeCompatTests extends WindowTestsBase { // 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 @@ public class SizeCompatTests extends WindowTestsBase { 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 f1bea676ed20..04b365f4a5c7 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -109,6 +109,20 @@ import java.util.concurrent.ConcurrentHashMap; */ 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 000000000000..c7e7cd5ec64e --- /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 d01297147fdb..f6d18fcd9ab3 100644 --- a/telephony/java/android/telephony/AccessNetworkConstants.java +++ b/telephony/java/android/telephony/AccessNetworkConstants.java @@ -18,10 +18,7 @@ package android.telephony; 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 @@ public final class AccessNetworkConstants { * 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 @@ public final class AccessNetworkConstants { * 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 @@ public final class AccessNetworkConstants { * 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 final class AccessNetworkConstants { 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 final class AccessNetworkConstants { 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 final class AccessNetworkConstants { 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 @@ public final class AccessNetworkConstants { BAND_18, BAND_20, BAND_25, + BAND_26, BAND_28, BAND_29, BAND_30, @@ -398,9 +776,11 @@ public final class AccessNetworkConstants { 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 @@ public final class AccessNetworkConstants { BAND_93, BAND_94, BAND_95, + BAND_96, BAND_257, BAND_258, BAND_260, @@ -464,7 +845,8 @@ public final class AccessNetworkConstants { value = { FREQUENCY_RANGE_GROUP_UNKNOWN, FREQUENCY_RANGE_GROUP_1, - FREQUENCY_RANGE_GROUP_2}) + FREQUENCY_RANGE_GROUP_2 + }) public @interface FrequencyRangeGroup {} /** @@ -489,6 +871,7 @@ public final class AccessNetworkConstants { 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 @@ public final class AccessNetworkConstants { 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 @@ public final class AccessNetworkConstants { 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 @@ public final class AccessNetworkConstants { 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 7661a32f6d5b..f29f3bd352be 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_FDD; 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 @@ public class AccessNetworkUtils { 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 @@ public class AccessNetworkUtils { } 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 7e019ccde372..426da52ea68e 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -3591,6 +3591,28 @@ public class CarrierConfigManager { */ 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 class CarrierConfigManager { */ 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 @@ public class CarrierConfigManager { 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 @@ public class CarrierConfigManager { 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 ed09d538a3b1..1273aa3abbc9 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -478,7 +478,9 @@ public class PhoneNumberUtils { /** * 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 @@ public class PhoneNumberUtils { * 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 @@ public class PhoneNumberUtils { } // 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 @@ public class PhoneNumberUtils { } 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 95c69ba470c4..b359ebed2683 100644 --- a/telephony/java/android/telephony/PhysicalChannelConfig.java +++ b/telephony/java/android/telephony/PhysicalChannelConfig.java @@ -19,7 +19,6 @@ package android.telephony; 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 @@ public final class PhysicalChannelConfig implements Parcelable { /** 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 @@ public final class PhysicalChannelConfig implements Parcelable { 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 @@ public final class PhysicalChannelConfig implements Parcelable { private int mFrequencyRange; /** - * The absolute radio frequency channel number, {@link #CHANNEL_NUMBER_UNKNOWN} if unknown. + * The frequency of Downlink. + */ + 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 mChannelNumber; + private int mUplinkChannelNumber; /** * A list of data calls mapped to this physical channel. An empty list means the physical @@ -98,6 +129,11 @@ public final class PhysicalChannelConfig implements Parcelable { */ 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 final class PhysicalChannelConfig implements Parcelable { 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 @@ public final class PhysicalChannelConfig implements Parcelable { } /** - * @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 @@ public final class PhysicalChannelConfig implements Parcelable { } /** - * @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 @@ public final class PhysicalChannelConfig implements Parcelable { 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 @@ public final class PhysicalChannelConfig implements Parcelable { * @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 @@ public final class PhysicalChannelConfig implements Parcelable { } } + 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 @@ public final class PhysicalChannelConfig implements Parcelable { 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 @@ public final class PhysicalChannelConfig implements Parcelable { .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 @@ public final class PhysicalChannelConfig implements Parcelable { * @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 dedb1afa2495..f110daecd952 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -2111,4 +2111,23 @@ public class ServiceState implements Parcelable { } 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 f6f6d75c37c6..bb9c0da3f8d4 100644 --- a/telephony/java/android/telephony/SignalThresholdInfo.java +++ b/telephony/java/android/telephony/SignalThresholdInfo.java @@ -28,101 +28,109 @@ import java.util.Objects; /** * 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 @@ public class SignalThresholdInfo implements Parcelable { * 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 - */ - public SignalThresholdInfo(@SignalMeasurementType int signalMeasurement, - int hysteresisMs, int hysteresisDb, @NonNull int [] thresholds, boolean isEnabled) { - mSignalMeasurement = signalMeasurement; + * @param ran Radio Access Network type + * @param signalMeasurementType Signal Measurement Type + * @param hysteresisMs hysteresisMs + * @param hysteresisDb hysteresisDb + * @param thresholds threshold value + * @param isEnabled isEnabled + */ + 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 @@ public class SignalThresholdInfo implements Parcelable { } @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 @@ public class SignalThresholdInfo implements Parcelable { } 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 @@ public class SignalThresholdInfo implements Parcelable { } 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 @@ public class SignalThresholdInfo implements Parcelable { @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 @@ public class SignalThresholdInfo implements Parcelable { @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 bfd37cd60806..2f577a99028e 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -131,10 +131,12 @@ import java.nio.file.Path; 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 @@ public class TelephonyManager { /** * 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 class TelephonyManager { */ 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 @@ public class TelephonyManager { ERROR_AUTHENTICATION_FAILED, ERROR_INPUT_CLOSED, ERROR_IO_EXCEPTION, + ERROR_NETWORK_UNAVAILABLE, }) + @Retention(RetentionPolicy.SOURCE) public @interface CallComposerError {} @@ -4355,14 +4369,16 @@ public class TelephonyManager { /** * 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 @@ public class TelephonyManager { } 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 @@ public class TelephonyManager { * 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 @@ public class TelephonyManager { 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 class TelephonyManager { */ 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 @@ public class TelephonyManager { * 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 @@ public class TelephonyManager { */ @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 @@ public class TelephonyManager { * * @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 @@ public class TelephonyManager { 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 34120790b25a..a5150b010f57 100644 --- a/telephony/java/android/telephony/euicc/DownloadableSubscription.java +++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.java @@ -121,25 +121,21 @@ public final class DownloadableSubscription implements Parcelable { } 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 @@ public final class DownloadableSubscription implements Parcelable { */ @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 66281edc0de1..fd206c1e803f 100644 --- a/telephony/java/android/telephony/ims/DelegateRegistrationState.java +++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.java @@ -320,4 +320,11 @@ public final class DelegateRegistrationState implements Parcelable { 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 1539224dedcf..006cca84e44b 100644 --- a/telephony/java/android/telephony/ims/SipMessage.java +++ b/telephony/java/android/telephony/ims/SipMessage.java @@ -22,6 +22,8 @@ import android.os.Build; 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 @@ public final class SipMessage implements Parcelable { // 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 @@ public final class SipMessage implements Parcelable { 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 @@ public final class SipMessage implements Parcelable { } 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 522ad8160870..9d919015087d 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.SipDelegateImsConfiguration; 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 @@ import java.util.concurrent.Executor; * @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 @@ public class SipDelegateAidlWrapper implements DelegateStateCallback, DelegateMe } 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 a35039bd7668..c877aca8ba96 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.SipMessage; 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 @@ public class SipDelegateConnectionAidlWrapper implements SipDelegateConnection, } 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 d2cb9761a028..d9734a7475c0 100644 --- a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java +++ b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java @@ -18,15 +18,12 @@ package android.telephony.ims.stub; 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 @@ public interface CapabilityExchangeEventListener { * 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 83fb38be820d..46c9dde6023e 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -1262,7 +1262,7 @@ interface ITelephony { 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 9a2def935f5d..1a940c75cfa4 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 b53b78a8d5b2..8be3b7e35d42 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.graphics.Shader; 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 @@ public class ColorFiltersMutateActivity extends Activity { 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 @@ public class ColorFiltersMutateActivity extends Activity { + " return half4(sample(bitmapShader, xy).rgb, param1);\n" + "}\n"; - private byte[] mUniforms = new byte[4]; - BitmapsView(Context c) { super(c); @@ -86,11 +83,13 @@ public class ColorFiltersMutateActivity extends Activity { 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 class ColorFiltersMutateActivity extends Activity { } 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 000000000000..f6d9a7301949 --- /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 d825dfd7cf00..aac68e994a39 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 8710d23730b6..2cb16d3372d7 100644 --- a/tests/net/common/java/android/net/CaptivePortalDataTest.kt +++ b/tests/net/common/java/android/net/CaptivePortalDataTest.kt @@ -18,12 +18,15 @@ package android.net 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 @@ import kotlin.test.assertNotEquals @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 @@ class CaptivePortalDataTest { .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 @@ class CaptivePortalDataTest { 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 @@ class CaptivePortalDataTest { 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 6953100dd2ac..f3a3c01cd880 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.HashSet; 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 @@ public class ConnectivityServiceTest { 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 class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { } // 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 @@ public class ConnectivityServiceTest { @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 @@ public class ConnectivityServiceTest { } /** - * 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 @@ public class ConnectivityServiceTest { // 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 @@ public class ConnectivityServiceTest { 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(); - - // 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(); - }); + b.expectNoBroadcast(800); // 800ms long enough to at least flake if this is sent + + // 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 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { 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 class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { 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 class ConnectivityServiceTest { 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 class ConnectivityServiceTest { 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 class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { 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 class ConnectivityServiceTest { 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 class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { // 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 class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { } 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 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { @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 @@ public class ConnectivityServiceTest { 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 @@ public class ConnectivityServiceTest { // 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 @@ public class ConnectivityServiceTest { // 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 @@ public class ConnectivityServiceTest { // 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 @@ public class ConnectivityServiceTest { // 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 @@ public class ConnectivityServiceTest { // 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 @@ public class ConnectivityServiceTest { // 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 @@ public class ConnectivityServiceTest { // 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 @@ public class ConnectivityServiceTest { // 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 @@ public class ConnectivityServiceTest { // 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 @@ public class ConnectivityServiceTest { // 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 @@ public class ConnectivityServiceTest { .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 @@ public class ConnectivityServiceTest { mCm.registerNetworkCallback(genericRequest, genericNetworkCallback); mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); + waitForIdle(); final ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById(); @@ -8466,4 +8491,20 @@ public class ConnectivityServiceTest { 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 000000000000..31561901be9e --- /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)); + } +} |