Merge changes from topic "oct5b"
* changes:
Detector to suggest more efficient collections.
Detector for Binder.clearCallingIdentity() bugs.
diff --git a/Android.bp b/Android.bp
index 5af7756..4121b8a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -598,6 +598,12 @@
"//frameworks/base/apex/jobscheduler/framework",
"//frameworks/base/packages/Tethering/tests/unit",
],
+ errorprone: {
+ javacflags: [
+ "-Xep:AndroidFrameworkCompatChange:ERROR",
+ "-Xep:AndroidFrameworkUid:ERROR",
+ ],
+ },
}
// This "framework" module is NOT installed to the device. It's
diff --git a/StubLibraries.bp b/StubLibraries.bp
index a3a2094..53053ce 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -58,7 +58,24 @@
"media/aidl",
],
},
- libs: ["framework-internal-utils"],
+ // These are libs from framework-internal-utils that are required (i.e. being referenced)
+ // from framework-non-updatable-sources. Add more here when there's a need.
+ // DO NOT add the entire framework-internal-utils. It might cause unnecessary circular
+ // dependencies gets bigger.
+ libs: [
+ "android.hardware.cas-V1.2-java",
+ "android.hardware.health-V1.0-java-constants",
+ "android.hardware.radio-V1.5-java",
+ "android.hardware.thermal-V1.0-java-constants",
+ "android.hardware.thermal-V2.0-java",
+ "android.hardware.tv.input-V1.0-java-constants",
+ "android.hardware.tv.tuner-V1.0-java-constants",
+ "android.hardware.usb-V1.0-java-constants",
+ "android.hardware.usb-V1.1-java-constants",
+ "android.hardware.usb.gadget-V1.0-java",
+ "android.hardware.vibrator-V1.3-java",
+ "framework-protos",
+ ],
installable: false,
annotations_enabled: true,
previous_api: ":android.api.public.latest",
@@ -143,6 +160,11 @@
api_file: "non-updatable-api/current.txt",
removed_api_file: "non-updatable-api/removed.txt",
},
+ last_released: {
+ api_file: ":android-non-updatable.api.public.latest",
+ removed_api_file: ":android-non-updatable-removed.api.public.latest",
+ baseline_file: ":public-api-incompatibilities-with-last-released",
+ },
api_lint: {
enabled: true,
new_since: ":android-non-updatable.api.public.latest",
@@ -205,6 +227,11 @@
api_file: "non-updatable-api/system-current.txt",
removed_api_file: "non-updatable-api/system-removed.txt",
},
+ last_released: {
+ api_file: ":android-non-updatable.api.system.latest",
+ removed_api_file: ":android-non-updatable-removed.api.system.latest",
+ baseline_file: ":system-api-incompatibilities-with-last-released"
+ },
api_lint: {
enabled: true,
new_since: ":android-non-updatable.api.system.latest",
diff --git a/apct-tests/perftests/core/src/android/text/CanvasDrawTextTest.java b/apct-tests/perftests/core/src/android/text/CanvasDrawTextTest.java
index bb6b691..66b2b0e 100644
--- a/apct-tests/perftests/core/src/android/text/CanvasDrawTextTest.java
+++ b/apct-tests/perftests/core/src/android/text/CanvasDrawTextTest.java
@@ -53,19 +53,19 @@
final String text = mTextUtil.nextRandomParagraph(
WORD_LENGTH, 4 * 1024 * 1024 /* 4mb text */).toString();
final RenderNode node = RenderNode.create("benchmark", null);
- final RenderNode child = RenderNode.create("child", null);
- child.setLeftTopRightBottom(50, 50, 100, 100);
-
- RecordingCanvas canvas = node.start(100, 100);
- node.end(canvas);
- canvas = child.start(50, 50);
- child.end(canvas);
final Random r = new Random(0);
-
while (state.keepRunning()) {
+ state.pauseTiming();
+ RecordingCanvas canvas = node.beginRecording();
int start = r.nextInt(text.length() - 100);
+ state.resumeTiming();
+
canvas.drawText(text, start, start + 100, 0, 0, PAINT);
+
+ state.pauseTiming();
+ node.endRecording();
+ state.resumeTiming();
}
}
}
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
index efcabd8..833cc0f 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
@@ -226,7 +226,7 @@
mMeasuredTimeNs = 0;
final long startTime = SystemClock.elapsedRealtimeNanos();
- atm.startRecentsActivity(sRecentsIntent, null /* unused */, anim);
+ atm.startRecentsActivity(sRecentsIntent, 0 /* eventTime */, anim);
final long elapsedTimeNsOfStart = SystemClock.elapsedRealtimeNanos() - startTime;
mMeasuredTimeNs += elapsedTimeNsOfStart;
state.addExtraResult("start", elapsedTimeNsOfStart);
diff --git a/apex/media/framework/api/module-lib-current.txt b/apex/media/framework/api/module-lib-current.txt
index d2826d0..2b69863 100644
--- a/apex/media/framework/api/module-lib-current.txt
+++ b/apex/media/framework/api/module-lib-current.txt
@@ -1,14 +1,14 @@
// Signature format: 2.0
package android.media {
- public final class MediaParceledListSlice<T extends android.os.Parcelable> implements android.os.Parcelable {
- ctor public MediaParceledListSlice(@NonNull java.util.List<T>);
- method public int describeContents();
- method @NonNull public static <T extends android.os.Parcelable> android.media.MediaParceledListSlice<T> emptyList();
- method public java.util.List<T> getList();
- method public void setInlineCountLimit(int);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.ClassLoaderCreator<android.media.MediaParceledListSlice> CREATOR;
+ @Deprecated public final class MediaParceledListSlice<T extends android.os.Parcelable> implements android.os.Parcelable {
+ ctor @Deprecated public MediaParceledListSlice(@NonNull java.util.List<T>);
+ method @Deprecated public int describeContents();
+ method @Deprecated @NonNull public static <T extends android.os.Parcelable> android.media.MediaParceledListSlice<T> emptyList();
+ method @Deprecated public java.util.List<T> getList();
+ method @Deprecated public void setInlineCountLimit(int);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.ClassLoaderCreator<android.media.MediaParceledListSlice> CREATOR;
}
}
diff --git a/apex/media/framework/java/android/media/MediaParceledListSlice.java b/apex/media/framework/java/android/media/MediaParceledListSlice.java
index e1223f6..47ac193 100644
--- a/apex/media/framework/java/android/media/MediaParceledListSlice.java
+++ b/apex/media/framework/java/android/media/MediaParceledListSlice.java
@@ -17,7 +17,6 @@
package android.media;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,13 +31,16 @@
* Transfer a large list of Parcelable objects across an IPC. Splits into
* multiple transactions if needed.
*
- * @see BaseMediaParceledListSlice
- *
* TODO: Remove this from @SystemApi once all the MediaSession related classes are moved
* to apex (or ParceledListSlice moved to apex). This class is temporaily added to system API
* for moving classes step by step.
+ *
+ * @param <T> The type of the elements in the list.
+ * @see BaseMediaParceledListSlice
+ * @deprecated This is temporary marked as @SystemApi. Should be removed from the API surface.
* @hide
*/
+@Deprecated
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class MediaParceledListSlice<T extends Parcelable>
extends BaseMediaParceledListSlice<T> {
diff --git a/api/Android.bp b/api/Android.bp
index 490c980..e403082 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -64,6 +64,24 @@
}
genrule {
+ name: "frameworks-base-api-removed-merged.txt",
+ srcs: [
+ ":conscrypt.module.public.api{.public.removed-api.txt}",
+ ":framework-media{.public.removed-api.txt}",
+ ":framework-mediaprovider{.public.removed-api.txt}",
+ ":framework-permission{.public.removed-api.txt}",
+ ":framework-sdkextensions{.public.removed-api.txt}",
+ ":framework-statsd{.public.removed-api.txt}",
+ ":framework-tethering{.public.removed-api.txt}",
+ ":framework-wifi{.public.removed-api.txt}",
+ ":non-updatable-removed.txt",
+ ],
+ out: ["removed.txt"],
+ tools: ["metalava"],
+ cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+}
+
+genrule {
name: "frameworks-base-api-system-current-merged.txt",
srcs: [
":framework-graphics{.system.api.txt}",
@@ -82,6 +100,23 @@
}
genrule {
+ name: "frameworks-base-api-system-removed-merged.txt",
+ srcs: [
+ ":framework-media{.system.removed-api.txt}",
+ ":framework-mediaprovider{.system.removed-api.txt}",
+ ":framework-permission{.system.removed-api.txt}",
+ ":framework-sdkextensions{.system.removed-api.txt}",
+ ":framework-statsd{.system.removed-api.txt}",
+ ":framework-tethering{.system.removed-api.txt}",
+ ":framework-wifi{.system.removed-api.txt}",
+ ":non-updatable-system-removed.txt",
+ ],
+ out: ["system-removed.txt"],
+ tools: ["metalava"],
+ cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+}
+
+genrule {
name: "frameworks-base-api-module-lib-current-merged.txt",
srcs: [
":framework-graphics{.module-lib.api.txt}",
@@ -98,3 +133,20 @@
tools: ["metalava"],
cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
}
+
+genrule {
+ name: "frameworks-base-api-module-lib-removed-merged.txt",
+ srcs: [
+ ":framework-media{.module-lib.removed-api.txt}",
+ ":framework-mediaprovider{.module-lib.removed-api.txt}",
+ ":framework-permission{.module-lib.removed-api.txt}",
+ ":framework-sdkextensions{.module-lib.removed-api.txt}",
+ ":framework-statsd{.module-lib.removed-api.txt}",
+ ":framework-tethering{.module-lib.removed-api.txt}",
+ ":framework-wifi{.module-lib.removed-api.txt}",
+ ":non-updatable-module-lib-removed.txt",
+ ],
+ out: ["module-lib-removed.txt"],
+ tools: ["metalava"],
+ cmd: "$(location metalava) --no-banner --format=v2 $(in) --api $(out)",
+}
diff --git a/api/current.txt b/api/current.txt
index 09a65c3..94e90a7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -646,10 +646,10 @@
field public static final int font = 16844082; // 0x1010532
field public static final int fontFamily = 16843692; // 0x10103ac
field public static final int fontFeatureSettings = 16843959; // 0x10104b7
- field public static final int fontProviderAuthority = 16844112; // 0x1010550
- field public static final int fontProviderCerts = 16844125; // 0x101055d
- field public static final int fontProviderPackage = 16844119; // 0x1010557
- field public static final int fontProviderQuery = 16844113; // 0x1010551
+ field @Deprecated public static final int fontProviderAuthority = 16844112; // 0x1010550
+ field @Deprecated public static final int fontProviderCerts = 16844125; // 0x101055d
+ field @Deprecated public static final int fontProviderPackage = 16844119; // 0x1010557
+ field @Deprecated public static final int fontProviderQuery = 16844113; // 0x1010551
field public static final int fontStyle = 16844095; // 0x101053f
field public static final int fontVariationSettings = 16844144; // 0x1010570
field public static final int fontWeight = 16844083; // 0x1010533
@@ -36675,7 +36675,7 @@
method public int dataCapacity();
method public int dataPosition();
method public int dataSize();
- method public void enforceInterface(String);
+ method public void enforceInterface(@NonNull String);
method public boolean hasFileDescriptors();
method public byte[] marshall();
method @NonNull public static android.os.Parcel obtain();
@@ -36746,7 +36746,7 @@
method public void writeFloatArray(@Nullable float[]);
method public void writeInt(int);
method public void writeIntArray(@Nullable int[]);
- method public void writeInterfaceToken(String);
+ method public void writeInterfaceToken(@NonNull String);
method public void writeList(@Nullable java.util.List);
method public void writeLong(long);
method public void writeLongArray(@Nullable long[]);
@@ -40190,62 +40190,62 @@
method public final int update(android.net.Uri, android.content.ContentValues, String, String[]);
}
- public final class FontRequest {
- ctor public FontRequest(@NonNull String, @NonNull String, @NonNull String);
- ctor public FontRequest(@NonNull String, @NonNull String, @NonNull String, @NonNull java.util.List<java.util.List<byte[]>>);
- method public java.util.List<java.util.List<byte[]>> getCertificates();
- method public String getProviderAuthority();
- method public String getProviderPackage();
- method public String getQuery();
+ @Deprecated public final class FontRequest {
+ ctor @Deprecated public FontRequest(@NonNull String, @NonNull String, @NonNull String);
+ ctor @Deprecated public FontRequest(@NonNull String, @NonNull String, @NonNull String, @NonNull java.util.List<java.util.List<byte[]>>);
+ method @Deprecated public java.util.List<java.util.List<byte[]>> getCertificates();
+ method @Deprecated public String getProviderAuthority();
+ method @Deprecated public String getProviderPackage();
+ method @Deprecated public String getQuery();
}
- public class FontsContract {
- method public static android.graphics.Typeface buildTypeface(@NonNull android.content.Context, @Nullable android.os.CancellationSignal, @NonNull android.provider.FontsContract.FontInfo[]);
- method @NonNull public static android.provider.FontsContract.FontFamilyResult fetchFonts(@NonNull android.content.Context, @Nullable android.os.CancellationSignal, @NonNull android.provider.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
- method public static void requestFonts(@NonNull android.content.Context, @NonNull android.provider.FontRequest, @NonNull android.os.Handler, @Nullable android.os.CancellationSignal, @NonNull android.provider.FontsContract.FontRequestCallback);
+ @Deprecated public class FontsContract {
+ method @Deprecated public static android.graphics.Typeface buildTypeface(@NonNull android.content.Context, @Nullable android.os.CancellationSignal, @NonNull android.provider.FontsContract.FontInfo[]);
+ method @Deprecated @NonNull public static android.provider.FontsContract.FontFamilyResult fetchFonts(@NonNull android.content.Context, @Nullable android.os.CancellationSignal, @NonNull android.provider.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @Deprecated public static void requestFonts(@NonNull android.content.Context, @NonNull android.provider.FontRequest, @NonNull android.os.Handler, @Nullable android.os.CancellationSignal, @NonNull android.provider.FontsContract.FontRequestCallback);
}
- public static final class FontsContract.Columns implements android.provider.BaseColumns {
- field public static final String FILE_ID = "file_id";
- field public static final String ITALIC = "font_italic";
- field public static final String RESULT_CODE = "result_code";
- field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
- field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
- field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
- field public static final int RESULT_CODE_OK = 0; // 0x0
- field public static final String TTC_INDEX = "font_ttc_index";
- field public static final String VARIATION_SETTINGS = "font_variation_settings";
- field public static final String WEIGHT = "font_weight";
+ @Deprecated public static final class FontsContract.Columns implements android.provider.BaseColumns {
+ field @Deprecated public static final String FILE_ID = "file_id";
+ field @Deprecated public static final String ITALIC = "font_italic";
+ field @Deprecated public static final String RESULT_CODE = "result_code";
+ field @Deprecated public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
+ field @Deprecated public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
+ field @Deprecated public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
+ field @Deprecated public static final int RESULT_CODE_OK = 0; // 0x0
+ field @Deprecated public static final String TTC_INDEX = "font_ttc_index";
+ field @Deprecated public static final String VARIATION_SETTINGS = "font_variation_settings";
+ field @Deprecated public static final String WEIGHT = "font_weight";
}
- public static class FontsContract.FontFamilyResult {
- method @NonNull public android.provider.FontsContract.FontInfo[] getFonts();
- method public int getStatusCode();
- field public static final int STATUS_OK = 0; // 0x0
- field public static final int STATUS_REJECTED = 3; // 0x3
- field public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; // 0x2
- field public static final int STATUS_WRONG_CERTIFICATES = 1; // 0x1
+ @Deprecated public static class FontsContract.FontFamilyResult {
+ method @Deprecated @NonNull public android.provider.FontsContract.FontInfo[] getFonts();
+ method @Deprecated public int getStatusCode();
+ field @Deprecated public static final int STATUS_OK = 0; // 0x0
+ field @Deprecated public static final int STATUS_REJECTED = 3; // 0x3
+ field @Deprecated public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; // 0x2
+ field @Deprecated public static final int STATUS_WRONG_CERTIFICATES = 1; // 0x1
}
- public static class FontsContract.FontInfo {
- method @Nullable public android.graphics.fonts.FontVariationAxis[] getAxes();
- method public int getResultCode();
- method @IntRange(from=0) public int getTtcIndex();
- method @NonNull public android.net.Uri getUri();
- method @IntRange(from=1, to=1000) public int getWeight();
- method public boolean isItalic();
+ @Deprecated public static class FontsContract.FontInfo {
+ method @Deprecated @Nullable public android.graphics.fonts.FontVariationAxis[] getAxes();
+ method @Deprecated public int getResultCode();
+ method @Deprecated @IntRange(from=0) public int getTtcIndex();
+ method @Deprecated @NonNull public android.net.Uri getUri();
+ method @Deprecated @IntRange(from=1, to=1000) public int getWeight();
+ method @Deprecated public boolean isItalic();
}
- public static class FontsContract.FontRequestCallback {
- ctor public FontsContract.FontRequestCallback();
- method public void onTypefaceRequestFailed(int);
- method public void onTypefaceRetrieved(android.graphics.Typeface);
- field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
- field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
- field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
- field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
- field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
- field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
+ @Deprecated public static class FontsContract.FontRequestCallback {
+ ctor @Deprecated public FontsContract.FontRequestCallback();
+ method @Deprecated public void onTypefaceRequestFailed(int);
+ method @Deprecated public void onTypefaceRetrieved(android.graphics.Typeface);
+ field @Deprecated public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+ field @Deprecated public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+ field @Deprecated public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+ field @Deprecated public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+ field @Deprecated public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+ field @Deprecated public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
}
@Deprecated public final class LiveFolders implements android.provider.BaseColumns {
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index 4a7c121..19f348c 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -19,7 +19,7 @@
package android.app.role {
public final class RoleManager {
- method @Nullable public String getDefaultSmsPackage(int);
+ method @Nullable public String getSmsRoleHolder(int);
}
}
@@ -53,14 +53,14 @@
field public static final int FLAG_FROM_KEY = 4096; // 0x1000
}
- public final class MediaParceledListSlice<T extends android.os.Parcelable> implements android.os.Parcelable {
- ctor public MediaParceledListSlice(@NonNull java.util.List<T>);
- method public int describeContents();
- method @NonNull public static <T extends android.os.Parcelable> android.media.MediaParceledListSlice<T> emptyList();
- method public java.util.List<T> getList();
- method public void setInlineCountLimit(int);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.ClassLoaderCreator<android.media.MediaParceledListSlice> CREATOR;
+ @Deprecated public final class MediaParceledListSlice<T extends android.os.Parcelable> implements android.os.Parcelable {
+ ctor @Deprecated public MediaParceledListSlice(@NonNull java.util.List<T>);
+ method @Deprecated public int describeContents();
+ method @Deprecated @NonNull public static <T extends android.os.Parcelable> android.media.MediaParceledListSlice<T> emptyList();
+ method @Deprecated public java.util.List<T> getList();
+ method @Deprecated public void setInlineCountLimit(int);
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.ClassLoaderCreator<android.media.MediaParceledListSlice> CREATOR;
}
}
diff --git a/api/system-current.txt b/api/system-current.txt
index aa9536e..f2ec297 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -95,6 +95,7 @@
field public static final String INJECT_EVENTS = "android.permission.INJECT_EVENTS";
field public static final String INSTALL_DYNAMIC_SYSTEM = "android.permission.INSTALL_DYNAMIC_SYSTEM";
field public static final String INSTALL_GRANT_RUNTIME_PERMISSIONS = "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS";
+ field public static final String INSTALL_LOCATION_TIME_ZONE_PROVIDER = "android.permission.INSTALL_LOCATION_TIME_ZONE_PROVIDER";
field public static final String INSTALL_PACKAGE_UPDATES = "android.permission.INSTALL_PACKAGE_UPDATES";
field public static final String INSTALL_SELF_UPDATES = "android.permission.INSTALL_SELF_UPDATES";
field public static final String INTENT_FILTER_VERIFICATION_AGENT = "android.permission.INTENT_FILTER_VERIFICATION_AGENT";
@@ -125,6 +126,7 @@
field public static final String MANAGE_SENSOR_PRIVACY = "android.permission.MANAGE_SENSOR_PRIVACY";
field public static final String MANAGE_SOUND_TRIGGER = "android.permission.MANAGE_SOUND_TRIGGER";
field public static final String MANAGE_SUBSCRIPTION_PLANS = "android.permission.MANAGE_SUBSCRIPTION_PLANS";
+ field public static final String MANAGE_TIME_AND_ZONE_DETECTION = "android.permission.MANAGE_TIME_AND_ZONE_DETECTION";
field public static final String MANAGE_USB = "android.permission.MANAGE_USB";
field public static final String MANAGE_USERS = "android.permission.MANAGE_USERS";
field public static final String MANAGE_USER_OEM_UNLOCK_STATE = "android.permission.MANAGE_USER_OEM_UNLOCK_STATE";
@@ -305,6 +307,7 @@
field public static final int config_helpPackageNameValue = 17039388; // 0x104001c
field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
field public static final int config_systemGallery = 17039399; // 0x1040027
+ field public static final int config_systemVideoCall = 17039401; // 0x1040029
}
public static final class R.style {
@@ -1389,6 +1392,57 @@
}
+package android.app.time {
+
+ public final class TimeManager {
+ method @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public void addTimeZoneDetectorListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.time.TimeManager.TimeZoneDetectorListener);
+ method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public android.app.time.TimeZoneCapabilitiesAndConfig getTimeZoneCapabilitiesAndConfig();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public void removeTimeZoneDetectorListener(@NonNull android.app.time.TimeManager.TimeZoneDetectorListener);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public boolean updateTimeZoneConfiguration(@NonNull android.app.time.TimeZoneConfiguration);
+ }
+
+ @java.lang.FunctionalInterface public static interface TimeManager.TimeZoneDetectorListener {
+ method public void onChange();
+ }
+
+ public final class TimeZoneCapabilities implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getConfigureAutoDetectionEnabledCapability();
+ method public int getConfigureGeoDetectionEnabledCapability();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CAPABILITY_NOT_ALLOWED = 20; // 0x14
+ field public static final int CAPABILITY_NOT_APPLICABLE = 30; // 0x1e
+ field public static final int CAPABILITY_NOT_SUPPORTED = 10; // 0xa
+ field public static final int CAPABILITY_POSSESSED = 40; // 0x28
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.time.TimeZoneCapabilities> CREATOR;
+ }
+
+ public final class TimeZoneCapabilitiesAndConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.app.time.TimeZoneCapabilities getCapabilities();
+ method @NonNull public android.app.time.TimeZoneConfiguration getConfiguration();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.time.TimeZoneCapabilitiesAndConfig> CREATOR;
+ }
+
+ public final class TimeZoneConfiguration implements android.os.Parcelable {
+ method public int describeContents();
+ method public boolean isAutoDetectionEnabled();
+ method public boolean isGeoDetectionEnabled();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.time.TimeZoneConfiguration> CREATOR;
+ }
+
+ public static final class TimeZoneConfiguration.Builder {
+ ctor public TimeZoneConfiguration.Builder();
+ ctor public TimeZoneConfiguration.Builder(@NonNull android.app.time.TimeZoneConfiguration);
+ method @NonNull public android.app.time.TimeZoneConfiguration build();
+ method @NonNull public android.app.time.TimeZoneConfiguration.Builder setAutoDetectionEnabled(boolean);
+ method @NonNull public android.app.time.TimeZoneConfiguration.Builder setGeoDetectionEnabled(boolean);
+ }
+
+}
+
package android.app.usage {
public final class CacheQuotaHint implements android.os.Parcelable {
@@ -11412,6 +11466,7 @@
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<java.lang.String> getEquivalentHomePlmns();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
diff --git a/api/test-current.txt b/api/test-current.txt
index 0540054..576cbacb 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -45,6 +45,7 @@
field public static final int config_defaultDialer = 17039395; // 0x1040023
field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
field public static final int config_systemGallery = 17039399; // 0x1040027
+ field public static final int config_systemVideoCall = 17039401; // 0x1040029
}
}
@@ -767,10 +768,10 @@
method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void addRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean addRoleHolderFromController(@NonNull String, @NonNull String);
method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void clearRoleHoldersAsUser(@NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
- method @Nullable public String getDefaultSmsPackage(int);
method @NonNull @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public java.util.List<java.lang.String> getHeldRolesFromController(@NonNull String);
method @NonNull @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public java.util.List<java.lang.String> getRoleHolders(@NonNull String);
method @NonNull @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public java.util.List<java.lang.String> getRoleHoldersAsUser(@NonNull String, @NonNull android.os.UserHandle);
+ method @Nullable public String getSmsRoleHolder(int);
method @RequiresPermission("android.permission.OBSERVE_ROLE_HOLDERS") public void removeOnRoleHoldersChangedListenerAsUser(@NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
method @RequiresPermission("android.permission.MANAGE_ROLE_HOLDERS") public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean removeRoleHolderFromController(@NonNull String, @NonNull String);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 42b560d..bda9e24 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -3777,6 +3777,7 @@
LAUNCHER = 1;
NOTIFICATION = 2;
LOCKSCREEN = 3;
+ RECENTS_ANIMATION = 4;
}
// The type of the startup source.
optional SourceType source_type = 16;
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 3dbb6ed..a8ef54a 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include "guardrail/StatsdStats.h"
+#include "metrics/parsing_utils/metrics_manager_util.h"
#include "stats_log_util.h"
#include "stats_util.h"
@@ -122,6 +123,47 @@
VLOG("~CountMetricProducer() called");
}
+bool CountMetricProducer::onConfigUpdatedLocked(
+ const StatsdConfig& config, const int configIndex, const int metricIndex,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const sp<EventMatcherWizard>& matcherWizard,
+ const vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& conditionTrackerMap, const sp<ConditionWizard>& wizard,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation) {
+ if (!MetricProducer::onConfigUpdatedLocked(
+ config, configIndex, metricIndex, allAtomMatchingTrackers,
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, matcherWizard,
+ allConditionTrackers, conditionTrackerMap, wizard, metricToActivationMap,
+ trackerToMetricMap, conditionToMetricMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation)) {
+ return false;
+ }
+
+ const CountMetric& metric = config.count_metric(configIndex);
+ int trackerIndex;
+ // Update appropriate indices, specifically mConditionIndex and MetricsManager maps.
+ if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex, false,
+ allAtomMatchingTrackers, newAtomMatchingTrackerMap,
+ trackerToMetricMap, trackerIndex)) {
+ return false;
+ }
+
+ if (metric.has_condition() &&
+ !handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
+ metric.links(), allConditionTrackers, mConditionTrackerIndex,
+ conditionToMetricMap)) {
+ return false;
+ }
+ return true;
+}
+
void CountMetricProducer::onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
const HashableDimensionKey& primaryKey,
const FieldValue& oldState, const FieldValue& newState) {
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 6b2f2ca..0769ac4 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -97,6 +97,22 @@
void flushCurrentBucketLocked(const int64_t& eventTimeNs,
const int64_t& nextBucketStartTimeNs) override;
+ bool onConfigUpdatedLocked(
+ const StatsdConfig& config, const int configIndex, const int metricIndex,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& oldAtomMatchingTrackerMap,
+ const std::unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
+ const sp<EventMatcherWizard>& matcherWizard,
+ const std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap,
+ const sp<ConditionWizard>& wizard,
+ const std::unordered_map<int64_t, int>& metricToActivationMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation) override;
+
std::unordered_map<MetricDimensionKey, std::vector<CountBucket>> mPastBuckets;
// The current bucket (may be a partial bucket).
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 320b285..4360010 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -566,7 +566,9 @@
FRIEND_TEST(MetricsManagerTest, TestInitialConditions);
FRIEND_TEST(ConfigUpdateTest, TestUpdateMetricActivations);
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateCountMetrics);
FRIEND_TEST(ConfigUpdateTest, TestUpdateEventMetrics);
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateMetricsMultipleTypes);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
index 12d3b94..5ff6975 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
@@ -587,6 +587,51 @@
// Now, perform the update. Must iterate the metric types in the same order
int metricIndex = 0;
+ for (int i = 0; i < config.count_metric_size(); i++, metricIndex++) {
+ newMetricProducerMap[config.count_metric(i).id()] = metricIndex;
+ const CountMetric& metric = config.count_metric(i);
+ switch (metricsToUpdate[metricIndex]) {
+ case UPDATE_PRESERVE: {
+ const auto& oldMetricProducerIt = oldMetricProducerMap.find(metric.id());
+ if (oldMetricProducerIt == oldMetricProducerMap.end()) {
+ ALOGE("Could not find Metric %lld in the previous config, but expected it "
+ "to be there",
+ (long long)metric.id());
+ return false;
+ }
+ const int oldIndex = oldMetricProducerIt->second;
+ sp<MetricProducer> producer = oldMetricProducers[oldIndex];
+ producer->onConfigUpdated(
+ config, i, metricIndex, allAtomMatchingTrackers, oldAtomMatchingTrackerMap,
+ newAtomMatchingTrackerMap, matcherWizard, allConditionTrackers,
+ conditionTrackerMap, wizard, metricToActivationMap, trackerToMetricMap,
+ conditionToMetricMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ newMetricProducers.push_back(producer);
+ break;
+ }
+ case UPDATE_REPLACE:
+ case UPDATE_NEW: {
+ sp<MetricProducer> producer = createCountMetricProducerAndUpdateMetadata(
+ key, config, timeBaseNs, currentTimeNs, metric, metricIndex,
+ allAtomMatchingTrackers, newAtomMatchingTrackerMap, allConditionTrackers,
+ conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
+ allStateGroupMaps, metricToActivationMap, trackerToMetricMap,
+ conditionToMetricMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation);
+ if (producer == nullptr) {
+ return false;
+ }
+ newMetricProducers.push_back(producer);
+ break;
+ }
+ default: {
+ ALOGE("Metric \"%lld\" update state is unknown. This should never happen",
+ (long long)metric.id());
+ return false;
+ }
+ }
+ }
for (int i = 0; i < config.event_metric_size(); i++, metricIndex++) {
newMetricProducerMap[config.event_metric(i).id()] = metricIndex;
const EventMetric& metric = config.event_metric(i);
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index 51df7df..98c6222 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -348,6 +348,81 @@
return true;
}
+sp<MetricProducer> createCountMetricProducerAndUpdateMetadata(
+ const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
+ const int64_t currentTimeNs, const CountMetric& metric, const int metricIndex,
+ const vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ vector<sp<ConditionTracker>>& allConditionTrackers,
+ const unordered_map<int64_t, int>& conditionTrackerMap,
+ const vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
+ const unordered_map<int64_t, int>& stateAtomIdMap,
+ const unordered_map<int64_t, unordered_map<int, int64_t>>& allStateGroupMaps,
+ const unordered_map<int64_t, int>& metricToActivationMap,
+ unordered_map<int, vector<int>>& trackerToMetricMap,
+ unordered_map<int, vector<int>>& conditionToMetricMap,
+ unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
+ unordered_map<int, vector<int>>& deactivationAtomTrackerToMetricMap,
+ vector<int>& metricsWithActivation) {
+ if (!metric.has_id() || !metric.has_what()) {
+ ALOGW("cannot find metric id or \"what\" in CountMetric \"%lld\"", (long long)metric.id());
+ return nullptr;
+ }
+ int trackerIndex;
+ if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex,
+ metric.has_dimensions_in_what(),
+ allAtomMatchingTrackers, atomMatchingTrackerMap,
+ trackerToMetricMap, trackerIndex)) {
+ return nullptr;
+ }
+
+ int conditionIndex = -1;
+ if (metric.has_condition()) {
+ if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
+ metric.links(), allConditionTrackers, conditionIndex,
+ conditionToMetricMap)) {
+ return nullptr;
+ }
+ } else {
+ if (metric.links_size() > 0) {
+ ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
+ return nullptr;
+ }
+ }
+
+ std::vector<int> slicedStateAtoms;
+ unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
+ if (metric.slice_by_state_size() > 0) {
+ if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
+ allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
+ return nullptr;
+ }
+ } else {
+ if (metric.state_link_size() > 0) {
+ ALOGW("CountMetric has a MetricStateLink but doesn't have a slice_by_state");
+ return nullptr;
+ }
+ }
+
+ unordered_map<int, shared_ptr<Activation>> eventActivationMap;
+ unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
+ if (!handleMetricActivation(config, metric.id(), metricIndex, metricToActivationMap,
+ atomMatchingTrackerMap, activationAtomTrackerToMetricMap,
+ deactivationAtomTrackerToMetricMap, metricsWithActivation,
+ eventActivationMap, eventDeactivationMap)) {
+ return nullptr;
+ }
+
+ uint64_t metricHash;
+ if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+ return nullptr;
+ }
+
+ return new CountMetricProducer(key, metric, conditionIndex, initialConditionCache, wizard,
+ metricHash, timeBaseNs, currentTimeNs, eventActivationMap,
+ eventDeactivationMap, slicedStateAtoms, stateGroupMap);
+}
+
sp<MetricProducer> createEventMetricProducerAndUpdateMetadata(
const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
const EventMetric& metric, const int metricIndex,
@@ -550,68 +625,20 @@
// Build MetricProducers for each metric defined in config.
// build CountMetricProducer
for (int i = 0; i < config.count_metric_size(); i++) {
- const CountMetric& metric = config.count_metric(i);
- if (!metric.has_what()) {
- ALOGW("cannot find \"what\" in CountMetric \"%lld\"", (long long)metric.id());
- return false;
- }
-
int metricIndex = allMetricProducers.size();
+ const CountMetric& metric = config.count_metric(i);
metricMap.insert({metric.id(), metricIndex});
- int trackerIndex;
- if (!handleMetricWithAtomMatchingTrackers(metric.what(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchingTrackers, atomMatchingTrackerMap,
- trackerToMetricMap, trackerIndex)) {
- return false;
- }
-
- int conditionIndex = -1;
- if (metric.has_condition()) {
- if (!handleMetricWithConditions(metric.condition(), metricIndex, conditionTrackerMap,
- metric.links(), allConditionTrackers, conditionIndex,
- conditionToMetricMap)) {
- return false;
- }
- } else {
- if (metric.links_size() > 0) {
- ALOGW("metrics has a MetricConditionLink but doesn't have a condition");
- return false;
- }
- }
-
- std::vector<int> slicedStateAtoms;
- unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
- if (metric.slice_by_state_size() > 0) {
- if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
- allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
- return false;
- }
- } else {
- if (metric.state_link_size() > 0) {
- ALOGW("CountMetric has a MetricStateLink but doesn't have a slice_by_state");
- return false;
- }
- }
-
- unordered_map<int, shared_ptr<Activation>> eventActivationMap;
- unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- bool success = handleMetricActivation(
- config, metric.id(), metricIndex, metricToActivationMap, atomMatchingTrackerMap,
+ sp<MetricProducer> producer = createCountMetricProducerAndUpdateMetadata(
+ key, config, timeBaseTimeNs, currentTimeNs, metric, metricIndex,
+ allAtomMatchingTrackers, atomMatchingTrackerMap, allConditionTrackers,
+ conditionTrackerMap, initialConditionCache, wizard, stateAtomIdMap,
+ allStateGroupMaps, metricToActivationMap, trackerToMetricMap, conditionToMetricMap,
activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- metricsWithActivation, eventActivationMap, eventDeactivationMap);
- if (!success) return false;
-
- uint64_t metricHash;
- if (!getMetricProtoHash(config, metric, metric.id(), metricToActivationMap, metricHash)) {
+ metricsWithActivation);
+ if (producer == nullptr) {
return false;
}
-
- sp<MetricProducer> countProducer = new CountMetricProducer(
- key, metric, conditionIndex, initialConditionCache, wizard, metricHash,
- timeBaseTimeNs, currentTimeNs, eventActivationMap, eventDeactivationMap,
- slicedStateAtoms, stateGroupMap);
- allMetricProducers.push_back(countProducer);
+ allMetricProducers.push_back(producer);
}
// build DurationMetricProducer
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
index fdfe5cf..f6b2b7d 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
@@ -93,6 +93,27 @@
std::unordered_map<int, shared_ptr<Activation>>& newEventActivationMap,
std::unordered_map<int, std::vector<shared_ptr<Activation>>>& newEventDeactivationMap);
+// Creates a CountMetricProducer and updates the vectors/maps used by MetricsManager with
+// the appropriate indices. Returns an sp to the producer, or null if there was an error.
+sp<MetricProducer> createCountMetricProducerAndUpdateMetadata(
+ const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
+ const int64_t currentTimeNs, const CountMetric& metric, const int metricIndex,
+ const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
+ const std::unordered_map<int64_t, int>& atomMatchingTrackerMap,
+ std::vector<sp<ConditionTracker>>& allConditionTrackers,
+ const std::unordered_map<int64_t, int>& conditionTrackerMap,
+ const std::vector<ConditionState>& initialConditionCache, const sp<ConditionWizard>& wizard,
+ const std::unordered_map<int64_t, int>& stateAtomIdMap,
+ const std::unordered_map<int64_t, std::unordered_map<int, int64_t>>& allStateGroupMaps,
+ const std::unordered_map<int64_t, int>& metricToActivationMap,
+ std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
+ std::unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+ std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
+ std::vector<int>& metricsWithActivation);
+
+// Creates an EventMetricProducer and updates the vectors/maps used by MetricsManager with
+// the appropriate indices. Returns an sp to the producer, or null if there was an error.
sp<MetricProducer> createEventMetricProducerAndUpdateMetadata(
const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseNs,
const EventMetric& metric, const int metricIndex,
diff --git a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
index 3b346c1..9e675878 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
@@ -97,6 +97,7 @@
metricsWithActivation.clear();
oldStateHashes.clear();
noReportMetricIds.clear();
+ StateManager::getInstance().clear();
}
};
@@ -121,6 +122,21 @@
return metric;
}
+CountMetric createCountMetric(string name, int64_t what, optional<int64_t> condition,
+ vector<int64_t> states) {
+ CountMetric metric;
+ metric.set_id(StringToId(name));
+ metric.set_what(what);
+ metric.set_bucket(TEN_MINUTES);
+ if (condition) {
+ metric.set_condition(condition.value());
+ }
+ for (const int64_t state : states) {
+ metric.add_slice_by_state(state);
+ }
+ return metric;
+}
+
} // anonymous namespace
TEST_F(ConfigUpdateTest, TestSimpleMatcherPreserve) {
@@ -1419,7 +1435,7 @@
EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(event1Id)],
newMetricProducers[newMetricProducerMap.at(event1Id)]);
- // Make sure replaced conditions are different and included in replacedConditions.
+ // Make sure replaced metrics are different.
EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(event2Id)],
newMetricProducers[newMetricProducerMap.at(event2Id)]);
EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(event3Id)],
@@ -1478,6 +1494,239 @@
EXPECT_EQ(oldConditionWizard->getStrongCount(), 1);
}
+TEST_F(ConfigUpdateTest, TestUpdateCountMetrics) {
+ StatsdConfig config;
+
+ // Add atom matchers/predicates/states. These are mostly needed for initStatsdConfig.
+ AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher();
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher();
+ int64_t matcher2Id = matcher2.id();
+ *config.add_atom_matcher() = matcher2;
+
+ AtomMatcher matcher3 = CreateStartScheduledJobAtomMatcher();
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
+ AtomMatcher matcher4 = CreateFinishScheduledJobAtomMatcher();
+ int64_t matcher4Id = matcher4.id();
+ *config.add_atom_matcher() = matcher4;
+
+ AtomMatcher matcher5 = CreateBatterySaverModeStartAtomMatcher();
+ int64_t matcher5Id = matcher5.id();
+ *config.add_atom_matcher() = matcher5;
+
+ Predicate predicate1 = CreateScreenIsOnPredicate();
+ int64_t predicate1Id = predicate1.id();
+ *config.add_predicate() = predicate1;
+
+ State state1 = CreateScreenStateWithOnOffMap(0x123, 0x321);
+ int64_t state1Id = state1.id();
+ *config.add_state() = state1;
+
+ State state2 = CreateScreenState();
+ int64_t state2Id = state2.id();
+ *config.add_state() = state2;
+
+ // Add a few count metrics.
+ // Will be preserved.
+ CountMetric count1 = createCountMetric("COUNT1", matcher1Id, predicate1Id, {state1Id});
+ int64_t count1Id = count1.id();
+ *config.add_count_metric() = count1;
+
+ // Will be replaced.
+ CountMetric count2 = createCountMetric("COUNT2", matcher2Id, nullopt, {});
+ int64_t count2Id = count2.id();
+ *config.add_count_metric() = count2;
+
+ // Will be replaced.
+ CountMetric count3 = createCountMetric("COUNT3", matcher3Id, nullopt, {});
+ int64_t count3Id = count3.id();
+ *config.add_count_metric() = count3;
+
+ // Will be replaced.
+ CountMetric count4 = createCountMetric("COUNT4", matcher4Id, nullopt, {state2Id});
+ int64_t count4Id = count4.id();
+ *config.add_count_metric() = count4;
+
+ // Will be deleted.
+ CountMetric count5 = createCountMetric("COUNT5", matcher5Id, nullopt, {});
+ int64_t count5Id = count5.id();
+ *config.add_count_metric() = count5;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Change bucket size of count2, causing it to be replaced.
+ count2.set_bucket(ONE_HOUR);
+
+ // Mark matcher 3 as replaced. Causes count3 to be replaced.
+ set<int64_t> replacedMatchers;
+ replacedMatchers.insert(matcher3Id);
+
+ // Mark state 2 as replaced and change the state to be about a different atom.
+ // Causes count4 to be replaced.
+ set<int64_t> replacedStates;
+ replacedStates.insert(state2Id);
+ state2.set_atom_id(util::BATTERY_SAVER_MODE_STATE_CHANGED);
+
+ // Fake that predicate 1 is true for count metric 1.
+ ASSERT_EQ(oldMetricProducers[0]->getMetricId(), count1Id);
+ oldMetricProducers[0]->onConditionChanged(true, /*timestamp=*/0);
+ EXPECT_EQ(oldMetricProducers[0]->mCondition, ConditionState::kTrue);
+
+ EXPECT_EQ(StateManager::getInstance().getStateTrackersCount(), 1);
+ // Tell the StateManager that the screen is on.
+ unique_ptr<LogEvent> event =
+ CreateScreenStateChangedEvent(0, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+ StateManager::getInstance().onLogEvent(*event);
+
+ // New count metric. Should have an initial condition of true since it depends on predicate1.
+ CountMetric count6 = createCountMetric("EVENT6", matcher2Id, predicate1Id, {state1Id});
+ int64_t count6Id = count6.id();
+
+ // Map the matchers and predicates in reverse order to force the indices to change.
+ std::unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ const int matcher5Index = 0;
+ newAtomMatchingTrackerMap[matcher5Id] = 0;
+ const int matcher4Index = 1;
+ newAtomMatchingTrackerMap[matcher4Id] = 1;
+ const int matcher3Index = 2;
+ newAtomMatchingTrackerMap[matcher3Id] = 2;
+ const int matcher2Index = 3;
+ newAtomMatchingTrackerMap[matcher2Id] = 3;
+ const int matcher1Index = 4;
+ newAtomMatchingTrackerMap[matcher1Id] = 4;
+ // Use the existing matchers. A bit hacky, but saves code and we don't rely on them.
+ vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(5);
+ std::reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(),
+ newAtomMatchingTrackers.begin());
+
+ std::unordered_map<int64_t, int> newConditionTrackerMap;
+ const int predicate1Index = 0;
+ newConditionTrackerMap[predicate1Id] = 0;
+ // Use the existing conditionTrackers. A bit hacky, but saves code and we don't rely on them.
+ vector<sp<ConditionTracker>> newConditionTrackers(1);
+ std::reverse_copy(oldConditionTrackers.begin(), oldConditionTrackers.end(),
+ newConditionTrackers.begin());
+ // Fake that predicate1 is true for all new metrics.
+ vector<ConditionState> conditionCache = {ConditionState::kTrue};
+
+ StatsdConfig newConfig;
+ *newConfig.add_count_metric() = count6;
+ const int count6Index = 0;
+ *newConfig.add_count_metric() = count3;
+ const int count3Index = 1;
+ *newConfig.add_count_metric() = count1;
+ const int count1Index = 2;
+ *newConfig.add_count_metric() = count4;
+ const int count4Index = 3;
+ *newConfig.add_count_metric() = count2;
+ const int count2Index = 4;
+
+ *newConfig.add_state() = state1;
+ *newConfig.add_state() = state2;
+
+ unordered_map<int64_t, int> stateAtomIdMap;
+ unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
+ map<int64_t, uint64_t> stateProtoHashes;
+ EXPECT_TRUE(initStates(newConfig, stateAtomIdMap, allStateGroupMaps, stateProtoHashes));
+ EXPECT_EQ(stateAtomIdMap[state2Id], util::BATTERY_SAVER_MODE_STATE_CHANGED);
+
+ // Output data structures to validate.
+ unordered_map<int64_t, int> newMetricProducerMap;
+ vector<sp<MetricProducer>> newMetricProducers;
+ unordered_map<int, vector<int>> conditionToMetricMap;
+ unordered_map<int, vector<int>> trackerToMetricMap;
+ set<int64_t> noReportMetricIds;
+ unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
+ vector<int> metricsWithActivation;
+ EXPECT_TRUE(updateMetrics(
+ key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers,
+ newAtomMatchingTrackers, newConditionTrackerMap, /*replacedConditions=*/{},
+ newConditionTrackers, conditionCache, stateAtomIdMap, allStateGroupMaps, replacedStates,
+ oldMetricProducerMap, oldMetricProducers, newMetricProducerMap, newMetricProducers,
+ conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation));
+
+ unordered_map<int64_t, int> expectedMetricProducerMap = {
+ {count1Id, count1Index}, {count2Id, count2Index}, {count3Id, count3Index},
+ {count4Id, count4Index}, {count6Id, count6Index},
+ };
+ EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap));
+
+ // Make sure preserved metrics are the same.
+ ASSERT_EQ(newMetricProducers.size(), 5);
+ EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(count1Id)],
+ newMetricProducers[newMetricProducerMap.at(count1Id)]);
+
+ // Make sure replaced metrics are different.
+ EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(count2Id)],
+ newMetricProducers[newMetricProducerMap.at(count2Id)]);
+ EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(count3Id)],
+ newMetricProducers[newMetricProducerMap.at(count3Id)]);
+ EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(count4Id)],
+ newMetricProducers[newMetricProducerMap.at(count4Id)]);
+
+ // Verify the conditionToMetricMap.
+ ASSERT_EQ(conditionToMetricMap.size(), 1);
+ const vector<int>& condition1Metrics = conditionToMetricMap[predicate1Index];
+ EXPECT_THAT(condition1Metrics, UnorderedElementsAre(count1Index, count6Index));
+
+ // Verify the trackerToMetricMap.
+ ASSERT_EQ(trackerToMetricMap.size(), 4);
+ const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index];
+ EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(count1Index));
+ const vector<int>& matcher2Metrics = trackerToMetricMap[matcher2Index];
+ EXPECT_THAT(matcher2Metrics, UnorderedElementsAre(count2Index, count6Index));
+ const vector<int>& matcher3Metrics = trackerToMetricMap[matcher3Index];
+ EXPECT_THAT(matcher3Metrics, UnorderedElementsAre(count3Index));
+ const vector<int>& matcher4Metrics = trackerToMetricMap[matcher4Index];
+ EXPECT_THAT(matcher4Metrics, UnorderedElementsAre(count4Index));
+
+ // Verify event activation/deactivation maps.
+ ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 0);
+ ASSERT_EQ(deactivationAtomTrackerToMetricMap.size(), 0);
+ ASSERT_EQ(metricsWithActivation.size(), 0);
+
+ // Verify tracker indices/ids/conditions/states are correct.
+ EXPECT_EQ(newMetricProducers[count1Index]->getMetricId(), count1Id);
+ EXPECT_EQ(newMetricProducers[count1Index]->mConditionTrackerIndex, predicate1Index);
+ EXPECT_EQ(newMetricProducers[count1Index]->mCondition, ConditionState::kTrue);
+ EXPECT_THAT(newMetricProducers[count1Index]->getSlicedStateAtoms(),
+ UnorderedElementsAre(util::SCREEN_STATE_CHANGED));
+ EXPECT_EQ(newMetricProducers[count2Index]->getMetricId(), count2Id);
+ EXPECT_EQ(newMetricProducers[count2Index]->mConditionTrackerIndex, -1);
+ EXPECT_EQ(newMetricProducers[count2Index]->mCondition, ConditionState::kTrue);
+ EXPECT_TRUE(newMetricProducers[count2Index]->getSlicedStateAtoms().empty());
+ EXPECT_EQ(newMetricProducers[count3Index]->getMetricId(), count3Id);
+ EXPECT_EQ(newMetricProducers[count3Index]->mConditionTrackerIndex, -1);
+ EXPECT_EQ(newMetricProducers[count3Index]->mCondition, ConditionState::kTrue);
+ EXPECT_TRUE(newMetricProducers[count3Index]->getSlicedStateAtoms().empty());
+ EXPECT_EQ(newMetricProducers[count4Index]->getMetricId(), count4Id);
+ EXPECT_EQ(newMetricProducers[count4Index]->mConditionTrackerIndex, -1);
+ EXPECT_EQ(newMetricProducers[count4Index]->mCondition, ConditionState::kTrue);
+ EXPECT_THAT(newMetricProducers[count4Index]->getSlicedStateAtoms(),
+ UnorderedElementsAre(util::BATTERY_SAVER_MODE_STATE_CHANGED));
+ EXPECT_EQ(newMetricProducers[count6Index]->getMetricId(), count6Id);
+ EXPECT_EQ(newMetricProducers[count6Index]->mConditionTrackerIndex, predicate1Index);
+ EXPECT_EQ(newMetricProducers[count6Index]->mCondition, ConditionState::kTrue);
+ EXPECT_THAT(newMetricProducers[count6Index]->getSlicedStateAtoms(),
+ UnorderedElementsAre(util::SCREEN_STATE_CHANGED));
+
+ oldMetricProducers.clear();
+ // Ensure that the screen state StateTracker did not get deleted and replaced.
+ EXPECT_EQ(StateManager::getInstance().getStateTrackersCount(), 2);
+ FieldValue screenState;
+ StateManager::getInstance().getStateValue(util::SCREEN_STATE_CHANGED, DEFAULT_DIMENSION_KEY,
+ &screenState);
+ EXPECT_EQ(screenState.mValue.int_value, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+}
+
TEST_F(ConfigUpdateTest, TestUpdateMetricActivations) {
StatsdConfig config;
// Add atom matchers
@@ -1605,6 +1854,135 @@
EXPECT_THAT(producer->mEventDeactivationMap[matcher2Index],
UnorderedElementsAre(matcher4Activation));
}
+
+TEST_F(ConfigUpdateTest, TestUpdateMetricsMultipleTypes) {
+ StatsdConfig config;
+ // Add atom matchers/predicates/states. These are mostly needed for initStatsdConfig
+ AtomMatcher matcher1 = CreateScreenTurnedOnAtomMatcher();
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateScreenTurnedOffAtomMatcher();
+ int64_t matcher2Id = matcher2.id();
+ *config.add_atom_matcher() = matcher2;
+
+ Predicate predicate1 = CreateScreenIsOnPredicate();
+ int64_t predicate1Id = predicate1.id();
+ *config.add_predicate() = predicate1;
+
+ // Add a few count metrics.
+ // Will be preserved.
+ CountMetric countMetric = createCountMetric("COUNT1", matcher1Id, predicate1Id, {});
+ int64_t countMetricId = countMetric.id();
+ *config.add_count_metric() = countMetric;
+
+ // Will be replaced since matcher2 is replaced.
+ EventMetric eventMetric = createEventMetric("EVENT1", matcher2Id, nullopt);
+ int64_t eventMetricId = eventMetric.id();
+ *config.add_event_metric() = eventMetric;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Used later to ensure the condition wizard is replaced. Get it before doing the update.
+ sp<ConditionWizard> oldConditionWizard = oldMetricProducers[0]->mWizard;
+ EXPECT_EQ(oldConditionWizard->getStrongCount(), 3);
+
+ // Mark matcher 2 as replaced. Causes eventMetric to be replaced.
+ set<int64_t> replacedMatchers;
+ replacedMatchers.insert(matcher2Id);
+
+ // Map the matchers and predicates in reverse order to force the indices to change.
+ std::unordered_map<int64_t, int> newAtomMatchingTrackerMap;
+ const int matcher2Index = 0;
+ newAtomMatchingTrackerMap[matcher2Id] = 0;
+ const int matcher1Index = 1;
+ newAtomMatchingTrackerMap[matcher1Id] = 1;
+ // Use the existing matchers. A bit hacky, but saves code and we don't rely on them.
+ vector<sp<AtomMatchingTracker>> newAtomMatchingTrackers(2);
+ std::reverse_copy(oldAtomMatchingTrackers.begin(), oldAtomMatchingTrackers.end(),
+ newAtomMatchingTrackers.begin());
+
+ std::unordered_map<int64_t, int> newConditionTrackerMap;
+ const int predicate1Index = 0;
+ newConditionTrackerMap[predicate1Id] = 0;
+ // Use the existing conditionTrackers. A bit hacky, but saves code and we don't rely on them.
+ vector<sp<ConditionTracker>> newConditionTrackers(1);
+ std::reverse_copy(oldConditionTrackers.begin(), oldConditionTrackers.end(),
+ newConditionTrackers.begin());
+ vector<ConditionState> conditionCache = {ConditionState::kUnknown};
+
+ StatsdConfig newConfig;
+ *newConfig.add_count_metric() = countMetric;
+ const int countMetricIndex = 0;
+ *newConfig.add_event_metric() = eventMetric;
+ const int eventMetricIndex = 1;
+
+ // Output data structures to validate.
+ unordered_map<int64_t, int> newMetricProducerMap;
+ vector<sp<MetricProducer>> newMetricProducers;
+ unordered_map<int, vector<int>> conditionToMetricMap;
+ unordered_map<int, vector<int>> trackerToMetricMap;
+ set<int64_t> noReportMetricIds;
+ unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
+ vector<int> metricsWithActivation;
+ EXPECT_TRUE(updateMetrics(
+ key, newConfig, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
+ oldAtomMatchingTrackerMap, newAtomMatchingTrackerMap, replacedMatchers,
+ newAtomMatchingTrackers, newConditionTrackerMap, /*replacedConditions=*/{},
+ newConditionTrackers, conditionCache, /*stateAtomIdMap*/ {}, /*allStateGroupMaps=*/{},
+ /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
+ newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation));
+
+ unordered_map<int64_t, int> expectedMetricProducerMap = {
+ {countMetricId, countMetricIndex},
+ {eventMetricId, eventMetricIndex},
+ };
+ EXPECT_THAT(newMetricProducerMap, ContainerEq(expectedMetricProducerMap));
+
+ // Make sure preserved metrics are the same.
+ ASSERT_EQ(newMetricProducers.size(), 2);
+ EXPECT_EQ(oldMetricProducers[oldMetricProducerMap.at(countMetricId)],
+ newMetricProducers[newMetricProducerMap.at(countMetricId)]);
+
+ // Make sure replaced metrics are different.
+ EXPECT_NE(oldMetricProducers[oldMetricProducerMap.at(eventMetricId)],
+ newMetricProducers[newMetricProducerMap.at(eventMetricId)]);
+
+ // Verify the conditionToMetricMap.
+ ASSERT_EQ(conditionToMetricMap.size(), 1);
+ const vector<int>& condition1Metrics = conditionToMetricMap[predicate1Index];
+ EXPECT_THAT(condition1Metrics, UnorderedElementsAre(countMetricIndex));
+
+ // Verify the trackerToMetricMap.
+ ASSERT_EQ(trackerToMetricMap.size(), 2);
+ const vector<int>& matcher1Metrics = trackerToMetricMap[matcher1Index];
+ EXPECT_THAT(matcher1Metrics, UnorderedElementsAre(countMetricIndex));
+ const vector<int>& matcher2Metrics = trackerToMetricMap[matcher2Index];
+ EXPECT_THAT(matcher2Metrics, UnorderedElementsAre(eventMetricIndex));
+
+ // Verify event activation/deactivation maps.
+ ASSERT_EQ(activationAtomTrackerToMetricMap.size(), 0);
+ ASSERT_EQ(deactivationAtomTrackerToMetricMap.size(), 0);
+ ASSERT_EQ(metricsWithActivation.size(), 0);
+
+ // Verify tracker indices/ids/conditions are correct.
+ EXPECT_EQ(newMetricProducers[countMetricIndex]->getMetricId(), countMetricId);
+ EXPECT_EQ(newMetricProducers[countMetricIndex]->mConditionTrackerIndex, predicate1Index);
+ EXPECT_EQ(newMetricProducers[countMetricIndex]->mCondition, ConditionState::kUnknown);
+ EXPECT_EQ(newMetricProducers[eventMetricIndex]->getMetricId(), eventMetricId);
+ EXPECT_EQ(newMetricProducers[eventMetricIndex]->mConditionTrackerIndex, -1);
+ EXPECT_EQ(newMetricProducers[eventMetricIndex]->mCondition, ConditionState::kTrue);
+
+ sp<ConditionWizard> newConditionWizard = newMetricProducers[0]->mWizard;
+ EXPECT_NE(newConditionWizard, oldConditionWizard);
+ EXPECT_EQ(newConditionWizard->getStrongCount(), 3);
+ oldMetricProducers.clear();
+ // Only reference to the old wizard should be the one in the test.
+ EXPECT_EQ(oldConditionWizard->getStrongCount(), 1);
+}
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index a61159a..85cb120 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1910,6 +1910,8 @@
public static final int TYPE_NOTIFICATION = 2;
/** Launched from lockscreen, including notification while the device is locked. */
public static final int TYPE_LOCKSCREEN = 3;
+ /** Launched from recents gesture handler. */
+ public static final int TYPE_RECENTS_ANIMATION = 4;
@IntDef(flag = true, prefix = { "TYPE_" }, value = {
TYPE_LAUNCHER,
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 1a4db4e..1995128 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -25,7 +25,6 @@
import android.app.IApplicationThread;
import android.app.IActivityController;
import android.app.IAppTask;
-import android.app.IAssistDataReceiver;
import android.app.IInstrumentationWatcher;
import android.app.IProcessObserver;
import android.app.IServiceConnection;
@@ -70,7 +69,6 @@
import android.os.StrictMode;
import android.os.WorkSource;
import android.service.voice.IVoiceInteractionSession;
-import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationAdapter;
import com.android.internal.app.IVoiceInteractor;
@@ -470,11 +468,6 @@
@UnsupportedAppUsage
boolean isInLockTaskMode();
@UnsupportedAppUsage
- void startRecentsActivity(in Intent intent, in IAssistDataReceiver assistDataReceiver,
- in IRecentsAnimationRunner recentsAnimationRunner);
- @UnsupportedAppUsage
- void cancelRecentsAnimation(boolean restoreHomeStackPosition);
- @UnsupportedAppUsage
int startActivityFromRecents(int taskId, in Bundle options);
@UnsupportedAppUsage
void startSystemLockTaskMode(int taskId);
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index e21ef8e..ddf2dc50 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -123,7 +123,7 @@
in ProfilerInfo profilerInfo, in Bundle options, int userId);
int startAssistantActivity(in String callingPackage, in String callingFeatureId, int callingPid,
int callingUid, in Intent intent, in String resolvedType, in Bundle options, int userId);
- void startRecentsActivity(in Intent intent, in IAssistDataReceiver assistDataReceiver,
+ void startRecentsActivity(in Intent intent, in long eventTime,
in IRecentsAnimationRunner recentsAnimationRunner);
int startActivityFromRecents(int taskId, in Bundle options);
int startActivityAsCaller(in IApplicationThread caller, in String callingPackage,
diff --git a/core/java/android/app/PictureInPictureParams.java b/core/java/android/app/PictureInPictureParams.java
index df53f98..32252a3f 100644
--- a/core/java/android/app/PictureInPictureParams.java
+++ b/core/java/android/app/PictureInPictureParams.java
@@ -326,6 +326,16 @@
out.writeBoolean(mAutoEnterEnabled);
}
+ @Override
+ public String toString() {
+ return "PictureInPictureParams("
+ + " aspectRatio=" + getAspectRatioRational()
+ + " sourceRectHint=" + getSourceRectHint()
+ + " hasSetActions=" + hasSetActions()
+ + " isAutoPipEnabled=" + isAutoEnterEnabled()
+ + ")";
+ }
+
public static final @android.annotation.NonNull Creator<PictureInPictureParams> CREATOR =
new Creator<PictureInPictureParams>() {
public PictureInPictureParams createFromParcel(Parcel in) {
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index 26edba3..87e1df3 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -636,7 +636,7 @@
@Nullable
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@TestApi
- public String getDefaultSmsPackage(@UserIdInt int userId) {
+ public String getSmsRoleHolder(@UserIdInt int userId) {
try {
return mService.getDefaultSmsPackage(userId);
} catch (RemoteException e) {
diff --git a/core/java/android/app/time/TimeManager.java b/core/java/android/app/time/TimeManager.java
index 9864afb..4796d8d 100644
--- a/core/java/android/app/time/TimeManager.java
+++ b/core/java/android/app/time/TimeManager.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.app.timezonedetector.ITimeZoneDetectorService;
import android.content.Context;
@@ -36,7 +37,7 @@
*
* @hide
*/
-// @SystemApi
+@SystemApi
@SystemService(Context.TIME_MANAGER)
public final class TimeManager {
private static final String TAG = "time.TimeManager";
diff --git a/core/java/android/app/time/TimeZoneCapabilities.java b/core/java/android/app/time/TimeZoneCapabilities.java
index c62c2b3..df89c28 100644
--- a/core/java/android/app/time/TimeZoneCapabilities.java
+++ b/core/java/android/app/time/TimeZoneCapabilities.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TimeZoneDetector;
import android.os.Parcel;
@@ -50,7 +51,7 @@
*
* @hide
*/
-// @SystemApi
+@SystemApi
public final class TimeZoneCapabilities implements Parcelable {
/** @hide */
diff --git a/core/java/android/app/time/TimeZoneCapabilitiesAndConfig.java b/core/java/android/app/time/TimeZoneCapabilitiesAndConfig.java
index 6a04f3f..b339e53 100644
--- a/core/java/android/app/time/TimeZoneCapabilitiesAndConfig.java
+++ b/core/java/android/app/time/TimeZoneCapabilitiesAndConfig.java
@@ -17,6 +17,7 @@
package android.app.time;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,7 +28,7 @@
*
* @hide
*/
-// @SystemApi
+@SystemApi
public final class TimeZoneCapabilitiesAndConfig implements Parcelable {
public static final @NonNull Creator<TimeZoneCapabilitiesAndConfig> CREATOR =
diff --git a/core/java/android/app/time/TimeZoneConfiguration.java b/core/java/android/app/time/TimeZoneConfiguration.java
index 488818a..c0a0c21 100644
--- a/core/java/android/app/time/TimeZoneConfiguration.java
+++ b/core/java/android/app/time/TimeZoneConfiguration.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.StringDef;
+import android.annotation.SystemApi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -41,7 +42,7 @@
*
* @hide
*/
-// @SystemApi
+@SystemApi
public final class TimeZoneConfiguration implements Parcelable {
public static final @NonNull Creator<TimeZoneConfiguration> CREATOR =
@@ -188,7 +189,7 @@
*
* @hide
*/
- // @SystemApi
+ @SystemApi
public static final class Builder {
private final Bundle mBundle = new Bundle();
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 6a68796..573892b 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2563,7 +2563,7 @@
* Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
* <p>The link key is not required to be authenticated, i.e the communication may be
* vulnerable to Person In the Middle attacks. For Bluetooth 2.1 devices,
- * the link will be encrypted, as encryption is mandartory.
+ * the link will be encrypted, as encryption is mandatory.
* For legacy devices (pre Bluetooth 2.1 devices) the link will not
* be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
* encrypted and authenticated communication channel is desired.
@@ -2602,7 +2602,7 @@
* an input and output capability or just has the ability to display a numeric key,
* a secure socket connection is not possible and this socket can be used.
* Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required.
- * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandartory.
+ * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandatory.
* For more details, refer to the Security Model section 5.2 (vol 3) of
* Bluetooth Core Specification version 2.1 + EDR.
* <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 35c7b96..9a9f165 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2732,6 +2732,54 @@
public static final String ACTION_MY_PACKAGE_UNSUSPENDED = "android.intent.action.MY_PACKAGE_UNSUSPENDED";
/**
+ * Broadcast Action: Sent to indicate that the package becomes startable.
+ * The intent will have the following extra values:
+ * <ul>
+ * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. </li>
+ * <li> {@link #EXTRA_PACKAGE_NAME} containing the package name. </li>
+ * </li>
+ * </ul>
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_PACKAGE_STARTABLE = "android.intent.action.PACKAGE_STARTABLE";
+
+ /**
+ * Broadcast Action: Sent to indicate that the package becomes unstartable.
+ * The intent will have the following extra values:
+ * <ul>
+ * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. </li>
+ * <li> {@link #EXTRA_PACKAGE_NAME} containing the package name. </li>
+ * <li> {@link #EXTRA_REASON} containing the integer indicating the reason for the state change,
+ * @see PackageManager.UnstartableReason
+ * </li>
+ * </ul>
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_PACKAGE_UNSTARTABLE =
+ "android.intent.action.PACKAGE_UNSTARTABLE";
+
+ /**
+ * Broadcast Action: Sent to indicate that the package is fully loaded.
+ * <ul>
+ * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. </li>
+ * <li> {@link #EXTRA_PACKAGE_NAME} containing the package name. </li>
+ * </li>
+ * </ul>
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_PACKAGE_FULLY_LOADED =
+ "android.intent.action.PACKAGE_FULLY_LOADED";
+
+ /**
* Broadcast Action: A user ID has been removed from the system. The user
* ID number is stored in the extra data under {@link #EXTRA_UID}.
*
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index c2beab5..ea4b762 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1109,6 +1109,34 @@
}
/**
+ * Returns the reversed orientation.
+ * @hide
+ */
+ @ActivityInfo.ScreenOrientation
+ public static int reverseOrientation(@ActivityInfo.ScreenOrientation int orientation) {
+ switch (orientation) {
+ case SCREEN_ORIENTATION_LANDSCAPE:
+ return SCREEN_ORIENTATION_PORTRAIT;
+ case SCREEN_ORIENTATION_PORTRAIT:
+ return SCREEN_ORIENTATION_LANDSCAPE;
+ case SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
+ return SCREEN_ORIENTATION_SENSOR_PORTRAIT;
+ case SCREEN_ORIENTATION_SENSOR_PORTRAIT:
+ return SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
+ case SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
+ return SCREEN_ORIENTATION_REVERSE_PORTRAIT;
+ case SCREEN_ORIENTATION_REVERSE_PORTRAIT:
+ return SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
+ case SCREEN_ORIENTATION_USER_LANDSCAPE:
+ return SCREEN_ORIENTATION_USER_PORTRAIT;
+ case SCREEN_ORIENTATION_USER_PORTRAIT:
+ return SCREEN_ORIENTATION_USER_LANDSCAPE;
+ default:
+ return orientation;
+ }
+ }
+
+ /**
* Returns true if the activity supports picture-in-picture.
* @hide
*/
diff --git a/core/java/android/content/pm/IDataLoaderStatusListener.aidl b/core/java/android/content/pm/IDataLoaderStatusListener.aidl
index efb00a0..745c39b 100644
--- a/core/java/android/content/pm/IDataLoaderStatusListener.aidl
+++ b/core/java/android/content/pm/IDataLoaderStatusListener.aidl
@@ -50,7 +50,30 @@
* fail and all retry limits are exceeded. */
const int DATA_LOADER_UNRECOVERABLE = 8;
+ /** There are no known issues with the data stream. */
+ const int STREAM_HEALTHY = 0;
+
+ /** There are issues with the current transport layer (network, adb connection, etc.) that may
+ * recover automatically or could eventually require user intervention. */
+ const int STREAM_TRANSPORT_ERROR = 1;
+
+ /** Integrity failures in the data stream, this could be due to file corruption, decompression
+ * issues or similar. This indicates a likely unrecoverable error. */
+ const int STREAM_INTEGRITY_ERROR = 2;
+
+ /** There are issues with the source of the data, e.g., backend availability issues, account
+ * issues. This indicates a potentially recoverable error, but one that may take a long time to
+ * resolve. */
+ const int STREAM_SOURCE_ERROR = 3;
+
+ /** The device or app is low on storage and cannot complete the stream as a result.
+ * A subsequent page miss resulting in app failure will transition app to unstartable state. */
+ const int STREAM_STORAGE_ERROR = 4;
+
/** Data loader status callback */
void onStatusChanged(in int dataLoaderId, in int status);
+
+ /** Callback to report streaming health status of a specific data loader */
+ void reportStreamHealth(in int dataLoaderId, in int streamStatus);
}
diff --git a/core/java/android/content/pm/IncrementalStatesInfo.aidl b/core/java/android/content/pm/IncrementalStatesInfo.aidl
new file mode 100644
index 0000000..7064fbf
--- /dev/null
+++ b/core/java/android/content/pm/IncrementalStatesInfo.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 2020, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.content.pm;
+
+parcelable IncrementalStatesInfo;
diff --git a/core/java/android/content/pm/IncrementalStatesInfo.java b/core/java/android/content/pm/IncrementalStatesInfo.java
new file mode 100644
index 0000000..6e91c19
--- /dev/null
+++ b/core/java/android/content/pm/IncrementalStatesInfo.java
@@ -0,0 +1,76 @@
+/*
+ * 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.content.pm;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Info about a package's states in Parcelable format.
+ * @hide
+ */
+public class IncrementalStatesInfo implements Parcelable {
+ private boolean mIsStartable;
+ private boolean mIsLoading;
+ private float mProgress;
+
+ public IncrementalStatesInfo(boolean isStartable, boolean isLoading, float progress) {
+ mIsStartable = isStartable;
+ mIsLoading = isLoading;
+ mProgress = progress;
+ }
+
+ private IncrementalStatesInfo(Parcel source) {
+ mIsStartable = source.readBoolean();
+ mIsLoading = source.readBoolean();
+ mProgress = source.readFloat();
+ }
+
+ public boolean isStartable() {
+ return mIsStartable;
+ }
+
+ public boolean isLoading() {
+ return mIsLoading;
+ }
+
+ public float getProgress() {
+ return mProgress;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeBoolean(mIsStartable);
+ dest.writeBoolean(mIsLoading);
+ dest.writeFloat(mProgress);
+ }
+
+ public static final @android.annotation.NonNull Creator<IncrementalStatesInfo> CREATOR =
+ new Creator<IncrementalStatesInfo>() {
+ public IncrementalStatesInfo createFromParcel(Parcel source) {
+ return new IncrementalStatesInfo(source);
+ }
+ public IncrementalStatesInfo[] newArray(int size) {
+ return new IncrementalStatesInfo[size];
+ }
+ };
+}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a600d6c..c293e4ad 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3786,6 +3786,39 @@
*/
public static final int SYSTEM_APP_STATE_UNINSTALLED = 3;
+ /**
+ * Reasons for why a package is unstartable.
+ * @hide
+ */
+ @IntDef({UNSTARTABLE_REASON_UNKNOWN,
+ UNSTARTABLE_REASON_DATALOADER_TRANSPORT,
+ UNSTARTABLE_REASON_DATALOADER_STORAGE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UnstartableReason {}
+
+ /**
+ * Unstartable state with no root cause specified. E.g., data loader seeing missing pages but
+ * unclear about the cause. This corresponds to a generic alert window shown to the user when
+ * the user attempts to launch the app.
+ * @hide
+ */
+ public static final int UNSTARTABLE_REASON_UNKNOWN = 0;
+
+ /**
+ * Unstartable state after hint from dataloader of issues with the transport layer.
+ * This corresponds to an alert window shown to the user indicating network errors.
+ * @hide
+ */
+ public static final int UNSTARTABLE_REASON_DATALOADER_TRANSPORT = 1;
+
+ /**
+ * Unstartable state after encountering storage limitations.
+ * This corresponds to an alert window indicating limited storage.
+ * @hide
+ */
+ public static final int UNSTARTABLE_REASON_DATALOADER_STORAGE = 2;
+
/** {@hide} */
public int getUserId() {
return UserHandle.myUserId();
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 327d1b8..3ed21b0 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -44,7 +44,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.CollectionUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index cad103e9..651494d 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -21,14 +21,13 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.net.util.LinkPropertiesUtils;
+import android.net.util.LinkPropertiesUtils.CompareResult;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
-import com.android.net.module.util.LinkPropertiesUtils;
-import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
-
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java
index 51c5a50..0eb3c1e 100644
--- a/core/java/android/net/MacAddress.java
+++ b/core/java/android/net/MacAddress.java
@@ -20,12 +20,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
+import android.net.util.MacAddressUtils;
import android.net.wifi.WifiInfo;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.util.Preconditions;
-import com.android.net.module.util.MacAddressUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index a8b45e9..9876076 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -22,12 +22,11 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.net.util.NetUtils;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.net.module.util.NetUtils;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.Inet4Address;
diff --git a/core/java/android/os/FileBridge.java b/core/java/android/os/FileBridge.java
index 21fd819..ab5637c 100644
--- a/core/java/android/os/FileBridge.java
+++ b/core/java/android/os/FileBridge.java
@@ -16,7 +16,6 @@
package android.os;
-import static android.system.OsConstants.AF_UNIX;
import static android.system.OsConstants.SOCK_STREAM;
import android.system.ErrnoException;
@@ -58,17 +57,19 @@
/** CMD_CLOSE */
private static final int CMD_CLOSE = 3;
- private FileDescriptor mTarget;
+ private ParcelFileDescriptor mTarget;
- private final FileDescriptor mServer = new FileDescriptor();
- private final FileDescriptor mClient = new FileDescriptor();
+ private ParcelFileDescriptor mServer;
+ private ParcelFileDescriptor mClient;
private volatile boolean mClosed;
public FileBridge() {
try {
- Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mServer, mClient);
- } catch (ErrnoException e) {
+ ParcelFileDescriptor[] fds = ParcelFileDescriptor.createSocketPair(SOCK_STREAM);
+ mServer = fds[0];
+ mClient = fds[1];
+ } catch (IOException e) {
throw new RuntimeException("Failed to create bridge");
}
}
@@ -80,15 +81,14 @@
public void forceClose() {
IoUtils.closeQuietly(mTarget);
IoUtils.closeQuietly(mServer);
- IoUtils.closeQuietly(mClient);
mClosed = true;
}
- public void setTargetFile(FileDescriptor target) {
+ public void setTargetFile(ParcelFileDescriptor target) {
mTarget = target;
}
- public FileDescriptor getClientSocket() {
+ public ParcelFileDescriptor getClientSocket() {
return mClient;
}
@@ -96,32 +96,33 @@
public void run() {
final byte[] temp = new byte[8192];
try {
- while (IoBridge.read(mServer, temp, 0, MSG_LENGTH) == MSG_LENGTH) {
+ while (IoBridge.read(mServer.getFileDescriptor(), temp, 0, MSG_LENGTH) == MSG_LENGTH) {
final int cmd = Memory.peekInt(temp, 0, ByteOrder.BIG_ENDIAN);
if (cmd == CMD_WRITE) {
// Shuttle data into local file
int len = Memory.peekInt(temp, 4, ByteOrder.BIG_ENDIAN);
while (len > 0) {
- int n = IoBridge.read(mServer, temp, 0, Math.min(temp.length, len));
+ int n = IoBridge.read(mServer.getFileDescriptor(), temp, 0,
+ Math.min(temp.length, len));
if (n == -1) {
throw new IOException(
"Unexpected EOF; still expected " + len + " bytes");
}
- IoBridge.write(mTarget, temp, 0, n);
+ IoBridge.write(mTarget.getFileDescriptor(), temp, 0, n);
len -= n;
}
} else if (cmd == CMD_FSYNC) {
// Sync and echo back to confirm
- Os.fsync(mTarget);
- IoBridge.write(mServer, temp, 0, MSG_LENGTH);
+ Os.fsync(mTarget.getFileDescriptor());
+ IoBridge.write(mServer.getFileDescriptor(), temp, 0, MSG_LENGTH);
} else if (cmd == CMD_CLOSE) {
// Close and echo back to confirm
- Os.fsync(mTarget);
- Os.close(mTarget);
+ Os.fsync(mTarget.getFileDescriptor());
+ mTarget.close();
mClosed = true;
- IoBridge.write(mServer, temp, 0, MSG_LENGTH);
+ IoBridge.write(mServer.getFileDescriptor(), temp, 0, MSG_LENGTH);
break;
}
}
@@ -143,17 +144,11 @@
mClient = clientPfd.getFileDescriptor();
}
- public FileBridgeOutputStream(FileDescriptor client) {
- mClientPfd = null;
- mClient = client;
- }
-
@Override
public void close() throws IOException {
try {
writeCommandAndBlock(CMD_CLOSE, "close()");
} finally {
- IoBridge.closeAndSignalBlockedThreads(mClient);
IoUtils.closeQuietly(mClientPfd);
}
}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 1bddc49..13d5f6a 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -673,11 +673,11 @@
* {@link #dataPosition}. This is used to validate that the marshalled
* transaction is intended for the target interface.
*/
- public final void writeInterfaceToken(String interfaceName) {
+ public final void writeInterfaceToken(@NonNull String interfaceName) {
nativeWriteInterfaceToken(mNativePtr, interfaceName);
}
- public final void enforceInterface(String interfaceName) {
+ public final void enforceInterface(@NonNull String interfaceName) {
nativeEnforceInterface(mNativePtr, interfaceName);
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index ca0981b..e62ad1f 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -852,12 +852,11 @@
/**
* Set the priority of a thread, based on Linux priorities.
- *
- * @param tid The identifier of the thread/process to change. It should be
- * the native thread id but not the managed id of {@link java.lang.Thread}.
+ *
+ * @param tid The identifier of the thread/process to change.
* @param priority A Linux priority level, from -20 for highest scheduling
* priority to 19 for lowest scheduling priority.
- *
+ *
* @throws IllegalArgumentException Throws IllegalArgumentException if
* <var>tid</var> does not exist.
* @throws SecurityException Throws SecurityException if your process does
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 9e332e9..06203ff 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -657,16 +657,8 @@
argsForZygote.add("--runtime-flags=" + runtimeFlags);
if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
argsForZygote.add("--mount-external-default");
- } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
- argsForZygote.add("--mount-external-read");
- } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
- argsForZygote.add("--mount-external-write");
- } else if (mountExternal == Zygote.MOUNT_EXTERNAL_FULL) {
- argsForZygote.add("--mount-external-full");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_INSTALLER) {
argsForZygote.add("--mount-external-installer");
- } else if (mountExternal == Zygote.MOUNT_EXTERNAL_LEGACY) {
- argsForZygote.add("--mount-external-legacy");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_PASS_THROUGH) {
argsForZygote.add("--mount-external-pass-through");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE) {
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index a79a1cf..4379ce1 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -70,13 +70,6 @@
public abstract void addExternalStoragePolicy(ExternalStorageMountPolicy policy);
/**
- * Notify the mount service that the mount policy for a UID changed.
- * @param uid The UID for which policy changed.
- * @param packageName The package in the UID for making the call.
- */
- public abstract void onExternalStoragePolicyChanged(int uid, String packageName);
-
- /**
* Gets the mount mode to use for a given UID as determined by consultin all
* policies.
*
diff --git a/core/java/android/provider/FontRequest.java b/core/java/android/provider/FontRequest.java
index 34114bc..1f67e8f 100644
--- a/core/java/android/provider/FontRequest.java
+++ b/core/java/android/provider/FontRequest.java
@@ -20,13 +20,14 @@
import com.android.internal.util.Preconditions;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Information about a font request that may be sent to a Font Provider.
+ * @deprecated Use the {@link androidx.core.provider.FontRequest}
*/
+@Deprecated
public final class FontRequest {
private final String mProviderAuthority;
private final String mProviderPackage;
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index fcbda5f..a15f3ae 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -69,7 +69,11 @@
/**
* Utility class to deal with Font ContentProviders.
+ * @deprecated Use the <a href="{@docRoot}jetpack">Jetpack Core Library</a>
+ * {@link androidx.core.provider.FontsContractCompat} for consistent behavior across all
+ * devices.
*/
+@Deprecated
public class FontsContract {
private static final String TAG = "FontsContract";
@@ -79,7 +83,11 @@
* This should point to a real file or shared memory, as the client will mmap the given file
* descriptor. Pipes, sockets and other non-mmap-able file descriptors will fail to load in the
* client application.
+ *
+ * @deprecated Use the {@link androidx.core.provider.FontsContractCompat.Columns} for consistent
+ * behavior across all devices.
*/
+ @Deprecated
public static final class Columns implements BaseColumns {
// Do not instantiate.
@@ -174,7 +182,11 @@
/**
* Object represent a font entry in the family returned from {@link #fetchFonts}.
+ *
+ * @deprecated Use the {@link androidx.core.provider.FontsContractCompat.FontInfo} for
+ * consistent behavior across all devices
*/
+ @Deprecated
public static class FontInfo {
private final Uri mUri;
private final int mTtcIndex;
@@ -251,7 +263,11 @@
/**
* Object returned from {@link #fetchFonts}.
+ *
+ * @deprecated Use the {@link androidx.core.provider.FontsContractCompat.FontFamilyResult} for
+ * consistent behavior across all devices
*/
+ @Deprecated
public static class FontFamilyResult {
/**
* Constant represents that the font was successfully retrieved. Note that when this value
@@ -412,7 +428,11 @@
/**
* Interface used to receive asynchronously fetched typefaces.
+ *
+ * @deprecated Use the {@link androidx.core.provider.FontsContractCompat.FontRequestCallback}
+ * for consistent behavior across all devices
*/
+ @Deprecated
public static class FontRequestCallback {
/**
* Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1dbf95f..97acd2f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3567,6 +3567,9 @@
if (outConfig.fontScale < 0) {
outConfig.fontScale = DEFAULT_FONT_SCALE;
}
+ outConfig.forceBoldText = Settings.Secure.getIntForUser(
+ cr, Settings.Secure.FORCE_BOLD_TEXT, Configuration.FORCE_BOLD_TEXT_NO,
+ userHandle);
final String localeValue =
Settings.System.getStringForUser(cr, SYSTEM_LOCALES, userHandle);
@@ -3597,6 +3600,7 @@
if (!inoutConfig.userSetLocale && !inoutConfig.getLocales().isEmpty()) {
inoutConfig.clearLocales();
}
+ inoutConfig.forceBoldText = Configuration.FORCE_BOLD_TEXT_UNDEFINED;
}
/**
@@ -3620,7 +3624,11 @@
DEFAULT_OVERRIDEABLE_BY_RESTORE);
}
- /** @hide */
+ /**
+ * Convenience function for checking if settings should be overwritten with config changes.
+ * @see #putConfigurationForUser(ContentResolver, Configuration, int)
+ * @hide
+ */
public static boolean hasInterestingConfigurationChanges(int changes) {
return (changes & ActivityInfo.CONFIG_FONT_SCALE) != 0 ||
(changes & ActivityInfo.CONFIG_LOCALE) != 0;
@@ -13407,15 +13415,6 @@
"power_button_very_long_press";
/**
- * Global settings that shouldn't be persisted.
- *
- * @hide
- */
- public static final String[] TRANSIENT_SETTINGS = {
- LOCATION_GLOBAL_KILL_SWITCH,
- };
-
- /**
* Keys we no longer back up under the current schema, but want to continue to
* process when restoring historical backup datasets.
*
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index be52667..e520d7c 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -181,6 +181,7 @@
private long mFrameIntervalNanos;
private boolean mDebugPrintNextFrameTimeDelta;
private int mFPSDivisor = 1;
+ private long mLastVsyncId = FrameInfo.INVALID_VSYNC_ID;
/**
* Contains information about the current frame for jank-tracking,
@@ -654,14 +655,24 @@
}
}
+ /**
+ * Returns the vsync id of the last frame callback. Client are expected to call
+ * this function from their frame callback function to get the vsyncId and pass
+ * it together with a buffer or transaction to the Surface Composer. Calling
+ * this function from anywhere else will return an undefined value.
+ *
+ * @hide
+ */
+ public long getVsyncId() {
+ return mLastVsyncId;
+ }
+
void setFPSDivisor(int divisor) {
if (divisor <= 0) divisor = 1;
mFPSDivisor = divisor;
ThreadedRenderer.setFPSDivisor(divisor);
}
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link "
- + "#postFrameCallback} instead")
void doFrame(long frameTimeNanos, int frame, long frameTimelineVsyncId) {
final long startNanos;
synchronized (mLock) {
@@ -715,6 +726,7 @@
mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos, frameTimelineVsyncId);
mFrameScheduled = false;
mLastFrameTimeNanos = frameTimeNanos;
+ mLastVsyncId = frameTimelineVsyncId;
}
try {
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index 430e2cf..51474d3 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -17,7 +17,6 @@
package android.view;
import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.Log;
@@ -158,8 +157,6 @@
* @param frameTimelineVsyncId The frame timeline vsync id, used to correlate a frame
* produced by HWUI with the timeline data stored in Surface Flinger.
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link "
- + "Choreographer#postFrameCallback} instead")
public void onVsync(long timestampNanos, long physicalDisplayId, int frame,
long frameTimelineVsyncId) {
}
@@ -203,8 +200,6 @@
// Called from native code.
@SuppressWarnings("unused")
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link "
- + "Choreographer#postFrameCallback} instead")
private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame,
long frameTimelineVsyncId) {
onVsync(timestampNanos, physicalDisplayId, frame, frameTimelineVsyncId);
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index 5c08fb1..e3129b6 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -33,6 +33,7 @@
import static android.view.RemoteAnimationTargetProto.WINDOW_CONFIGURATION;
import android.annotation.IntDef;
+import android.app.PictureInPictureParams;
import android.app.WindowConfiguration;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Point;
@@ -185,11 +186,20 @@
@UnsupportedAppUsage
public boolean isNotInRecents;
+ /**
+ * {@link PictureInPictureParams} to allow launcher to determine if an app should
+ * automatically enter PiP on swiping up to home.
+ *
+ * TODO: add this to proto dump
+ */
+ public PictureInPictureParams pictureInPictureParams;
+
public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent,
Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position,
Rect localBounds, Rect screenSpaceBounds,
WindowConfiguration windowConfig, boolean isNotInRecents,
- SurfaceControl startLeash, Rect startBounds) {
+ SurfaceControl startLeash, Rect startBounds,
+ PictureInPictureParams pictureInPictureParams) {
this.mode = mode;
this.taskId = taskId;
this.leash = leash;
@@ -205,6 +215,7 @@
this.isNotInRecents = isNotInRecents;
this.startLeash = startLeash;
this.startBounds = startBounds == null ? null : new Rect(startBounds);
+ this.pictureInPictureParams = pictureInPictureParams;
}
public RemoteAnimationTarget(Parcel in) {
@@ -223,6 +234,7 @@
isNotInRecents = in.readBoolean();
startLeash = in.readParcelable(null);
startBounds = in.readParcelable(null);
+ pictureInPictureParams = in.readParcelable(null);
}
@Override
@@ -247,6 +259,7 @@
dest.writeBoolean(isNotInRecents);
dest.writeParcelable(startLeash, 0 /* flags */);
dest.writeParcelable(startBounds, 0 /* flags */);
+ dest.writeParcelable(pictureInPictureParams, 0 /* flags */);
}
public void dump(PrintWriter pw, String prefix) {
@@ -263,6 +276,7 @@
pw.println();
pw.print(prefix); pw.print("windowConfiguration="); pw.println(windowConfiguration);
pw.print(prefix); pw.print("leash="); pw.println(leash);
+ pw.print(prefix); pw.print("pictureInPictureParams="); pw.println(pictureInPictureParams);
}
public void dumpDebug(ProtoOutputStream proto, long fieldId) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index c698b92..0c64eea 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -182,9 +182,6 @@
IBinder displayToken, int mode);
private static native void nativeDeferTransactionUntil(long transactionObj, long nativeObject,
long barrierObject, long frame);
- private static native void nativeDeferTransactionUntilSurface(long transactionObj,
- long nativeObject,
- long surfaceObject, long frame);
private static native void nativeReparentChildren(long transactionObj, long nativeObject,
long newParentObject);
private static native void nativeReparent(long transactionObj, long nativeObject,
@@ -225,6 +222,8 @@
int transformHint);
private static native void nativeSetFocusedWindow(long transactionObj, IBinder toToken,
IBinder focusedToken, int displayId);
+ private static native void nativeSetFrameTimelineVsync(long transactionObj,
+ long frameTimelineVsyncId);
@Nullable
@GuardedBy("mLock")
@@ -2945,22 +2944,6 @@
/**
* @hide
*/
- @Deprecated
- @UnsupportedAppUsage
- public Transaction deferTransactionUntilSurface(SurfaceControl sc, Surface barrierSurface,
- long frameNumber) {
- if (frameNumber < 0) {
- return this;
- }
- checkPreconditions(sc);
- nativeDeferTransactionUntilSurface(mNativeObject, sc.mNativeObject,
- barrierSurface.mNativeObject, frameNumber);
- return this;
- }
-
- /**
- * @hide
- */
public Transaction reparentChildren(SurfaceControl sc, SurfaceControl newParent) {
checkPreconditions(sc);
nativeReparentChildren(mNativeObject, sc.mNativeObject, newParent.mNativeObject);
@@ -3341,6 +3324,19 @@
}
/**
+ * Sets the frame timeline vsync id received from choreographer
+ * {@link Choreographer#getVsyncId()} that corresponds to the transaction submitted on that
+ * surface control.
+ *
+ * @hide
+ */
+ @NonNull
+ public Transaction setFrameTimelineVsync(long frameTimelineVsyncId) {
+ nativeSetFrameTimelineVsync(mNativeObject, frameTimelineVsyncId);
+ return this;
+ }
+
+ /**
* Writes the transaction to parcel, clearing the transaction as if it had been applied so
* it can be used to store future transactions. It's the responsibility of the parcel
* reader to apply the original transaction.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b653d21..e00ff7e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -78,6 +78,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
+import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorProto.ClientSideProto.IME_FOCUS_CONTROLLER;
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodEditorProto.ClientSideProto.INSETS_CONTROLLER;
@@ -2707,7 +2708,13 @@
updateColorModeIfNeeded(lp.getColorMode());
surfaceCreated = !hadSurface && mSurface.isValid();
surfaceDestroyed = hadSurface && !mSurface.isValid();
- surfaceReplaced = (surfaceGenerationId != mSurface.getGenerationId())
+ // When using Blast, the surface generation id may not change when there's a new
+ // SurfaceControl. In that case, we also check relayout flag
+ // RELAYOUT_RES_SURFACE_CHANGED since it should indicate that WMS created a new
+ // SurfaceControl.
+ surfaceReplaced = (surfaceGenerationId != mSurface.getGenerationId()
+ || (relayoutResult & RELAYOUT_RES_SURFACE_CHANGED)
+ == RELAYOUT_RES_SURFACE_CHANGED)
&& mSurface.isValid();
if (cutoutChanged) {
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
index d8f2bb2..a7cb642 100644
--- a/core/java/android/window/TaskOrganizer.java
+++ b/core/java/android/window/TaskOrganizer.java
@@ -39,13 +39,14 @@
private ITaskOrganizerController mTaskOrganizerController;
public TaskOrganizer() {
- mTaskOrganizerController = getController();
+ this(null);
}
/** @hide */
@VisibleForTesting
public TaskOrganizer(ITaskOrganizerController taskOrganizerController) {
- mTaskOrganizerController = taskOrganizerController;
+ mTaskOrganizerController = taskOrganizerController != null
+ ? taskOrganizerController : getController();
}
/**
diff --git a/core/java/com/android/ims/internal/uce/presence/PresCmdId.aidl b/core/java/com/android/ims/internal/uce/presence/PresCmdID.aidl
similarity index 100%
rename from core/java/com/android/ims/internal/uce/presence/PresCmdId.aidl
rename to core/java/com/android/ims/internal/uce/presence/PresCmdID.aidl
diff --git a/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java b/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java
index 900e18d..28a9601 100644
--- a/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java
+++ b/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java
@@ -166,7 +166,7 @@
// Now fetch app icon and raster with no badging even in work profile
Bitmap appIcon = mSelectableTargetInfoCommunicator.makePresentationGetter(info)
- .getIconBitmap(UserHandle.getUserHandleForUid(UserHandle.myUserId()));
+ .getIconBitmap(android.os.Process.myUserHandle());
// Raster target drawable with appIcon as a badge
SimpleIconFactory sif = SimpleIconFactory.obtain(mContext);
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index e60f7fc..dd4409c 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -44,26 +44,37 @@
private static final long DEFAULT_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(5L);
// Every value must have a corresponding entry in CUJ_STATSD_INTERACTION_TYPE.
- public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE = 1;
- public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE_LOCK = 0;
- public static final int CUJ_NOTIFICATION_SHADE_SCROLL_FLING = 0;
- public static final int CUJ_NOTIFICATION_SHADE_ROW_EXPAND = 0;
- public static final int CUJ_NOTIFICATION_SHADE_ROW_SWIPE = 0;
- public static final int CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE = 0;
- public static final int CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE = 0;
- public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS = 0;
- public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON = 0;
- public static final int CUJ_LAUNCHER_APP_CLOSE_TO_HOME = 0;
- public static final int CUJ_LAUNCHER_APP_CLOSE_TO_PIP = 0;
- public static final int CUJ_LAUNCHER_QUICK_SWITCH = 0;
+ public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE = 0;
+ public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE_LOCK = 1;
+ public static final int CUJ_NOTIFICATION_SHADE_SCROLL_FLING = 2;
+ public static final int CUJ_NOTIFICATION_SHADE_ROW_EXPAND = 3;
+ public static final int CUJ_NOTIFICATION_SHADE_ROW_SWIPE = 4;
+ public static final int CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE = 5;
+ public static final int CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE = 6;
+ public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS = 7;
+ public static final int CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON = 8;
+ public static final int CUJ_LAUNCHER_APP_CLOSE_TO_HOME = 9;
+ public static final int CUJ_LAUNCHER_APP_CLOSE_TO_PIP = 10;
+ public static final int CUJ_LAUNCHER_QUICK_SWITCH = 11;
private static final int NO_STATSD_LOGGING = -1;
// Used to convert CujType to InteractionType enum value for statsd logging.
// Use NO_STATSD_LOGGING in case the measurement for a given CUJ should not be logged to statsd.
- private static final int[] CUJ_TO_STATSD_INTERACTION_TYPE = {
- NO_STATSD_LOGGING,
+ @VisibleForTesting
+ public static final int[] CUJ_TO_STATSD_INTERACTION_TYPE = {
UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__NOTIFICATION_SHADE_SWIPE,
+ NO_STATSD_LOGGING,
+ NO_STATSD_LOGGING,
+ NO_STATSD_LOGGING,
+ NO_STATSD_LOGGING,
+ NO_STATSD_LOGGING,
+ NO_STATSD_LOGGING,
+ NO_STATSD_LOGGING,
+ NO_STATSD_LOGGING,
+ NO_STATSD_LOGGING,
+ NO_STATSD_LOGGING,
+ NO_STATSD_LOGGING,
};
private static volatile InteractionJankMonitor sInstance;
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 095882e..60f1b44 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -36,7 +36,6 @@
import com.android.server.NetworkManagementSocketTagger;
import dalvik.system.RuntimeHooks;
-import dalvik.system.ThreadPrioritySetter;
import dalvik.system.VMRuntime;
import libcore.content.type.MimeMap;
@@ -208,7 +207,6 @@
*/
public static void preForkInit() {
if (DEBUG) Slog.d(TAG, "Entered preForkInit.");
- RuntimeHooks.setThreadPrioritySetter(new RuntimeThreadPrioritySetter());
RuntimeInit.enableDdms();
// TODO(b/142019040#comment13): Decide whether to load the default instance eagerly, i.e.
// MimeMap.setDefault(DefaultMimeMapFactory.create());
@@ -221,35 +219,6 @@
MimeMap.setDefaultSupplier(DefaultMimeMapFactory::create);
}
- private static class RuntimeThreadPrioritySetter implements ThreadPrioritySetter {
- // Should remain consistent with kNiceValues[] in system/libartpalette/palette_android.cc
- private static final int[] NICE_VALUES = {
- Process.THREAD_PRIORITY_LOWEST, // 1 (MIN_PRIORITY)
- Process.THREAD_PRIORITY_BACKGROUND + 6,
- Process.THREAD_PRIORITY_BACKGROUND + 3,
- Process.THREAD_PRIORITY_BACKGROUND,
- Process.THREAD_PRIORITY_DEFAULT, // 5 (NORM_PRIORITY)
- Process.THREAD_PRIORITY_DEFAULT - 2,
- Process.THREAD_PRIORITY_DEFAULT - 4,
- Process.THREAD_PRIORITY_URGENT_DISPLAY + 3,
- Process.THREAD_PRIORITY_URGENT_DISPLAY + 2,
- Process.THREAD_PRIORITY_URGENT_DISPLAY // 10 (MAX_PRIORITY)
- };
-
- @Override
- public void setPriority(int nativeTid, int priority) {
- // Check NICE_VALUES[] length first.
- if (NICE_VALUES.length != (1 + Thread.MAX_PRIORITY - Thread.MIN_PRIORITY)) {
- throw new AssertionError("Unexpected NICE_VALUES.length=" + NICE_VALUES.length);
- }
- // Priority should be in the range of MIN_PRIORITY (1) to MAX_PRIORITY (10).
- if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
- throw new IllegalArgumentException("Priority out of range: " + priority);
- }
- Process.setThreadPriority(nativeTid, NICE_VALUES[priority - Thread.MIN_PRIORITY]);
- }
- }
-
@UnsupportedAppUsage
protected static final void commonInit() {
if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index a985965..5e20cd0 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -172,23 +172,11 @@
public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE;
/** Default external storage should be mounted. */
public static final int MOUNT_EXTERNAL_DEFAULT = IVold.REMOUNT_MODE_DEFAULT;
- /** Read-only external storage should be mounted. */
- public static final int MOUNT_EXTERNAL_READ = IVold.REMOUNT_MODE_READ;
- /** Read-write external storage should be mounted. */
- public static final int MOUNT_EXTERNAL_WRITE = IVold.REMOUNT_MODE_WRITE;
- /**
- * Mount mode for apps that are already installed on the device before the isolated_storage
- * feature is enabled.
- */
- public static final int MOUNT_EXTERNAL_LEGACY = IVold.REMOUNT_MODE_LEGACY;
/**
* Mount mode for package installers which should give them access to
* all obb dirs in addition to their package sandboxes
*/
public static final int MOUNT_EXTERNAL_INSTALLER = IVold.REMOUNT_MODE_INSTALLER;
- /** Read-write external storage should be mounted instead of package sandbox */
- public static final int MOUNT_EXTERNAL_FULL = IVold.REMOUNT_MODE_FULL;
-
/** The lower file system should be bind mounted directly on external storage */
public static final int MOUNT_EXTERNAL_PASS_THROUGH = IVold.REMOUNT_MODE_PASS_THROUGH;
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index ed07432..32b808a 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -380,16 +380,8 @@
mNiceName = getAssignmentValue(arg);
} else if (arg.equals("--mount-external-default")) {
mMountExternal = Zygote.MOUNT_EXTERNAL_DEFAULT;
- } else if (arg.equals("--mount-external-read")) {
- mMountExternal = Zygote.MOUNT_EXTERNAL_READ;
- } else if (arg.equals("--mount-external-write")) {
- mMountExternal = Zygote.MOUNT_EXTERNAL_WRITE;
- } else if (arg.equals("--mount-external-full")) {
- mMountExternal = Zygote.MOUNT_EXTERNAL_FULL;
- } else if (arg.equals("--mount-external-installer")) {
+ } else if (arg.equals("--mount-external-installer")) {
mMountExternal = Zygote.MOUNT_EXTERNAL_INSTALLER;
- } else if (arg.equals("--mount-external-legacy")) {
- mMountExternal = Zygote.MOUNT_EXTERNAL_LEGACY;
} else if (arg.equals("--mount-external-pass-through")) {
mMountExternal = Zygote.MOUNT_EXTERNAL_PASS_THROUGH;
} else if (arg.equals("--mount-external-android-writable")) {
diff --git a/core/java/com/android/internal/protolog/ProtoLogGroup.java b/core/java/com/android/internal/protolog/ProtoLogGroup.java
index 50ba42f..ce3efd3 100644
--- a/core/java/com/android/internal/protolog/ProtoLogGroup.java
+++ b/core/java/com/android/internal/protolog/ProtoLogGroup.java
@@ -48,6 +48,10 @@
Consts.TAG_WM),
WM_DEBUG_LOCKTASK(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
Consts.TAG_WM),
+ WM_DEBUG_STATES(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
+ Consts.TAG_WM),
+ WM_DEBUG_TASKS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
+ Consts.TAG_WM),
WM_DEBUG_STARTING_WINDOW(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
Consts.TAG_WM),
WM_SHOW_TRANSACTIONS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index cd69a02..f317f3f 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -760,6 +760,7 @@
/**
* Returns an array containing elements from the given one that match the given predicate.
+ * The returned array may, in some cases, be the reference to the input array.
*/
public static @Nullable <T> T[] filter(@Nullable T[] items,
@NonNull IntFunction<T[]> arrayConstructor,
@@ -775,16 +776,13 @@
matchesCount++;
}
}
- if (matchesCount == 0) {
- return items;
- }
if (matchesCount == items.length) {
return items;
}
- if (matchesCount == 0) {
- return null;
- }
T[] result = arrayConstructor.apply(matchesCount);
+ if (matchesCount == 0) {
+ return result;
+ }
int outIdx = 0;
for (int i = 0; i < size; i++) {
if (predicate.test(items[i])) {
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 0892b70..355ef0c 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -612,50 +612,77 @@
return ret;
}
+// String tries to allocate itself on the stack, within a known size, but will
+// make a heap allocation if not.
+template <size_t StackReserve>
+class StackString {
+public:
+ StackString(JNIEnv* env, jstring str) : mEnv(env), mJStr(str) {
+ LOG_ALWAYS_FATAL_IF(str == nullptr);
+ mSize = env->GetStringLength(str);
+ if (mSize > StackReserve) {
+ mStr = new jchar[mSize];
+ } else {
+ mStr = &mBuffer[0];
+ }
+ mEnv->GetStringRegion(str, 0, mSize, mStr);
+ }
+ ~StackString() {
+ if (mStr != &mBuffer[0]) {
+ delete[] mStr;
+ }
+ }
+ const jchar* str() { return mStr; }
+ jsize size() { return mSize; }
+
+private:
+ JNIEnv* mEnv;
+ jstring mJStr;
+
+ jchar mBuffer[StackReserve];
+ // pointer to &mBuffer[0] if string fits in mBuffer, otherwise owned
+ jchar* mStr;
+ jsize mSize;
+};
+
+// This size is chosen to be longer than most interface descriptors.
+// Ones longer than this will be allocated on the heap.
+typedef StackString<64> InterfaceDescriptorString;
+
static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr,
jstring name)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
- if (parcel != NULL) {
- // In the current implementation, the token is just the serialized interface name that
- // the caller expects to be invoking
- const jchar* str = env->GetStringCritical(name, 0);
- if (str != NULL) {
- parcel->writeInterfaceToken(String16(
- reinterpret_cast<const char16_t*>(str),
- env->GetStringLength(name)));
- env->ReleaseStringCritical(name, str);
- }
+ if (parcel != nullptr) {
+ InterfaceDescriptorString descriptor(env, name);
+ parcel->writeInterfaceToken(reinterpret_cast<const char16_t*>(descriptor.str()),
+ descriptor.size());
}
}
static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
- if (parcel != NULL) {
- const jchar* str = env->GetStringCritical(name, 0);
- if (str) {
- IPCThreadState* threadState = IPCThreadState::self();
- const int32_t oldPolicy = threadState->getStrictModePolicy();
- const bool isValid = parcel->enforceInterface(
- reinterpret_cast<const char16_t*>(str),
- env->GetStringLength(name),
- threadState);
- env->ReleaseStringCritical(name, str);
- if (isValid) {
- const int32_t newPolicy = threadState->getStrictModePolicy();
- if (oldPolicy != newPolicy) {
- // Need to keep the Java-level thread-local strict
- // mode policy in sync for the libcore
- // enforcements, which involves an upcall back
- // into Java. (We can't modify the
- // Parcel.enforceInterface signature, as it's
- // pseudo-public, and used via AIDL
- // auto-generation...)
- set_dalvik_blockguard_policy(env, newPolicy);
- }
- return; // everything was correct -> return silently
+ if (parcel != nullptr) {
+ InterfaceDescriptorString descriptor(env, name);
+ IPCThreadState* threadState = IPCThreadState::self();
+ const int32_t oldPolicy = threadState->getStrictModePolicy();
+ const bool isValid =
+ parcel->enforceInterface(reinterpret_cast<const char16_t*>(descriptor.str()),
+ descriptor.size(), threadState);
+ if (isValid) {
+ const int32_t newPolicy = threadState->getStrictModePolicy();
+ if (oldPolicy != newPolicy) {
+ // Need to keep the Java-level thread-local strict
+ // mode policy in sync for the libcore
+ // enforcements, which involves an upcall back
+ // into Java. (We can't modify the
+ // Parcel.enforceInterface signature, as it's
+ // pseudo-public, and used via AIDL
+ // auto-generation...)
+ set_dalvik_blockguard_policy(env, newPolicy);
}
+ return; // everything was correct -> return silently
}
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 5de30a2..1419855 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -481,7 +481,7 @@
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
auto relative = reinterpret_cast<SurfaceControl *>(relativeToObject);
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
- transaction->setRelativeLayer(ctrl, relative->getHandle(), zorder);
+ transaction->setRelativeLayer(ctrl, relative, zorder);
}
static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong transactionObj,
@@ -1327,20 +1327,9 @@
static void nativeDeferTransactionUntil(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jlong barrierObject, jlong frameNumber) {
- auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- auto barrier = reinterpret_cast<SurfaceControl *>(barrierObject);
+ sp<SurfaceControl> ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+ sp<SurfaceControl> barrier = reinterpret_cast<SurfaceControl*>(barrierObject);
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
- transaction->deferTransactionUntil_legacy(ctrl, barrier->getHandle(), frameNumber);
-}
-
-static void nativeDeferTransactionUntilSurface(JNIEnv* env, jclass clazz, jlong transactionObj,
- jlong nativeObject,
- jlong surfaceObject, jlong frameNumber) {
- auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
-
- auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- sp<Surface> barrier = reinterpret_cast<Surface *>(surfaceObject);
-
transaction->deferTransactionUntil_legacy(ctrl, barrier, frameNumber);
}
@@ -1351,7 +1340,7 @@
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
auto newParent = reinterpret_cast<SurfaceControl *>(newParentObject);
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
- transaction->reparentChildren(ctrl, newParent->getHandle());
+ transaction->reparentChildren(ctrl, newParent);
}
static void nativeReparent(JNIEnv* env, jclass clazz, jlong transactionObj,
@@ -1360,7 +1349,7 @@
auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
auto newParent = reinterpret_cast<SurfaceControl *>(newParentObject);
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
- transaction->reparent(ctrl, newParent != NULL ? newParent->getHandle() : NULL);
+ transaction->reparent(ctrl, newParent);
}
static void nativeSeverChildren(JNIEnv* env, jclass clazz, jlong transactionObj,
@@ -1558,6 +1547,13 @@
displayId);
}
+static void nativeSetFrameTimelineVsync(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong frameTimelineVsyncId) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
+ transaction->setFrameTimelineVsync(frameTimelineVsyncId);
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod sSurfaceControlMethods[] = {
@@ -1692,8 +1688,6 @@
(void*)nativeGetProtectedContentSupport },
{"nativeDeferTransactionUntil", "(JJJJ)V",
(void*)nativeDeferTransactionUntil },
- {"nativeDeferTransactionUntilSurface", "(JJJJ)V",
- (void*)nativeDeferTransactionUntilSurface },
{"nativeReparentChildren", "(JJJ)V",
(void*)nativeReparentChildren } ,
{"nativeReparent", "(JJJ)V",
@@ -1742,6 +1736,8 @@
(void*)nativeSetFixedTransformHint},
{"nativeSetFocusedWindow", "(JLandroid/os/IBinder;Landroid/os/IBinder;I)V",
(void*)nativeSetFocusedWindow},
+ {"nativeSetFrameTimelineVsync", "(JJ)V",
+ (void*)nativeSetFrameTimelineVsync },
// clang-format on
};
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index e6bfecc..42aab6a 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -326,31 +326,15 @@
static FileDescriptorTable* gOpenFdTable = nullptr;
// Must match values in com.android.internal.os.Zygote.
-// The order of entries here must be kept in sync with ExternalStorageViews array values.
+// Note that there are gaps in the constants:
+// This is to further keep the values consistent with IVold.aidl
enum MountExternalKind {
- MOUNT_EXTERNAL_NONE = 0,
- MOUNT_EXTERNAL_DEFAULT = 1,
- MOUNT_EXTERNAL_READ = 2,
- MOUNT_EXTERNAL_WRITE = 3,
- MOUNT_EXTERNAL_LEGACY = 4,
- MOUNT_EXTERNAL_INSTALLER = 5,
- MOUNT_EXTERNAL_FULL = 6,
- MOUNT_EXTERNAL_PASS_THROUGH = 7,
- MOUNT_EXTERNAL_ANDROID_WRITABLE = 8,
- MOUNT_EXTERNAL_COUNT = 9
-};
-
-// The order of entries here must be kept in sync with MountExternalKind enum values.
-static const std::array<const std::string, MOUNT_EXTERNAL_COUNT> ExternalStorageViews = {
- "", // MOUNT_EXTERNAL_NONE
- "/mnt/runtime/default", // MOUNT_EXTERNAL_DEFAULT
- "/mnt/runtime/read", // MOUNT_EXTERNAL_READ
- "/mnt/runtime/write", // MOUNT_EXTERNAL_WRITE
- "/mnt/runtime/write", // MOUNT_EXTERNAL_LEGACY
- "/mnt/runtime/write", // MOUNT_EXTERNAL_INSTALLER
- "/mnt/runtime/full", // MOUNT_EXTERNAL_FULL
- "/mnt/runtime/full", // MOUNT_EXTERNAL_PASS_THROUGH (only used w/ FUSE)
- "/mnt/runtime/full", // MOUNT_EXTERNAL_ANDROID_WRITABLE (only used w/ FUSE)
+ MOUNT_EXTERNAL_NONE = 0,
+ MOUNT_EXTERNAL_DEFAULT = 1,
+ MOUNT_EXTERNAL_INSTALLER = 5,
+ MOUNT_EXTERNAL_PASS_THROUGH = 7,
+ MOUNT_EXTERNAL_ANDROID_WRITABLE = 8,
+ MOUNT_EXTERNAL_COUNT = 9
};
// Must match values in com.android.internal.os.Zygote.
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index d4d8772..d315ff2 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -205,9 +205,8 @@
optional WindowStateProto input_method_input_target = 28;
optional WindowStateProto input_method_control_target = 29;
optional WindowStateProto current_focus = 30;
- optional InsetsSourceProviderProto insets_source_provider = 31;
- optional ImeInsetsSourceProviderProto ime_insets_source_provider = 32;
- optional bool can_show_ime = 33;
+ optional ImeInsetsSourceProviderProto ime_insets_source_provider = 31;
+ optional bool can_show_ime = 32;
}
/* represents DisplayArea object */
@@ -527,6 +526,7 @@
message ImeInsetsSourceProviderProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
- optional WindowStateProto ime_target_from_ime = 1;
- optional bool is_ime_layout_drawn = 2;
+ optional InsetsSourceProviderProto insets_source_provider = 1;
+ optional WindowStateProto ime_target_from_ime = 2;
+ optional bool is_ime_layout_drawn = 3;
}
\ No newline at end of file
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto
index 004b096..d289e00 100644
--- a/core/proto/android/service/package.proto
+++ b/core/proto/android/service/package.proto
@@ -124,6 +124,11 @@
optional string originating_package_name = 2;
}
+ message StatesProto {
+ optional bool is_startable = 1;
+ optional bool is_loading = 2;
+ }
+
// Name of package. e.g. "com.android.providers.telephony".
optional string name = 1;
// UID for this package as assigned by Android OS.
@@ -145,4 +150,6 @@
repeated UserInfoProto users = 9;
// Where the request to install this package came from,
optional InstallSourceProto install_source = 10;
+ // Whether the package is startable or is still loading
+ optional StatesProto states = 11;
}
diff --git a/core/proto/android/view/inputmethod/inputmethodeditortrace.proto b/core/proto/android/view/inputmethod/inputmethodeditortrace.proto
index 2729e82..856d8da 100644
--- a/core/proto/android/view/inputmethod/inputmethodeditortrace.proto
+++ b/core/proto/android/view/inputmethod/inputmethodeditortrace.proto
@@ -65,8 +65,6 @@
repeated ClientSideProto client = 1;
}
- /* todo: extract as a separate message to allow other dumps to use this as their client side
- proto */
/* groups together the dump from ime related client side classes */
message ClientSideProto {
optional int32 display_id = 1;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7247e4f..c8b8ef2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -42,6 +42,9 @@
<protected-broadcast android:name="android.intent.action.PACKAGE_REMOVED" />
<protected-broadcast android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
<protected-broadcast android:name="android.intent.action.PACKAGE_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_STARTABLE" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_UNSTARTABLE" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_FULLY_LOADED" />
<protected-broadcast android:name="android.intent.action.PACKAGE_ENABLE_ROLLBACK" />
<protected-broadcast android:name="android.intent.action.CANCEL_ENABLE_ROLLBACK" />
<protected-broadcast android:name="android.intent.action.ROLLBACK_COMMITTED" />
@@ -1575,6 +1578,13 @@
<permission android:name="android.permission.INSTALL_LOCATION_PROVIDER"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi @hide Allows an application to install a LocationTimeZoneProvider into the
+ LocationTimeZoneProviderManager.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.INSTALL_LOCATION_TIME_ZONE_PROVIDER"
+ android:protectionLevel="signature|privileged" />
+
<!-- @SystemApi @hide Allows HDMI-CEC service to access device and configuration files.
This should only be used by HDMI-CEC service.
-->
@@ -2712,7 +2722,7 @@
<!-- Allows applications like settings to manage configuration associated with automatic time
and time zone detection.
<p>Not for use by third-party applications.
- @hide
+ @SystemApi @hide
-->
<permission android:name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION"
android:protectionLevel="signature|privileged" />
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 60f7a09..fac2f22 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -432,23 +432,17 @@
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"change your audio settings"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"record audio"</string>
- <!-- no translation found for permdesc_recordAudio (5857246765327514062) -->
- <skip />
- <!-- no translation found for permlab_recordBackgroundAudio (5891032812308878254) -->
- <skip />
- <!-- no translation found for permdesc_recordBackgroundAudio (1992623135737407516) -->
- <skip />
+ <string name="permdesc_recordAudio" msgid="5857246765327514062">"This app can record audio using the microphone while the app is in use."</string>
+ <string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"record audio in the background"</string>
+ <string name="permdesc_recordBackgroundAudio" msgid="1992623135737407516">"This app can record audio using the microphone at any time."</string>
<string name="permlab_sim_communication" msgid="176788115994050692">"send commands to the SIM"</string>
<string name="permdesc_sim_communication" msgid="4179799296415957960">"Allows the app to send commands to the SIM. This is very dangerous."</string>
<string name="permlab_activityRecognition" msgid="1782303296053990884">"recognise physical activity"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"This app can recognise your physical activity."</string>
<string name="permlab_camera" msgid="6320282492904119413">"take pictures and videos"</string>
- <!-- no translation found for permdesc_camera (5240801376168647151) -->
- <skip />
- <!-- no translation found for permlab_backgroundCamera (7549917926079731681) -->
- <skip />
- <!-- no translation found for permdesc_backgroundCamera (1615291686191138250) -->
- <skip />
+ <string name="permdesc_camera" msgid="5240801376168647151">"This app can take pictures and record videos using the camera while the app is in use."</string>
+ <string name="permlab_backgroundCamera" msgid="7549917926079731681">"take pictures and videos in the background"</string>
+ <string name="permdesc_backgroundCamera" msgid="1615291686191138250">"This app can take pictures and record videos using the camera at any time."</string>
<string name="permlab_systemCamera" msgid="3642917457796210580">"Grant an application or service access to system cameras to take pictures and videos"</string>
<string name="permdesc_systemCamera" msgid="5938360914419175986">"This privileged or system app can take pictures and record videos using a system camera at any time. Requires the android.permission.CAMERA permission to be held by the app as well"</string>
<string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"Allow an application or service to receive callbacks about camera devices being opened or closed."</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index ae3aaab..8497658 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -432,23 +432,17 @@
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"change your audio settings"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"record audio"</string>
- <!-- no translation found for permdesc_recordAudio (5857246765327514062) -->
- <skip />
- <!-- no translation found for permlab_recordBackgroundAudio (5891032812308878254) -->
- <skip />
- <!-- no translation found for permdesc_recordBackgroundAudio (1992623135737407516) -->
- <skip />
+ <string name="permdesc_recordAudio" msgid="5857246765327514062">"This app can record audio using the microphone while the app is in use."</string>
+ <string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"record audio in the background"</string>
+ <string name="permdesc_recordBackgroundAudio" msgid="1992623135737407516">"This app can record audio using the microphone at any time."</string>
<string name="permlab_sim_communication" msgid="176788115994050692">"send commands to the SIM"</string>
<string name="permdesc_sim_communication" msgid="4179799296415957960">"Allows the app to send commands to the SIM. This is very dangerous."</string>
<string name="permlab_activityRecognition" msgid="1782303296053990884">"recognise physical activity"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"This app can recognise your physical activity."</string>
<string name="permlab_camera" msgid="6320282492904119413">"take pictures and videos"</string>
- <!-- no translation found for permdesc_camera (5240801376168647151) -->
- <skip />
- <!-- no translation found for permlab_backgroundCamera (7549917926079731681) -->
- <skip />
- <!-- no translation found for permdesc_backgroundCamera (1615291686191138250) -->
- <skip />
+ <string name="permdesc_camera" msgid="5240801376168647151">"This app can take pictures and record videos using the camera while the app is in use."</string>
+ <string name="permlab_backgroundCamera" msgid="7549917926079731681">"take pictures and videos in the background"</string>
+ <string name="permdesc_backgroundCamera" msgid="1615291686191138250">"This app can take pictures and record videos using the camera at any time."</string>
<string name="permlab_systemCamera" msgid="3642917457796210580">"Grant an application or service access to system cameras to take pictures and videos"</string>
<string name="permdesc_systemCamera" msgid="5938360914419175986">"This privileged or system app can take pictures and record videos using a system camera at any time. Requires the android.permission.CAMERA permission to be held by the app as well"</string>
<string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"Allow an application or service to receive callbacks about camera devices being opened or closed."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 52dcf97..12881e7 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -432,23 +432,17 @@
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"change your audio settings"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"record audio"</string>
- <!-- no translation found for permdesc_recordAudio (5857246765327514062) -->
- <skip />
- <!-- no translation found for permlab_recordBackgroundAudio (5891032812308878254) -->
- <skip />
- <!-- no translation found for permdesc_recordBackgroundAudio (1992623135737407516) -->
- <skip />
+ <string name="permdesc_recordAudio" msgid="5857246765327514062">"This app can record audio using the microphone while the app is in use."</string>
+ <string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"record audio in the background"</string>
+ <string name="permdesc_recordBackgroundAudio" msgid="1992623135737407516">"This app can record audio using the microphone at any time."</string>
<string name="permlab_sim_communication" msgid="176788115994050692">"send commands to the SIM"</string>
<string name="permdesc_sim_communication" msgid="4179799296415957960">"Allows the app to send commands to the SIM. This is very dangerous."</string>
<string name="permlab_activityRecognition" msgid="1782303296053990884">"recognise physical activity"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"This app can recognise your physical activity."</string>
<string name="permlab_camera" msgid="6320282492904119413">"take pictures and videos"</string>
- <!-- no translation found for permdesc_camera (5240801376168647151) -->
- <skip />
- <!-- no translation found for permlab_backgroundCamera (7549917926079731681) -->
- <skip />
- <!-- no translation found for permdesc_backgroundCamera (1615291686191138250) -->
- <skip />
+ <string name="permdesc_camera" msgid="5240801376168647151">"This app can take pictures and record videos using the camera while the app is in use."</string>
+ <string name="permlab_backgroundCamera" msgid="7549917926079731681">"take pictures and videos in the background"</string>
+ <string name="permdesc_backgroundCamera" msgid="1615291686191138250">"This app can take pictures and record videos using the camera at any time."</string>
<string name="permlab_systemCamera" msgid="3642917457796210580">"Grant an application or service access to system cameras to take pictures and videos"</string>
<string name="permdesc_systemCamera" msgid="5938360914419175986">"This privileged or system app can take pictures and record videos using a system camera at any time. Requires the android.permission.CAMERA permission to be held by the app as well"</string>
<string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"Allow an application or service to receive callbacks about camera devices being opened or closed."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 2f7f271..cb2eb7a 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -432,23 +432,17 @@
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"change your audio settings"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"record audio"</string>
- <!-- no translation found for permdesc_recordAudio (5857246765327514062) -->
- <skip />
- <!-- no translation found for permlab_recordBackgroundAudio (5891032812308878254) -->
- <skip />
- <!-- no translation found for permdesc_recordBackgroundAudio (1992623135737407516) -->
- <skip />
+ <string name="permdesc_recordAudio" msgid="5857246765327514062">"This app can record audio using the microphone while the app is in use."</string>
+ <string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"record audio in the background"</string>
+ <string name="permdesc_recordBackgroundAudio" msgid="1992623135737407516">"This app can record audio using the microphone at any time."</string>
<string name="permlab_sim_communication" msgid="176788115994050692">"send commands to the SIM"</string>
<string name="permdesc_sim_communication" msgid="4179799296415957960">"Allows the app to send commands to the SIM. This is very dangerous."</string>
<string name="permlab_activityRecognition" msgid="1782303296053990884">"recognise physical activity"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"This app can recognise your physical activity."</string>
<string name="permlab_camera" msgid="6320282492904119413">"take pictures and videos"</string>
- <!-- no translation found for permdesc_camera (5240801376168647151) -->
- <skip />
- <!-- no translation found for permlab_backgroundCamera (7549917926079731681) -->
- <skip />
- <!-- no translation found for permdesc_backgroundCamera (1615291686191138250) -->
- <skip />
+ <string name="permdesc_camera" msgid="5240801376168647151">"This app can take pictures and record videos using the camera while the app is in use."</string>
+ <string name="permlab_backgroundCamera" msgid="7549917926079731681">"take pictures and videos in the background"</string>
+ <string name="permdesc_backgroundCamera" msgid="1615291686191138250">"This app can take pictures and record videos using the camera at any time."</string>
<string name="permlab_systemCamera" msgid="3642917457796210580">"Grant an application or service access to system cameras to take pictures and videos"</string>
<string name="permdesc_systemCamera" msgid="5938360914419175986">"This privileged or system app can take pictures and record videos using a system camera at any time. Requires the android.permission.CAMERA permission to be held by the app as well"</string>
<string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"Allow an application or service to receive callbacks about camera devices being opened or closed."</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 8f017f9..5750e50 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -432,23 +432,17 @@
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"change your audio settings"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"record audio"</string>
- <!-- no translation found for permdesc_recordAudio (5857246765327514062) -->
- <skip />
- <!-- no translation found for permlab_recordBackgroundAudio (5891032812308878254) -->
- <skip />
- <!-- no translation found for permdesc_recordBackgroundAudio (1992623135737407516) -->
- <skip />
+ <string name="permdesc_recordAudio" msgid="5857246765327514062">"This app can record audio using the microphone while the app is in use."</string>
+ <string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"record audio in the background"</string>
+ <string name="permdesc_recordBackgroundAudio" msgid="1992623135737407516">"This app can record audio using the microphone at any time."</string>
<string name="permlab_sim_communication" msgid="176788115994050692">"send commands to the SIM"</string>
<string name="permdesc_sim_communication" msgid="4179799296415957960">"Allows the app to send commands to the SIM. This is very dangerous."</string>
<string name="permlab_activityRecognition" msgid="1782303296053990884">"recognize physical activity"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"This app can recognize your physical activity."</string>
<string name="permlab_camera" msgid="6320282492904119413">"take pictures and videos"</string>
- <!-- no translation found for permdesc_camera (5240801376168647151) -->
- <skip />
- <!-- no translation found for permlab_backgroundCamera (7549917926079731681) -->
- <skip />
- <!-- no translation found for permdesc_backgroundCamera (1615291686191138250) -->
- <skip />
+ <string name="permdesc_camera" msgid="5240801376168647151">"This app can take pictures and record videos using the camera while the app is in use."</string>
+ <string name="permlab_backgroundCamera" msgid="7549917926079731681">"take pictures and videos in the background"</string>
+ <string name="permdesc_backgroundCamera" msgid="1615291686191138250">"This app can take pictures and record videos using the camera at any time."</string>
<string name="permlab_systemCamera" msgid="3642917457796210580">"Allow an application or service access to system cameras to take pictures and videos"</string>
<string name="permdesc_systemCamera" msgid="5938360914419175986">"This privileged or system app can take pictures and record videos using a system camera at any time. Requires the android.permission.CAMERA permission to be held by the app as well"</string>
<string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"Allow an application or service to receive callbacks about camera devices being opened or closed."</string>
diff --git a/core/res/res/values-mcc310-mnc150-as/strings.xml b/core/res/res/values-mcc310-mnc150-as/strings.xml
new file mode 100644
index 0000000..2a4e46bd6
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc150-as/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_illegal_me" msgid="8004509200390992737">"ফ\'নৰ অনুমতি নাই MM#6"</string>
+</resources>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index b327342..7b376ff 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1632,12 +1632,10 @@
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"सिफारिस तहभन्दा आवाज ठुलो गर्नुहुन्छ?\n\nलामो समय सम्म उच्च आवाजमा सुन्दा तपाईँको सुन्ने शक्तिलाई हानी गर्न सक्छ।"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"पहुँच सम्बन्धी सर्टकट प्रयोग गर्ने हो?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"यो सर्टकट सक्रिय हुँदा, ३ सेकेन्डसम्म दुवै भोल्युम बटन थिच्नुले पहुँचसम्बन्धी कुनै सुविधा सुरु गर्ने छ।"</string>
- <!-- no translation found for accessibility_shortcut_multiple_service_warning_title (3135860819356676426) -->
- <skip />
+ <string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"सर्वसुलभता कायम गर्ने सुविधाहरू प्रयोग गर्न सर्टकट अन गर्ने हो?"</string>
<string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"केही सेकेन्डसम्म दुवै भोल्युम बटन थिचिराख्नुभयो भने पहुँचसम्बन्धी सुविधाहरू सक्रिय हुन्छ। यसले तपाईंको यन्त्रले काम गर्ने तरिका परिवर्तन गर्न सक्छ।\n\nहालका सुविधाहरू:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nतपाईं सेटिङ > पहुँचमा गएर चयन गरिएका सुविधाहरू परिवर्तन गर्न सक्नुहुन्छ।"</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
- <!-- no translation found for accessibility_shortcut_single_service_warning_title (1909518473488345266) -->
- <skip />
+ <string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> प्रयोग गर्न सर्टकट अन गर्ने हो?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"केही सेकेन्डसम्म दुवै भोल्युम बटन थिचिराख्नुले <xliff:g id="SERVICE">%1$s</xliff:g> नामक पहुँचसम्बन्धी सुविधा सक्रिय गर्छ। यसले तपाईंको यन्त्रले काम गर्ने तरिका परिवर्तन गर्न सक्छ।\n\nतपाईं सेटिङ > पहुँचमा गई यो सर्टकटमार्फत अर्को सुविधा खुल्ने बनाउन सक्नुहुन्छ।"</string>
<string name="accessibility_shortcut_on" msgid="5463618449556111344">"सक्रिय गरियोस्"</string>
<string name="accessibility_shortcut_off" msgid="3651336255403648739">"सक्रिय नगरियोस्"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index f09e7b0..450fddb 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -432,23 +432,17 @@
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"alterar as suas configurações de áudio"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Permite que o app modifique configurações de áudio globais como volume e alto-falantes de saída."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"gravar áudio"</string>
- <!-- no translation found for permdesc_recordAudio (5857246765327514062) -->
- <skip />
- <!-- no translation found for permlab_recordBackgroundAudio (5891032812308878254) -->
- <skip />
- <!-- no translation found for permdesc_recordBackgroundAudio (1992623135737407516) -->
- <skip />
+ <string name="permdesc_recordAudio" msgid="5857246765327514062">"Enquanto está sendo usado, este app pode gravar áudio usando o microfone."</string>
+ <string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"gravar áudio em segundo plano"</string>
+ <string name="permdesc_recordBackgroundAudio" msgid="1992623135737407516">"Este app pode gravar áudio usando o microfone a qualquer momento."</string>
<string name="permlab_sim_communication" msgid="176788115994050692">"enviar comandos para o chip"</string>
<string name="permdesc_sim_communication" msgid="4179799296415957960">"Permite que o app envie comandos ao chip. Muito perigoso."</string>
<string name="permlab_activityRecognition" msgid="1782303296053990884">"reconhecer atividade física"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"Este app pode reconhecer sua atividade física."</string>
<string name="permlab_camera" msgid="6320282492904119413">"tirar fotos e gravar vídeos"</string>
- <!-- no translation found for permdesc_camera (5240801376168647151) -->
- <skip />
- <!-- no translation found for permlab_backgroundCamera (7549917926079731681) -->
- <skip />
- <!-- no translation found for permdesc_backgroundCamera (1615291686191138250) -->
- <skip />
+ <string name="permdesc_camera" msgid="5240801376168647151">"Enquanto está sendo usado, este app pode tirar fotos e gravar vídeos usando a câmera."</string>
+ <string name="permlab_backgroundCamera" msgid="7549917926079731681">"tirar fotos e gravar vídeos em segundo plano"</string>
+ <string name="permdesc_backgroundCamera" msgid="1615291686191138250">"Este app pode tirar fotos e gravar vídeos usando a câmera a qualquer momento."</string>
<string name="permlab_systemCamera" msgid="3642917457796210580">"Permitir que um aplicativo ou serviço acesse as câmeras do sistema para tirar fotos e gravar vídeos"</string>
<string name="permdesc_systemCamera" msgid="5938360914419175986">"Esse app do sistema ou com privilégios pode tirar fotos e gravar vídeos a qualquer momento usando a câmera do sistema. É necessário que o app tenha também a permissão android.permission.CAMERA"</string>
<string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"Permitir que um aplicativo ou serviço receba callbacks sobre dispositivos de câmera sendo abertos ou fechados."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index f09e7b0..450fddb 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -432,23 +432,17 @@
<string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"alterar as suas configurações de áudio"</string>
<string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Permite que o app modifique configurações de áudio globais como volume e alto-falantes de saída."</string>
<string name="permlab_recordAudio" msgid="1208457423054219147">"gravar áudio"</string>
- <!-- no translation found for permdesc_recordAudio (5857246765327514062) -->
- <skip />
- <!-- no translation found for permlab_recordBackgroundAudio (5891032812308878254) -->
- <skip />
- <!-- no translation found for permdesc_recordBackgroundAudio (1992623135737407516) -->
- <skip />
+ <string name="permdesc_recordAudio" msgid="5857246765327514062">"Enquanto está sendo usado, este app pode gravar áudio usando o microfone."</string>
+ <string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"gravar áudio em segundo plano"</string>
+ <string name="permdesc_recordBackgroundAudio" msgid="1992623135737407516">"Este app pode gravar áudio usando o microfone a qualquer momento."</string>
<string name="permlab_sim_communication" msgid="176788115994050692">"enviar comandos para o chip"</string>
<string name="permdesc_sim_communication" msgid="4179799296415957960">"Permite que o app envie comandos ao chip. Muito perigoso."</string>
<string name="permlab_activityRecognition" msgid="1782303296053990884">"reconhecer atividade física"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"Este app pode reconhecer sua atividade física."</string>
<string name="permlab_camera" msgid="6320282492904119413">"tirar fotos e gravar vídeos"</string>
- <!-- no translation found for permdesc_camera (5240801376168647151) -->
- <skip />
- <!-- no translation found for permlab_backgroundCamera (7549917926079731681) -->
- <skip />
- <!-- no translation found for permdesc_backgroundCamera (1615291686191138250) -->
- <skip />
+ <string name="permdesc_camera" msgid="5240801376168647151">"Enquanto está sendo usado, este app pode tirar fotos e gravar vídeos usando a câmera."</string>
+ <string name="permlab_backgroundCamera" msgid="7549917926079731681">"tirar fotos e gravar vídeos em segundo plano"</string>
+ <string name="permdesc_backgroundCamera" msgid="1615291686191138250">"Este app pode tirar fotos e gravar vídeos usando a câmera a qualquer momento."</string>
<string name="permlab_systemCamera" msgid="3642917457796210580">"Permitir que um aplicativo ou serviço acesse as câmeras do sistema para tirar fotos e gravar vídeos"</string>
<string name="permdesc_systemCamera" msgid="5938360914419175986">"Esse app do sistema ou com privilégios pode tirar fotos e gravar vídeos a qualquer momento usando a câmera do sistema. É necessário que o app tenha também a permissão android.permission.CAMERA"</string>
<string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"Permitir que um aplicativo ou serviço receba callbacks sobre dispositivos de câmera sendo abertos ou fechados."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index fc2fd35..d074960 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1325,7 +1325,7 @@
<string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"Отмена"</string>
<string name="sms_short_code_remember_choice" msgid="1374526438647744862">"Запомнить выбор"</string>
<string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"Это можно изменить позже в разделе настроек \"Приложения\"."</string>
- <string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"Всегда разрешать"</string>
+ <string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"Разрешать всегда"</string>
<string name="sms_short_code_confirm_never_allow" msgid="2688828813521652079">"Не разрешать"</string>
<string name="sim_removed_title" msgid="5387212933992546283">"SIM-карта удалена"</string>
<string name="sim_removed_message" msgid="9051174064474904617">"Пока вы не вставите действующую SIM-карту, мобильная сеть будет недоступна."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 20ef017f..644ed3a 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -9180,21 +9180,32 @@
<attr name="fontVariationSettings" format="string" />
</declare-styleable>
- <!-- Attributes that are read when parsing a <fontfamily> tag. -->
+ <!-- Attributes that are read when parsing a <fontfamily> tag.
+ {@deprecated Use Jetpack Core library instead.}
+ -->
<declare-styleable name="FontFamily">
- <!-- The authority of the Font Provider to be used for the request. -->
+ <!-- The authority of the Font Provider to be used for the request.
+ {@deprecated Use app:fontProviderAuthority with Jetpack Core library instead for
+ consistent behavior across all devices.}
+ -->
<attr name="fontProviderAuthority" format="string" />
<!-- The package for the Font Provider to be used for the request. This is used to verify
- the identity of the provider. -->
+ the identity of the provider.
+ {@deprecated Use app:fontProviderPackage with Jetpack Core library instead.}
+ -->
<attr name="fontProviderPackage" format="string" />
<!-- The query to be sent over to the provider. Refer to your font provider's documentation
- on the format of this string. -->
+ on the format of this string.
+ {@deprecated Use app:fontProviderQuery with Jetpack Core library instead.}
+ -->
<attr name="fontProviderQuery" format="string" />
<!-- The sets of hashes for the certificates the provider should be signed with. This is
used to verify the identity of the provider, and is only required if the provider is not
part of the system image. This value may point to one list or a list of lists, where each
individual list represents one collection of signature hashes. Refer to your font provider's
- documentation for these values. -->
+ documentation for these values.
+ {@deprecated Use app:fontProviderCerts with Jetpack Core library instead.}
+ -->
<attr name="fontProviderCerts" format="reference" />
</declare-styleable>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 89e348a..f55114c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -271,11 +271,6 @@
when there's no network connection. If the scan doesn't timeout, use zero -->
<integer name="config_radioScanningTimeout">0</integer>
- <!-- When true, Android uses the PAC implementation included in WebView to handle
- networks with PAC scripts.
- When false, Android's own implementation of libpac is used.-->
- <bool name ="config_useWebViewPacProcessor">true</bool>
-
<!-- XXXXX NOTE THE FOLLOWING RESOURCES USE THE WRONG NAMING CONVENTION.
Please don't copy them, copy anything else. -->
@@ -1583,6 +1578,16 @@
config_timeZoneRulesUpdateTrackingEnabled are true.] -->
<integer name="config_timeZoneRulesCheckRetryCount">5</integer>
+ <!-- Whether to enable primary location time zone provider overlay which allows the primary
+ location time zone provider to be replaced by an app at run-time. When disabled, only the
+ config_primaryLocationTimeZoneProviderPackageName package will be searched for the primary
+ location time zone provider, otherwise any system package is eligible. Anyone who wants to
+ disable the overlay mechanism can set it to false. -->
+ <bool name="config_enablePrimaryLocationTimeZoneOverlay" translatable="false">false</bool>
+ <!-- Package name providing the primary location time zone provider. Used only when
+ config_enablePrimaryLocationTimeZoneOverlay is false. -->
+ <string name="config_primaryLocationTimeZoneProviderPackageName" translatable="false">@null</string>
+
<!-- Whether to enable network location overlay which allows network location provider to be
replaced by an app at run-time. When disabled, only the
config_networkLocationProviderPackageName package will be searched for network location
@@ -1826,6 +1831,8 @@
<string name="config_systemGallery" translatable="false">com.android.gallery3d</string>
<!-- The name of the package that will hold the system cluster service role. -->
<string name="config_systemAutomotiveCluster" translatable="false"></string>
+ <!-- The name of the package that will hold the system video call role. -->
+ <string name="config_systemVideoCall" translatable="false"></string>
<!-- The name of the package that will be allowed to change its components' label/icon. -->
<string name="config_overrideComponentUiPackage" translatable="false"></string>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 1e2d554..fe17eca 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3071,6 +3071,8 @@
<public-group type="string" first-id="0x01040028">
<!-- @hide @SystemApi @TestApi -->
<public name="config_systemAutomotiveCluster" />
+ <!-- @hide @SystemApi @TestApi -->
+ <public name="config_systemVideoCall" />
</public-group>
<public-group type="id" first-id="0x01020055">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 996e1f9..3e59549 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -287,7 +287,6 @@
<java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
<java-symbol type="bool" name="config_disableTransitionAnimation" />
<java-symbol type="bool" name="config_enableAutoPowerModes" />
- <java-symbol type="bool" name="config_useWebViewPacProcessor" />
<java-symbol type="integer" name="config_autoPowerModeThresholdAngle" />
<java-symbol type="integer" name="config_autoPowerModeAnyMotionSensor" />
<java-symbol type="bool" name="config_autoPowerModePreferWristTilt" />
@@ -2159,6 +2158,8 @@
<java-symbol type="string" name="config_defaultNetworkScorerPackageName" />
<java-symbol type="string" name="config_persistentDataPackageName" />
<java-symbol type="string" name="config_deviceConfiguratorPackageName" />
+ <java-symbol type="bool" name="config_enablePrimaryLocationTimeZoneOverlay" />
+ <java-symbol type="string" name="config_primaryLocationTimeZoneProviderPackageName" />
<java-symbol type="layout" name="resolver_list" />
<java-symbol type="id" name="resolver_list" />
diff --git a/core/tests/coretests/src/android/os/FileBridgeTest.java b/core/tests/coretests/src/android/os/FileBridgeTest.java
index d4f6b1f..708bfa6 100644
--- a/core/tests/coretests/src/android/os/FileBridgeTest.java
+++ b/core/tests/coretests/src/android/os/FileBridgeTest.java
@@ -16,6 +16,9 @@
package android.os;
+import static android.os.ParcelFileDescriptor.MODE_CREATE;
+import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
+
import android.os.FileBridge.FileBridgeOutputStream;
import android.test.AndroidTestCase;
import android.test.MoreAsserts;
@@ -25,7 +28,6 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Random;
@@ -33,7 +35,7 @@
public class FileBridgeTest extends AndroidTestCase {
private File file;
- private FileOutputStream fileOs;
+ private ParcelFileDescriptor outputFile;
private FileBridge bridge;
private FileBridgeOutputStream client;
@@ -44,17 +46,17 @@
file = getContext().getFileStreamPath("meow.dat");
file.delete();
- fileOs = new FileOutputStream(file);
+ outputFile = ParcelFileDescriptor.open(file, MODE_CREATE | MODE_READ_WRITE);
bridge = new FileBridge();
- bridge.setTargetFile(fileOs.getFD());
+ bridge.setTargetFile(outputFile);
bridge.start();
client = new FileBridgeOutputStream(bridge.getClientSocket());
}
@Override
protected void tearDown() throws Exception {
- fileOs.close();
+ outputFile.close();
file.delete();
}
diff --git a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
index b669cc6..a9cfd28 100644
--- a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
@@ -17,8 +17,10 @@
package com.android.internal.jank;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE;
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_TO_STATSD_INTERACTION_TYPE;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
@@ -45,6 +47,13 @@
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.stream.Collectors;
+
@SmallTest
public class InteractionJankMonitorTest {
private ViewAttachTestActivity mActivity;
@@ -138,4 +147,27 @@
verify(tracker).cancel();
}
+ @Test
+ public void testCujTypeEnumCorrectlyDefined() throws Exception {
+ List<Field> cujEnumFields =
+ Arrays.stream(InteractionJankMonitor.class.getDeclaredFields())
+ .filter(field -> field.getName().startsWith("CUJ_")
+ && Modifier.isStatic(field.getModifiers())
+ && field.getType() == int.class)
+ .collect(Collectors.toList());
+
+ HashSet<Integer> allValues = new HashSet<>();
+ for (Field field : cujEnumFields) {
+ int fieldValue = field.getInt(null);
+ assertWithMessage(
+ "Field %s must have a mapping to a value in CUJ_TO_STATSD_INTERACTION_TYPE",
+ field.getName())
+ .that(fieldValue < CUJ_TO_STATSD_INTERACTION_TYPE.length)
+ .isTrue();
+ assertWithMessage("All CujType values must be unique. Field %s repeats existing value.",
+ field.getName())
+ .that(allValues.add(fieldValue))
+ .isTrue();
+ }
+ }
}
diff --git a/core/xsd/vts/Android.bp b/core/xsd/vts/Android.bp
index 4b43b41..ca655f1 100644
--- a/core/xsd/vts/Android.bp
+++ b/core/xsd/vts/Android.bp
@@ -40,7 +40,3 @@
],
test_config: "vts_permission_validate_test.xml",
}
-
-vts_config {
- name: "VtsValidatePermission",
-}
diff --git a/core/xsd/vts/AndroidTest.xml b/core/xsd/vts/AndroidTest.xml
deleted file mode 100644
index e5cc9a0..0000000
--- a/core/xsd/vts/AndroidTest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 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.
--->
-<configuration description="Config for VTS VtsValidatePermission.">
- <option name="config-descriptor:metadata" key="plan" value="vts-treble" />
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
- <option name="abort-on-push-failure" value="false"/>
- <option name="push-group" value="HostDrivenTest.push"/>
- <option name="push" value="DATA/etc/permission.xsd->/data/local/tmp/permission.xsd"/>
- </target_preparer>
- <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
- <option name="test-module-name" value="VtsValidatePermission"/>
- <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_permission_validate_test/vts_permission_validate_test" />
- <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_permission_validate_test/vts_permission_validate_test" />
- <option name="binary-test-type" value="gtest"/>
- <option name="test-timeout" value="30s"/>
- </test>
-</configuration>
diff --git a/data/etc/com.android.storagemanager.xml b/data/etc/com.android.storagemanager.xml
index e85a82c..a1635fe 100644
--- a/data/etc/com.android.storagemanager.xml
+++ b/data/etc/com.android.storagemanager.xml
@@ -22,5 +22,6 @@
<permission name="android.permission.PACKAGE_USAGE_STATS"/>
<permission name="android.permission.USE_RESERVED_DISK"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+ <permission name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
</privapp-permissions>
</permissions>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index c53ea87..29c8de6 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -49,6 +49,18 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-2062338592": {
+ "message": "Looking for task of %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
+ "-2054442123": {
+ "message": "Setting Intent of %s to %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-2049725903": {
"message": "Task back pressed on root taskId=%d",
"level": "VERBOSE",
@@ -103,6 +115,12 @@
"group": "WM_DEBUG_WINDOW_ORGANIZER",
"at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java"
},
+ "-1977793524": {
+ "message": "moveStackToDisplay: moving stackId=%d to displayId=%d",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
+ },
"-1976930686": {
"message": "Attempted to add Accessibility overlay window with bad token %s. Aborting.",
"level": "WARN",
@@ -163,6 +181,12 @@
"group": "WM_DEBUG_WINDOW_ORGANIZER",
"at": "com\/android\/server\/wm\/TaskOrganizerController.java"
},
+ "-1890326172": {
+ "message": "no-history finish of %s on new resume",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-1884933373": {
"message": "enableScreenAfterBoot: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s",
"level": "INFO",
@@ -199,6 +223,12 @@
"group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
"at": "com\/android\/server\/wm\/AppTransition.java"
},
+ "-1861864501": {
+ "message": "resumeTopActivityLocked: Going to sleep and all paused",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-1847087163": {
"message": "TRANSIT_TASK_OPEN_BEHIND, adding %s to mOpeningApps",
"level": "DEBUG",
@@ -259,6 +289,12 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimationController.java"
},
+ "-1768090656": {
+ "message": "Re-launching after pause: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-1750206390": {
"message": "Exception thrown when creating surface for client %s (%s). %s",
"level": "WARN",
@@ -295,6 +331,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayContent.java"
},
+ "-1704402370": {
+ "message": "resetTaskIntendedTask: calling finishActivity on %s",
+ "level": "WARN",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java"
+ },
"-1699018375": {
"message": "Adding activity %s to task %s callers: %s",
"level": "INFO",
@@ -307,6 +349,12 @@
"group": "WM_DEBUG_ADD_REMOVE",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "-1679411993": {
+ "message": "setVr2dDisplayId called for: %d",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
+ },
"-1670695197": {
"message": "Attempted to add presentation window to a non-suitable display. Aborting.",
"level": "WARN",
@@ -319,6 +367,18 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-1655805455": {
+ "message": "Enqueue pending stop if needed: %s wasStopping=%b visibleRequested=%b",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
+ "-1647332198": {
+ "message": "remove RecentTask %s when finishing user %d",
+ "level": "INFO",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/RecentTasks.java"
+ },
"-1638958146": {
"message": "Removing activity %s from task=%s adding to task=%s Callers=%s",
"level": "INFO",
@@ -337,6 +397,24 @@
"group": "WM_DEBUG_LOCKTASK",
"at": "com\/android\/server\/wm\/LockTaskController.java"
},
+ "-1613096551": {
+ "message": "Top resumed state released %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityStackSupervisor.java"
+ },
+ "-1607026519": {
+ "message": "Ready to stop: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityStackSupervisor.java"
+ },
+ "-1601745126": {
+ "message": "Launch on display check: allow launch for owner of the display",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityStackSupervisor.java"
+ },
"-1598452494": {
"message": "activityDestroyedLocked: r=%s",
"level": "DEBUG",
@@ -355,6 +433,18 @@
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
"at": "com\/android\/server\/wm\/Transition.java"
},
+ "-1585311008": {
+ "message": "Bring to front target: %s from %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityStarter.java"
+ },
+ "-1575977269": {
+ "message": "Skipping %s: mismatch root %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
"-1568331821": {
"message": "Enabling listeners",
"level": "VERBOSE",
@@ -367,6 +457,12 @@
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
"at": "com\/android\/server\/wm\/Transition.java"
},
+ "-1558137010": {
+ "message": "Config is relaunching invisible activity %s called by %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-1554521902": {
"message": "showInsets(ime) was requested by different window: %s ",
"level": "WARN",
@@ -433,6 +529,18 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityStarter.java"
},
+ "-1492696222": {
+ "message": "App died during pause, not stopping: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
+ "-1474292612": {
+ "message": "Could not find task for id: %d",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
+ },
"-1471946192": {
"message": "Marking app token %s with replacing child windows.",
"level": "DEBUG",
@@ -463,6 +571,12 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimationController.java"
},
+ "-1432963966": {
+ "message": "Moving to DESTROYING: %s (destroy requested)",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-1427184084": {
"message": "addWindow: New client %s: window=%s Callers=%s",
"level": "VERBOSE",
@@ -499,6 +613,12 @@
"group": "WM_DEBUG_SYNC_ENGINE",
"at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
},
+ "-1376035390": {
+ "message": "No task found",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
"-1375751630": {
"message": " --- Start combine pass ---",
"level": "VERBOSE",
@@ -541,12 +661,36 @@
"group": "WM_DEBUG_IME",
"at": "com\/android\/server\/wm\/WindowState.java"
},
+ "-1305966693": {
+ "message": "Sending position change to %s, onTop: %b",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
+ "-1305791032": {
+ "message": "Moving to STOPPED: %s (stop complete)",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-1305755880": {
"message": "Initial config: %s",
"level": "VERBOSE",
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
},
+ "-1304806505": {
+ "message": "Starting new activity %s in new task %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityStarter.java"
+ },
+ "-1295684101": {
+ "message": "Launch on display check: no caller info, skip check",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityStackSupervisor.java"
+ },
"-1292329638": {
"message": "Added starting %s: startingWindow=%s startingView=%s",
"level": "VERBOSE",
@@ -601,12 +745,30 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimationController.java"
},
+ "-1198579104": {
+ "message": "Pushing next activity %s out to target's task %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java"
+ },
+ "-1193946201": {
+ "message": "Can't report activity position update - client not running, activityRecord=%s",
+ "level": "WARN",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-1176488860": {
"message": "SURFACE isSecure=%b: %s",
"level": "INFO",
"group": "WM_SHOW_TRANSACTIONS",
"at": "com\/android\/server\/wm\/WindowSurfaceController.java"
},
+ "-1164930508": {
+ "message": "Moving to RESUMED: %s (starting new instance) callers=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-1156118957": {
"message": "Updated config=%s",
"level": "DEBUG",
@@ -631,6 +793,12 @@
"group": "WM_DEBUG_FOCUS",
"at": "com\/android\/server\/wm\/DisplayContent.java"
},
+ "-1136139407": {
+ "message": "no-history finish of %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-1130891072": {
"message": "Orientation continue waiting for draw in %s",
"level": "VERBOSE",
@@ -697,12 +865,24 @@
"group": "WM_DEBUG_STARTING_WINDOW",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "-1084548141": {
+ "message": "Launch on display check: allow launch any on display",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityStackSupervisor.java"
+ },
"-1076978367": {
"message": "thawRotation: mRotation=%d",
"level": "VERBOSE",
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-1066383762": {
+ "message": "Sleep still waiting to pause %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-1060365734": {
"message": "Attempted to add QS dialog window with bad token %s. Aborting.",
"level": "WARN",
@@ -727,12 +907,30 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-1022146708": {
+ "message": "Skipping %s: mismatch activity type",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
+ "-1016578046": {
+ "message": "Moving to %s Relaunching %s callers=%s",
+ "level": "INFO",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-1009117329": {
"message": "isFetchingAppTransitionSpecs=true",
"level": "VERBOSE",
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/AppTransitionController.java"
},
+ "-1003060523": {
+ "message": "Finish needs to pause: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-993378225": {
"message": "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s",
"level": "VERBOSE",
@@ -751,6 +949,12 @@
"group": "WM_DEBUG_WINDOW_ORGANIZER",
"at": "com\/android\/server\/wm\/TaskOrganizerController.java"
},
+ "-937498525": {
+ "message": "Executing finish of failed to pause activity: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-930893991": {
"message": "Set sync ready, syncId=%d",
"level": "VERBOSE",
@@ -775,6 +979,18 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
},
+ "-926231510": {
+ "message": "State unchanged from:%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
+ "-917215012": {
+ "message": "%s: caller %d is using old GET_TASKS but privileged; allowing",
+ "level": "WARN",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
+ },
"-916108501": {
"message": "Adding %s to %s",
"level": "VERBOSE",
@@ -787,18 +1003,36 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-903853754": {
+ "message": "pauseBackStacks: stack=%s mResumedActivity=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
+ },
"-883738232": {
"message": "Adding more than one toast window for UID at a time.",
"level": "WARN",
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-877494781": {
+ "message": "Start pushing activity %s out to bottom task %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ResetTargetTaskHelper.java"
+ },
"-874446906": {
"message": "showBootMessage: msg=%s always=%b mAllowBootMessages=%b mShowingBootMessages=%b mSystemBooted=%b. %s",
"level": "INFO",
"group": "WM_DEBUG_BOOT",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-866966979": {
+ "message": "Moving to PAUSED: %s (starting in paused state)",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityStackSupervisor.java"
+ },
"-861859917": {
"message": "Attempted to add window to a display that does not exist: %d. Aborting.",
"level": "WARN",
@@ -841,6 +1075,12 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "-814760297": {
+ "message": "Looking for task of %s in %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
"-809771899": {
"message": "findFocusedWindow: Reached focused app=%s",
"level": "VERBOSE",
@@ -871,6 +1111,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-775004869": {
+ "message": "Not a match: %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
"-771177730": {
"message": "Removing focused app token:%s displayId=%d",
"level": "VERBOSE",
@@ -901,12 +1147,24 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "-729530161": {
+ "message": "Moving to DESTROYED: %s (no app)",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-716565534": {
"message": "moveActivityStackToFront: unfocusable activity=%s",
"level": "DEBUG",
"group": "WM_DEBUG_FOCUS",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "-705939410": {
+ "message": "Waiting for pause to complete...",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-703543418": {
"message": " check sibling %s",
"level": "VERBOSE",
@@ -925,6 +1183,12 @@
"group": "WM_DEBUG_SYNC_ENGINE",
"at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
},
+ "-672228342": {
+ "message": "resumeTopActivityLocked: Top activity resumed %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-668956537": {
"message": " THUMBNAIL %s: CREATE",
"level": "INFO",
@@ -943,6 +1207,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
+ "-650261962": {
+ "message": "Sleep needs to pause %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-639305784": {
"message": "Could not report config changes to the window token client.",
"level": "WARN",
@@ -979,6 +1249,18 @@
"group": "WM_DEBUG_BOOT",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-606328116": {
+ "message": "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
+ "-596163537": {
+ "message": "Waiting for top state to be released by %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityStackSupervisor.java"
+ },
"-593535526": {
"message": "Binding proc %s with config %s",
"level": "VERBOSE",
@@ -997,6 +1279,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotation.java"
},
+ "-571686216": {
+ "message": "Launch on display check: disallow launch on virtual display for not-embedded activity.",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityStackSupervisor.java"
+ },
"-561092364": {
"message": "onPointerDownOutsideFocusLocked called on %s",
"level": "INFO",
@@ -1027,12 +1315,24 @@
"group": "WM_SHOW_TRANSACTIONS",
"at": "com\/android\/server\/wm\/WindowAnimator.java"
},
+ "-533690126": {
+ "message": "resumeTopActivityLocked: Resumed %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-532081937": {
"message": " Commit activity becoming invisible: %s",
"level": "VERBOSE",
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
"at": "com\/android\/server\/wm\/Transition.java"
},
+ "-527683022": {
+ "message": "resumeTopActivityLocked: Skip resume: some activity pausing.",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-519504830": {
"message": "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM transit=%s isEntrance=%b Callers=%s",
"level": "VERBOSE",
@@ -1117,6 +1417,18 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotation.java"
},
+ "-427457280": {
+ "message": "App died while pausing: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
+ "-417514857": {
+ "message": "Key dispatch not paused for screen off",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-415865166": {
"message": "findFocusedWindow: Found new focus @ %s",
"level": "VERBOSE",
@@ -1135,6 +1447,18 @@
"group": "WM_DEBUG_CONTAINERS",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "-401029526": {
+ "message": "%s: caller %d does not hold REAL_GET_TASKS; limiting output",
+ "level": "WARN",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
+ },
+ "-399343789": {
+ "message": "Skipping %s: different user",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
"-395922585": {
"message": "InsetsSource setWin %s",
"level": "DEBUG",
@@ -1183,6 +1507,12 @@
"group": "WM_DEBUG_STARTING_WINDOW",
"at": "com\/android\/server\/wm\/WindowStateAnimator.java"
},
+ "-332679827": {
+ "message": "resumeNextFocusableActivityWhenStackIsEmpty: %s, go home",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-324085783": {
"message": "SURFACE CROP %s: %s",
"level": "INFO",
@@ -1225,12 +1555,30 @@
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
"at": "com\/android\/server\/wm\/Transition.java"
},
+ "-300896109": {
+ "message": "moveTaskToStack: moving task=%d to stackId=%d toTop=%b",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
+ },
+ "-279436615": {
+ "message": "Moving to PAUSING: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-272719931": {
"message": "startLockTaskModeLocked: %s",
"level": "WARN",
"group": "WM_DEBUG_LOCKTASK",
"at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
},
+ "-262984451": {
+ "message": "Relaunch failed %s",
+ "level": "INFO",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-260960989": {
"message": "Removing and adding activity %s to stack at top callers=%s",
"level": "INFO",
@@ -1249,6 +1597,12 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "-234244777": {
+ "message": "Activity config changed during resume: %s, new next: %s",
+ "level": "INFO",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-198463978": {
"message": "updateRotationUnchecked: alwaysSendConfiguration=%b forceRelayout=%b",
"level": "VERBOSE",
@@ -1273,6 +1627,12 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimationController.java"
},
+ "-172326720": {
+ "message": "Saving icicle of %s: %s",
+ "level": "INFO",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-168799453": {
"message": "Allowing features %d:0x%s",
"level": "WARN",
@@ -1291,6 +1651,12 @@
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/AppTransitionController.java"
},
+ "-118786523": {
+ "message": "Resume failed; resetting state to %s: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"-116086365": {
"message": "******************** ENABLING SCREEN!",
"level": "INFO",
@@ -1351,6 +1717,12 @@
"group": "WM_SHOW_TRANSACTIONS",
"at": "com\/android\/server\/wm\/WindowSurfaceController.java"
},
+ "-21399771": {
+ "message": "activity %s already destroying, skipping request with reason:%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-7343917": {
"message": "onAnimationFinished(): targetStack=%s targetActivity=%s mRestoreTargetBehindStack=%s",
"level": "DEBUG",
@@ -1411,6 +1783,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "51927339": {
+ "message": "Skipping %s: voice session",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
"73987756": {
"message": "ControlAdapter onAnimationCancelled mSource: %s mControlTarget: %s",
"level": "INFO",
@@ -1429,12 +1807,24 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimationController.java"
},
+ "86989930": {
+ "message": "setTaskWindowingMode: moving task=%d to windowingMode=%d toTop=%b",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
+ },
"91350919": {
"message": "Attempted to set IME flag to a display that does not exist: %d",
"level": "WARN",
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "94402792": {
+ "message": "Moving to RESUMED: %s (in existing)",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"95216706": {
"message": "hideIme target: %s ",
"level": "DEBUG",
@@ -1537,6 +1927,12 @@
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/AppTransitionController.java"
},
+ "189628502": {
+ "message": "Moving to STOPPING: %s (stop requested)",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"194124419": {
"message": "goodToGo(): Animation finished already, canceled=%s mPendingAnimations=%d",
"level": "DEBUG",
@@ -1657,6 +2053,12 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimationController.java"
},
+ "306524472": {
+ "message": "Stop failed; moving to STOPPED: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"309039362": {
"message": "SURFACE MATRIX [%f,%f,%f,%f]: %s",
"level": "INFO",
@@ -1729,6 +2131,12 @@
"group": "WM_DEBUG_FOCUS",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "397382873": {
+ "message": "Moving to PAUSED: %s %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"399841913": {
"message": "SURFACE RECOVER DESTROY: %s",
"level": "INFO",
@@ -1783,6 +2191,12 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimation.java"
},
+ "485170982": {
+ "message": "Not finishing noHistory %s on stop because we're just sleeping",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"487621047": {
"message": "DisplayArea vanished name=%s",
"level": "VERBOSE",
@@ -1849,6 +2263,12 @@
"group": "WM_SHOW_TRANSACTIONS",
"at": "com\/android\/server\/wm\/WindowSurfaceController.java"
},
+ "579298675": {
+ "message": "Moving to DESTROYED: %s (removed from history)",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"585096182": {
"message": "SURFACE isColorSpaceAgnostic=%b: %s",
"level": "INFO",
@@ -1969,6 +2389,12 @@
"group": "WM_DEBUG_SCREEN_ON",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "674932310": {
+ "message": "Setting Intent of %s to target %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"685047360": {
"message": "Resizing window %s",
"level": "VERBOSE",
@@ -1993,12 +2419,24 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "709500946": {
+ "message": "resumeTopActivityLocked: Skip resume: need to start pausing",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"715749922": {
"message": "Allowlisting %d:%s",
"level": "WARN",
"group": "WM_DEBUG_LOCKTASK",
"at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
},
+ "726205185": {
+ "message": "Moving to DESTROYED: %s (destroy skipped)",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"736692676": {
"message": "Config is relaunching %s",
"level": "VERBOSE",
@@ -2083,6 +2521,12 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimation.java"
},
+ "864551564": {
+ "message": "Launch on display check: disallow activity embedding without permission.",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityStackSupervisor.java"
+ },
"869266572": {
"message": "Removing activity %s from stack, reason= %s callers=%s",
"level": "INFO",
@@ -2101,12 +2545,30 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
+ "875196661": {
+ "message": "Skipping stack: (mismatch activity\/stack) %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
+ },
"892244061": {
"message": "Waiting for drawn %s: removed=%b visible=%b mHasSurface=%b drawState=%d",
"level": "INFO",
"group": "WM_DEBUG_SCREEN_ON",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "895158150": {
+ "message": "allPausedActivitiesComplete: r=%s state=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
+ "897964776": {
+ "message": "Complete pause: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"898863925": {
"message": "Attempted to add QS dialog window with unknown token %s. Aborting.",
"level": "WARN",
@@ -2161,6 +2623,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
+ "988389910": {
+ "message": "resumeTopActivityLocked: Pausing %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"996960396": {
"message": "Starting Transition %d",
"level": "VERBOSE",
@@ -2173,12 +2641,30 @@
"group": "WM_DEBUG_SYNC_ENGINE",
"at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
},
+ "1001509841": {
+ "message": "Auto-PIP allowed, entering PIP mode directly: %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"1001904964": {
"message": "***** BOOT TIMEOUT: forcing display enabled",
"level": "WARN",
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "1015542198": {
+ "message": "Launch on display check: displayId=%d callingPid=%d callingUid=%d",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityStackSupervisor.java"
+ },
+ "1023413388": {
+ "message": "Finish waiting for pause of: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"1040675582": {
"message": "Can't report activity configuration update - client not running, activityRecord=%s",
"level": "WARN",
@@ -2191,6 +2677,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "1047769218": {
+ "message": "Finishing activity r=%s, result=%d, data=%s, reason=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"1049367566": {
"message": "Sending to proc %s new config %s",
"level": "VERBOSE",
@@ -2203,6 +2695,12 @@
"group": "WM_DEBUG_ADD_REMOVE",
"at": "com\/android\/server\/wm\/WindowState.java"
},
+ "1068803972": {
+ "message": "Activity paused: token=%s, timeout=%b",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"1073230342": {
"message": "startAnimation",
"level": "DEBUG",
@@ -2221,6 +2719,12 @@
"group": "WM_SHOW_SURFACE_ALLOC",
"at": "com\/android\/server\/wm\/ScreenRotationAnimation.java"
},
+ "1098891625": {
+ "message": "realStartActivityLocked: Skipping start of r=%s some activities pausing...",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityStackSupervisor.java"
+ },
"1112047265": {
"message": "finishDrawingWindow: %s mDrawState=%s",
"level": "DEBUG",
@@ -2239,6 +2743,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "1126328412": {
+ "message": "Scheduling idle now: forceIdle=%b immediate=%b",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"1140424002": {
"message": "Finished screen turning on...",
"level": "INFO",
@@ -2263,12 +2773,24 @@
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
"at": "com\/android\/server\/wm\/Transition.java"
},
+ "1192413464": {
+ "message": "Comparing existing cls=%s \/aff=%s to new cls=%s \/aff=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
"1208313423": {
"message": "addWindowToken: Attempted to add token: %s for non-exiting displayId=%d",
"level": "WARN",
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "1217926207": {
+ "message": "Activity not running, resuming next.",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"1219600119": {
"message": "addWindow: win=%s Callers=%s",
"level": "DEBUG",
@@ -2305,12 +2827,24 @@
"group": "WM_DEBUG_STARTING_WINDOW",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "1270792394": {
+ "message": "Resumed after relaunch %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"1288731814": {
"message": "WindowState.hideLw: setting mFocusMayChange true",
"level": "INFO",
"group": "WM_DEBUG_FOCUS_LIGHT",
"at": "com\/android\/server\/wm\/WindowState.java"
},
+ "1316533291": {
+ "message": "State movement: %s from:%s to:%s reason:%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"1325649102": {
"message": "Bad requesting window %s",
"level": "WARN",
@@ -2353,6 +2887,12 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
},
+ "1364126018": {
+ "message": "Resumed activity; dropping state of: %s",
+ "level": "INFO",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"1364498663": {
"message": "notifyAppResumed: wasStopped=%b %s",
"level": "VERBOSE",
@@ -2503,6 +3043,12 @@
"group": "WM_DEBUG_IME",
"at": "com\/android\/server\/wm\/WindowState.java"
},
+ "1557732761": {
+ "message": "For Intent %s bringing to top: %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
"1563755163": {
"message": "Permission Denial: %s from pid=%d, uid=%d requires %s",
"level": "WARN",
@@ -2527,12 +3073,24 @@
"group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
"at": "com\/android\/server\/wm\/WindowContainer.java"
},
+ "1585450696": {
+ "message": "resumeTopActivityLocked: Restarting %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"1589610525": {
"message": "applyAnimation NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS: anim=%s transit=%s isEntrance=true Callers=%s",
"level": "VERBOSE",
"group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
"at": "com\/android\/server\/wm\/AppTransition.java"
},
+ "1610646518": {
+ "message": "Enqueueing pending finish: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"1628345525": {
"message": "Now opening app %s",
"level": "VERBOSE",
@@ -2593,6 +3151,18 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "1696210756": {
+ "message": "Launch on display check: allow launch on public display",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityStackSupervisor.java"
+ },
+ "1706082525": {
+ "message": "Stopping %s: nowVisible=%b animating=%b finishing=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/ActivityStackSupervisor.java"
+ },
"1720229827": {
"message": "Creating animation bounds layer",
"level": "INFO",
@@ -2659,6 +3229,12 @@
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
"at": "com\/android\/server\/wm\/TransitionController.java"
},
+ "1804435108": {
+ "message": "allResumedActivitiesIdle: stack=%d %s not idle",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
"1822843721": {
"message": "Aborted starting %s: startingData=%s",
"level": "VERBOSE",
@@ -2695,6 +3271,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "1837992242": {
+ "message": "Executing finish of activity: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"1853793312": {
"message": "Notify removed startingWindow %s",
"level": "VERBOSE",
@@ -2713,12 +3295,24 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "1884961873": {
+ "message": "Sleep still need to stop %d activities",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"1891501279": {
"message": "cancelAnimation(): reason=%s",
"level": "DEBUG",
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
+ "1894239744": {
+ "message": "Enqueueing pending pause: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/Task.java"
+ },
"1903353011": {
"message": "notifyAppStopped: %s",
"level": "VERBOSE",
@@ -2749,6 +3343,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotation.java"
},
+ "1947936538": {
+ "message": "Found matching class!",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
"1964565370": {
"message": "Starting remote animation",
"level": "INFO",
@@ -2827,12 +3427,24 @@
"group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
"at": "com\/android\/server\/wm\/AppTransition.java"
},
+ "2034714267": {
+ "message": "Launch on display check: allow launch for caller present on the display",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityStackSupervisor.java"
+ },
"2034780299": {
"message": "CHECK_IF_BOOT_ANIMATION_FINISHED:",
"level": "INFO",
"group": "WM_DEBUG_BOOT",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "2039056415": {
+ "message": "Found matching affinity candidate!",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+ },
"2045641491": {
"message": "Checking %d opening apps (frozen=%b timeout=%b)...",
"level": "VERBOSE",
@@ -2881,6 +3493,12 @@
"group": "WM_DEBUG_ADD_REMOVE",
"at": "com\/android\/server\/wm\/WindowState.java"
},
+ "2117696413": {
+ "message": "moveTaskToFront: moving taskId=%d",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java"
+ },
"2119122320": {
"message": "setInputMethodTarget %s",
"level": "INFO",
@@ -2964,12 +3582,18 @@
"WM_DEBUG_STARTING_WINDOW": {
"tag": "WindowManager"
},
+ "WM_DEBUG_STATES": {
+ "tag": "WindowManager"
+ },
"WM_DEBUG_SWITCH": {
"tag": "WindowManager"
},
"WM_DEBUG_SYNC_ENGINE": {
"tag": "WindowManager"
},
+ "WM_DEBUG_TASKS": {
+ "tag": "WindowManager"
+ },
"WM_DEBUG_WINDOW_MOVEMENT": {
"tag": "WindowManager"
},
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/CompatChangeChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/CompatChangeChecker.java
new file mode 100644
index 0000000..9c84f50
--- /dev/null
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/CompatChangeChecker.java
@@ -0,0 +1,125 @@
+/*
+ * 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.google.errorprone.bugpatterns.android;
+
+import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
+import static com.google.errorprone.bugpatterns.android.TargetSdkChecker.binaryTreeExact;
+import static com.google.errorprone.matchers.FieldMatchers.anyFieldInClass;
+import static com.google.errorprone.matchers.FieldMatchers.staticField;
+import static com.google.errorprone.matchers.Matchers.allOf;
+import static com.google.errorprone.matchers.Matchers.anyOf;
+import static com.google.errorprone.matchers.Matchers.anything;
+import static com.google.errorprone.matchers.Matchers.kindIs;
+import static com.google.errorprone.matchers.Matchers.not;
+
+import com.google.auto.service.AutoService;
+import com.google.errorprone.BugPattern;
+import com.google.errorprone.VisitorState;
+import com.google.errorprone.bugpatterns.BugChecker;
+import com.google.errorprone.bugpatterns.BugChecker.BinaryTreeMatcher;
+import com.google.errorprone.matchers.Description;
+import com.google.errorprone.matchers.Matcher;
+import com.sun.source.tree.BinaryTree;
+import com.sun.source.tree.ExpressionTree;
+import com.sun.source.tree.Tree.Kind;
+
+/**
+ * Each SDK level often has dozens of different behavior changes, which can be
+ * difficult for large app developers to adjust to during preview or beta
+ * releases. For this reason, {@code android.app.compat.CompatChanges} was
+ * introduced as a new best-practice for adding behavior changes.
+ * <p>
+ * During a preview or beta release, developers can temporarily opt-out of each
+ * individual change to aid debugging. This opt-out is only available during
+ * preview of beta releases, and cannot be adjusted on finalized builds.
+ */
+@AutoService(BugChecker.class)
+@BugPattern(
+ name = "AndroidFrameworkCompatChange",
+ summary = "Verifies that behavior changes use the modern compatibility framework",
+ severity = WARNING)
+public final class CompatChangeChecker extends BugChecker implements BinaryTreeMatcher {
+ private static final Matcher<ExpressionTree> VERSION_CODE =
+ anyFieldInClass("android.os.Build.VERSION_CODES");
+
+ // Ship has already sailed on these SDK levels; not worth fixing
+ private static final Matcher<ExpressionTree> LEGACY_VERSION_CODE = anyOf(
+ staticField("android.os.Build.VERSION_CODES", "BASE"),
+ staticField("android.os.Build.VERSION_CODES", "BASE_1_1"),
+ staticField("android.os.Build.VERSION_CODES", "CUPCAKE"),
+ staticField("android.os.Build.VERSION_CODES", "DONUT"),
+ staticField("android.os.Build.VERSION_CODES", "ECLAIR"),
+ staticField("android.os.Build.VERSION_CODES", "ECLAIR_0_1"),
+ staticField("android.os.Build.VERSION_CODES", "ECLAIR_MR1"),
+ staticField("android.os.Build.VERSION_CODES", "FROYO"),
+ staticField("android.os.Build.VERSION_CODES", "GINGERBREAD"),
+ staticField("android.os.Build.VERSION_CODES", "GINGERBREAD_MR1"),
+ staticField("android.os.Build.VERSION_CODES", "HONEYCOMB"),
+ staticField("android.os.Build.VERSION_CODES", "HONEYCOMB_MR1"),
+ staticField("android.os.Build.VERSION_CODES", "HONEYCOMB_MR2"),
+ staticField("android.os.Build.VERSION_CODES", "ICE_CREAM_SANDWICH"),
+ staticField("android.os.Build.VERSION_CODES", "ICE_CREAM_SANDWICH_MR1"),
+ staticField("android.os.Build.VERSION_CODES", "JELLY_BEAN"),
+ staticField("android.os.Build.VERSION_CODES", "JELLY_BEAN_MR1"),
+ staticField("android.os.Build.VERSION_CODES", "JELLY_BEAN_MR2"),
+ staticField("android.os.Build.VERSION_CODES", "KITKAT"),
+ staticField("android.os.Build.VERSION_CODES", "KITKAT_WATCH"),
+ staticField("android.os.Build.VERSION_CODES", "L"),
+ staticField("android.os.Build.VERSION_CODES", "LOLLIPOP"),
+ staticField("android.os.Build.VERSION_CODES", "LOLLIPOP_MR1"),
+ staticField("android.os.Build.VERSION_CODES", "M"),
+ staticField("android.os.Build.VERSION_CODES", "N"),
+ staticField("android.os.Build.VERSION_CODES", "N_MR1"),
+ staticField("android.os.Build.VERSION_CODES", "O"),
+ staticField("android.os.Build.VERSION_CODES", "O_MR1"),
+ staticField("android.os.Build.VERSION_CODES", "P"),
+ staticField("android.os.Build.VERSION_CODES", "Q"),
+ staticField("android.os.Build.VERSION_CODES", "R"));
+
+ private static final Matcher<ExpressionTree> R_VERSION_CODE =
+ staticField("android.os.Build.VERSION_CODES", "R");
+
+ private static final Matcher<ExpressionTree> CUR_DEVELOPMENT_VERSION_CODE =
+ staticField("android.os.Build.VERSION_CODES", "CUR_DEVELOPMENT");
+
+ private static final Matcher<ExpressionTree> MODERN_VERSION_CODE =
+ allOf(VERSION_CODE, not(LEGACY_VERSION_CODE), not(CUR_DEVELOPMENT_VERSION_CODE));
+
+ private static final Matcher<ExpressionTree> BOOLEAN_OPERATOR = anyOf(
+ kindIs(Kind.LESS_THAN), kindIs(Kind.LESS_THAN_EQUAL),
+ kindIs(Kind.GREATER_THAN), kindIs(Kind.GREATER_THAN_EQUAL),
+ kindIs(Kind.EQUAL_TO), kindIs(Kind.NOT_EQUAL_TO));
+
+ private static final Matcher<BinaryTree> INVALID = anyOf(
+ allOf(BOOLEAN_OPERATOR, binaryTreeExact(MODERN_VERSION_CODE, anything())),
+ allOf(BOOLEAN_OPERATOR, binaryTreeExact(anything(), MODERN_VERSION_CODE)),
+ allOf(kindIs(Kind.GREATER_THAN), binaryTreeExact(anything(), R_VERSION_CODE)),
+ allOf(kindIs(Kind.LESS_THAN), binaryTreeExact(R_VERSION_CODE, anything())));
+
+ @Override
+ public Description matchBinary(BinaryTree tree, VisitorState state) {
+ if (INVALID.matches(tree, state)) {
+ return buildDescription(tree)
+ .setMessage("Behavior changes should use CompatChanges.isChangeEnabled() "
+ + "instead of direct SDK checks to ease developer transitions; "
+ + "see go/compat-framework for more details")
+ .build();
+
+ }
+ return Description.NO_MATCH;
+ }
+}
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/TargetSdkChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/TargetSdkChecker.java
index 232cf3f..e1ebf42 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/TargetSdkChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/TargetSdkChecker.java
@@ -89,7 +89,7 @@
return Description.NO_MATCH;
}
- private static Matcher<BinaryTree> binaryTreeExact(Matcher<ExpressionTree> left,
+ static Matcher<BinaryTree> binaryTreeExact(Matcher<ExpressionTree> left,
Matcher<ExpressionTree> right) {
return new Matcher<BinaryTree>() {
@Override
diff --git a/errorprone/java/com/google/errorprone/matchers/FieldMatchers.java b/errorprone/java/com/google/errorprone/matchers/FieldMatchers.java
index 46f0fb2..08969d6 100644
--- a/errorprone/java/com/google/errorprone/matchers/FieldMatchers.java
+++ b/errorprone/java/com/google/errorprone/matchers/FieldMatchers.java
@@ -36,7 +36,8 @@
return new FieldReferenceMatcher() {
@Override
boolean classIsAppropriate(ClassSymbol classSymbol) {
- return classSymbol.getQualifiedName().contentEquals(className);
+ return classSymbol != null
+ && classSymbol.getQualifiedName().contentEquals(className);
}
@Override
@@ -50,12 +51,14 @@
return new FieldReferenceMatcher() {
@Override
boolean classIsAppropriate(ClassSymbol classSymbol) {
- return classSymbol.getQualifiedName().contentEquals(className);
+ return classSymbol != null
+ && classSymbol.getQualifiedName().contentEquals(className);
}
@Override
boolean fieldSymbolIsAppropriate(Symbol symbol) {
- return symbol.isStatic() && symbol.getSimpleName().contentEquals(fieldName);
+ return symbol != null
+ && symbol.isStatic() && symbol.getSimpleName().contentEquals(fieldName);
}
};
}
@@ -64,12 +67,14 @@
return new FieldReferenceMatcher() {
@Override
boolean classIsAppropriate(ClassSymbol classSymbol) {
- return classSymbol.getQualifiedName().contentEquals(className);
+ return classSymbol != null
+ && classSymbol.getQualifiedName().contentEquals(className);
}
@Override
boolean fieldSymbolIsAppropriate(Symbol symbol) {
- return !symbol.isStatic() && symbol.getSimpleName().contentEquals(fieldName);
+ return symbol != null
+ && !symbol.isStatic() && symbol.getSimpleName().contentEquals(fieldName);
}
};
}
diff --git a/errorprone/tests/java/com/google/errorprone/bugpatterns/android/CompatChangeCheckerTest.java b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/CompatChangeCheckerTest.java
new file mode 100644
index 0000000..4625d43
--- /dev/null
+++ b/errorprone/tests/java/com/google/errorprone/bugpatterns/android/CompatChangeCheckerTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.google.errorprone.bugpatterns.android;
+
+import com.google.errorprone.CompilationTestHelper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class CompatChangeCheckerTest {
+ private CompilationTestHelper compilationHelper;
+
+ @Before
+ public void setUp() {
+ compilationHelper = CompilationTestHelper.newInstance(
+ CompatChangeChecker.class, getClass());
+ }
+
+ @Test
+ public void testSimple() {
+ compilationHelper
+ .addSourceFile("/android/os/Build.java")
+ .addSourceLines("Example.java",
+ "import android.os.Build;",
+ "public class Example {",
+ " void test(int targetSdkVersion) {",
+ " // BUG: Diagnostic contains:",
+ " if (targetSdkVersion < Build.VERSION_CODES.S) { }",
+ " // BUG: Diagnostic contains:",
+ " if (targetSdkVersion <= Build.VERSION_CODES.S) { }",
+ " // BUG: Diagnostic contains:",
+ " if (targetSdkVersion > Build.VERSION_CODES.S) { }",
+ " // BUG: Diagnostic contains:",
+ " if (targetSdkVersion >= Build.VERSION_CODES.S) { }",
+ " // BUG: Diagnostic contains:",
+ " if (targetSdkVersion == Build.VERSION_CODES.S) { }",
+ " // BUG: Diagnostic contains:",
+ " if (targetSdkVersion != Build.VERSION_CODES.S) { }",
+ " }",
+ "}")
+ .doTest();
+ }
+
+ @Test
+ public void testObscure() {
+ compilationHelper
+ .addSourceFile("/android/os/Build.java")
+ .addSourceLines("Example.java",
+ "import android.os.Build;",
+ "import static android.os.Build.VERSION_CODES.S;",
+ "public class Example {",
+ " void test(int targetSdkVersion) {",
+ " // BUG: Diagnostic contains:",
+ " boolean indirect = S >= targetSdkVersion;",
+ " // BUG: Diagnostic contains:",
+ " if (targetSdkVersion > Build.VERSION_CODES.R) { }",
+ " if (targetSdkVersion >= Build.VERSION_CODES.R) { }",
+ " if (targetSdkVersion < Build.VERSION_CODES.R) { }",
+ " if (targetSdkVersion <= Build.VERSION_CODES.R) { }",
+ " // BUG: Diagnostic contains:",
+ " if (Build.VERSION_CODES.R < targetSdkVersion) { }",
+ " if (Build.VERSION_CODES.R <= targetSdkVersion) { }",
+ " if (Build.VERSION_CODES.R > targetSdkVersion) { }",
+ " if (Build.VERSION_CODES.R >= targetSdkVersion) { }",
+ " }",
+ "}")
+ .doTest();
+ }
+
+ @Test
+ public void testIgnored() {
+ compilationHelper
+ .addSourceFile("/android/os/Build.java")
+ .addSourceLines("Example.java",
+ "import android.os.Build;",
+ "public class Example {",
+ " void test(int targetSdkVersion) {",
+ " if (targetSdkVersion < Build.VERSION_CODES.DONUT) { }",
+ " String result = \"test\" + Build.VERSION_CODES.S;",
+ " if (targetSdkVersion != Build.VERSION_CODES.CUR_DEVELOPMENT) { }",
+ " }",
+ "}")
+ .doTest();
+ }
+}
diff --git a/errorprone/tests/res/android/os/Build.java b/errorprone/tests/res/android/os/Build.java
index bbf7ef2..2d354e2 100644
--- a/errorprone/tests/res/android/os/Build.java
+++ b/errorprone/tests/res/android/os/Build.java
@@ -18,6 +18,9 @@
public class Build {
public static class VERSION_CODES {
+ public static final int CUR_DEVELOPMENT = 10000;
public static final int DONUT = 4;
+ public static final int R = 30;
+ public static final int S = CUR_DEVELOPMENT;
}
}
diff --git a/graphics/java/android/graphics/FrameInfo.java b/graphics/java/android/graphics/FrameInfo.java
index 163823f..f768bc7 100644
--- a/graphics/java/android/graphics/FrameInfo.java
+++ b/graphics/java/android/graphics/FrameInfo.java
@@ -52,6 +52,7 @@
public static final long FLAG_SURFACE_CANVAS = 1 << 2;
// An invalid vsync id to be used when FRAME_TIMELINE_VSYNC_ID is unknown
+ // Needs to be in sync with android::ISurfaceComposer::INVALID_VSYNC_ID in native code
public static final long INVALID_VSYNC_ID = -1;
@LongDef(flag = true, value = {
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index e1a1795..21b8fc6 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -516,7 +516,7 @@
mLocaleList = localeList;
synchronized (MAP_LOCK) {
- FONT_PTR_MAP.append(mNativePtr, new WeakReference<>(this));
+ FONT_PTR_MAP.append(nGetNativeFontPtr(mNativePtr), new WeakReference<>(this));
}
}
@@ -716,4 +716,7 @@
@FastNative
private static native float nGetFontMetrics(long font, long paint, Paint.FontMetrics metrics);
+
+ @CriticalNative
+ private static native long nGetNativeFontPtr(long ptr);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 8f496d0..f6edc07 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -66,10 +66,7 @@
public ShellTaskOrganizer(SyncTransactionQueue syncQueue, TransactionPool transactionPool,
ShellExecutor mainExecutor, ShellExecutor animExecutor) {
- super();
- addListener(new FullscreenTaskListener(syncQueue), WINDOWING_MODE_FULLSCREEN);
- mTransitions = new Transitions(this, transactionPool, mainExecutor, animExecutor);
- if (Transitions.ENABLE_SHELL_TRANSITIONS) registerTransitionPlayer(mTransitions);
+ this(null, syncQueue, transactionPool, mainExecutor, animExecutor);
}
@VisibleForTesting
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index bb501fb..e236d24 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -88,7 +88,7 @@
* This class is also responsible for general resize/offset PiP operations within SysUI component,
* see also {@link PipMotionHelper}.
*/
-public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganizer.TaskListener,
+public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
DisplayController.OnDisplaysChangedListener {
private static final String TAG = PipTaskOrganizer.class.getSimpleName();
private static final boolean DEBUG = false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
new file mode 100644
index 0000000..bebe5f9
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
@@ -0,0 +1,295 @@
+/*
+ * 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.wm.shell.pip.phone;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.TransitionDrawable;
+import android.os.Handler;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.dynamicanimation.animation.DynamicAnimation;
+import androidx.dynamicanimation.animation.SpringForce;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.animation.PhysicsAnimator;
+import com.android.wm.shell.common.DismissCircleView;
+import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
+import com.android.wm.shell.pip.PipUiEventLogger;
+
+import kotlin.Unit;
+
+/**
+ * Handler of all Magnetized Object related code for PiP.
+ */
+public class PipDismissTargetHandler {
+
+ /* The multiplier to apply scale the target size by when applying the magnetic field radius */
+ private static final float MAGNETIC_FIELD_RADIUS_MULTIPLIER = 1.25f;
+
+ /** Duration of the dismiss scrim fading in/out. */
+ private static final int DISMISS_TRANSITION_DURATION_MS = 200;
+
+ /**
+ * MagnetizedObject wrapper for PIP. This allows the magnetic target library to locate and move
+ * PIP.
+ */
+ private final MagnetizedObject<Rect> mMagnetizedPip;
+
+ /**
+ * Container for the dismiss circle, so that it can be animated within the container via
+ * translation rather than within the WindowManager via slow layout animations.
+ */
+ private final ViewGroup mTargetViewContainer;
+
+ /** Circle view used to render the dismiss target. */
+ private final DismissCircleView mTargetView;
+
+ /**
+ * MagneticTarget instance wrapping the target view and allowing us to set its magnetic radius.
+ */
+ private final MagnetizedObject.MagneticTarget mMagneticTarget;
+
+ /** PhysicsAnimator instance for animating the dismiss target in/out. */
+ private final PhysicsAnimator<View> mMagneticTargetAnimator;
+
+ /** Default configuration to use for springing the dismiss target in/out. */
+ private final PhysicsAnimator.SpringConfig mTargetSpringConfig =
+ new PhysicsAnimator.SpringConfig(
+ SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
+
+ /**
+ * Runnable that can be posted delayed to show the target. This needs to be saved as a member
+ * variable so we can pass it to removeCallbacks.
+ */
+ private Runnable mShowTargetAction = this::showDismissTargetMaybe;
+
+ // Allow dragging the PIP to a location to close it
+ private final boolean mEnableDismissDragToEdge;
+
+ private int mDismissAreaHeight;
+
+ private final Context mContext;
+ private final PipMotionHelper mMotionHelper;
+ private final PipUiEventLogger mPipUiEventLogger;
+ private final WindowManager mWindowManager;
+ private final Handler mHandler;
+
+ public PipDismissTargetHandler(Context context, PipUiEventLogger pipUiEventLogger,
+ PipMotionHelper motionHelper, Handler handler) {
+ mContext = context;
+ mPipUiEventLogger = pipUiEventLogger;
+ mMotionHelper = motionHelper;
+ mHandler = handler;
+ mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+
+ Resources res = context.getResources();
+ mEnableDismissDragToEdge = res.getBoolean(R.bool.config_pipEnableDismissDragToEdge);
+ mDismissAreaHeight = res.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height);
+
+ mTargetView = new DismissCircleView(context);
+ mTargetViewContainer = new FrameLayout(context);
+ mTargetViewContainer.setBackgroundDrawable(
+ context.getDrawable(R.drawable.floating_dismiss_gradient_transition));
+ mTargetViewContainer.setClipChildren(false);
+ mTargetViewContainer.addView(mTargetView);
+
+ mMagnetizedPip = mMotionHelper.getMagnetizedPip();
+ mMagneticTarget = mMagnetizedPip.addTarget(mTargetView, 0);
+ updateMagneticTargetSize();
+
+ mMagnetizedPip.setAnimateStuckToTarget(
+ (target, velX, velY, flung, after) -> {
+ if (mEnableDismissDragToEdge) {
+ mMotionHelper.animateIntoDismissTarget(target, velX, velY, flung, after);
+ }
+ return Unit.INSTANCE;
+ });
+ mMagnetizedPip.setMagnetListener(new MagnetizedObject.MagnetListener() {
+ @Override
+ public void onStuckToTarget(@NonNull MagnetizedObject.MagneticTarget target) {
+ // Show the dismiss target, in case the initial touch event occurred within the
+ // magnetic field radius.
+ if (mEnableDismissDragToEdge) {
+ showDismissTargetMaybe();
+ }
+ }
+
+ @Override
+ public void onUnstuckFromTarget(@NonNull MagnetizedObject.MagneticTarget target,
+ float velX, float velY, boolean wasFlungOut) {
+ if (wasFlungOut) {
+ mMotionHelper.flingToSnapTarget(velX, velY, null /* endAction */);
+ hideDismissTargetMaybe();
+ } else {
+ mMotionHelper.setSpringingToTouch(true);
+ }
+ }
+
+ @Override
+ public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) {
+ mMotionHelper.notifyDismissalPending();
+
+ handler.post(() -> {
+ mMotionHelper.animateDismiss();
+ hideDismissTargetMaybe();
+ });
+
+ mPipUiEventLogger.log(
+ PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_DRAG_TO_REMOVE);
+ }
+ });
+
+ mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView);
+ }
+
+ /**
+ * Potentially start consuming future motion events if PiP is currently near the magnetized
+ * object.
+ */
+ public boolean maybeConsumeMotionEvent(MotionEvent ev) {
+ return mMagnetizedPip.maybeConsumeMotionEvent(ev);
+ }
+
+ /**
+ * Update the magnet size.
+ */
+ public void updateMagneticTargetSize() {
+ if (mTargetView == null) {
+ return;
+ }
+
+ final Resources res = mContext.getResources();
+ final int targetSize = res.getDimensionPixelSize(R.dimen.dismiss_circle_size);
+ mDismissAreaHeight = res.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height);
+ final FrameLayout.LayoutParams newParams =
+ new FrameLayout.LayoutParams(targetSize, targetSize);
+ newParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
+ newParams.bottomMargin = mContext.getResources().getDimensionPixelSize(
+ R.dimen.floating_dismiss_bottom_margin);
+ mTargetView.setLayoutParams(newParams);
+
+ // Set the magnetic field radius equal to the target size from the center of the target
+ mMagneticTarget.setMagneticFieldRadiusPx(
+ (int) (targetSize * MAGNETIC_FIELD_RADIUS_MULTIPLIER));
+ }
+
+ /** Adds the magnetic target view to the WindowManager so it's ready to be animated in. */
+ public void createOrUpdateDismissTarget() {
+ if (!mTargetViewContainer.isAttachedToWindow()) {
+ mHandler.removeCallbacks(mShowTargetAction);
+ mMagneticTargetAnimator.cancel();
+
+ mTargetViewContainer.setVisibility(View.INVISIBLE);
+
+ try {
+ mWindowManager.addView(mTargetViewContainer, getDismissTargetLayoutParams());
+ } catch (IllegalStateException e) {
+ // This shouldn't happen, but if the target is already added, just update its layout
+ // params.
+ mWindowManager.updateViewLayout(
+ mTargetViewContainer, getDismissTargetLayoutParams());
+ }
+ } else {
+ mWindowManager.updateViewLayout(mTargetViewContainer, getDismissTargetLayoutParams());
+ }
+ }
+
+ /** Returns layout params for the dismiss target, using the latest display metrics. */
+ private WindowManager.LayoutParams getDismissTargetLayoutParams() {
+ final Point windowSize = new Point();
+ mWindowManager.getDefaultDisplay().getRealSize(windowSize);
+
+ final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ WindowManager.LayoutParams.MATCH_PARENT,
+ mDismissAreaHeight,
+ 0, windowSize.y - mDismissAreaHeight,
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ PixelFormat.TRANSLUCENT);
+
+ lp.setTitle("pip-dismiss-overlay");
+ lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+ lp.setFitInsetsTypes(0 /* types */);
+
+ return lp;
+ }
+
+ /** Makes the dismiss target visible and animates it in, if it isn't already visible. */
+ public void showDismissTargetMaybe() {
+ if (!mEnableDismissDragToEdge) {
+ return;
+ }
+
+ createOrUpdateDismissTarget();
+
+ if (mTargetViewContainer.getVisibility() != View.VISIBLE) {
+
+ mTargetView.setTranslationY(mTargetViewContainer.getHeight());
+ mTargetViewContainer.setVisibility(View.VISIBLE);
+
+ // Cancel in case we were in the middle of animating it out.
+ mMagneticTargetAnimator.cancel();
+ mMagneticTargetAnimator
+ .spring(DynamicAnimation.TRANSLATION_Y, 0f, mTargetSpringConfig)
+ .start();
+
+ ((TransitionDrawable) mTargetViewContainer.getBackground()).startTransition(
+ DISMISS_TRANSITION_DURATION_MS);
+ }
+ }
+
+ /** Animates the magnetic dismiss target out and then sets it to GONE. */
+ public void hideDismissTargetMaybe() {
+ if (!mEnableDismissDragToEdge) {
+ return;
+ }
+
+ mHandler.removeCallbacks(mShowTargetAction);
+ mMagneticTargetAnimator
+ .spring(DynamicAnimation.TRANSLATION_Y,
+ mTargetViewContainer.getHeight(),
+ mTargetSpringConfig)
+ .withEndActions(() -> mTargetViewContainer.setVisibility(View.GONE))
+ .start();
+
+ ((TransitionDrawable) mTargetViewContainer.getBackground()).reverseTransition(
+ DISMISS_TRANSITION_DURATION_MS);
+ }
+
+ /**
+ * Removes the dismiss target and cancels any pending callbacks to show it.
+ */
+ public void cleanUpDismissTarget() {
+ mHandler.removeCallbacks(mShowTargetAction);
+
+ if (mTargetViewContainer.isAttachedToWindow()) {
+ mWindowManager.removeViewImmediate(mTargetViewContainer);
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActivityController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActivityController.java
index c53803a7..cd47d55 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActivityController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActivityController.java
@@ -156,20 +156,6 @@
}
/**
- * Updates the appearance of the menu and scrim on top of the PiP while dismissing.
- */
- public void setDismissFraction(float fraction) {
- final boolean isMenuVisible = isMenuVisible();
- if (DEBUG) {
- Log.d(TAG, "setDismissFraction() isMenuVisible=" + isMenuVisible
- + " fraction=" + fraction);
- }
- if (isMenuVisible) {
- mPipMenuView.updateDismissFraction(fraction);
- }
- }
-
- /**
* Similar to {@link #showMenu(int, Rect, boolean, boolean, boolean)} but only show the menu
* upon PiP window transition is finished.
*/
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
index 24e49f8..5195140 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
@@ -429,25 +429,6 @@
}
}
- void updateDismissFraction(float fraction) {
- int alpha;
- final float menuAlpha = 1 - fraction;
- if (mMenuState == MENU_STATE_FULL) {
- mMenuContainer.setAlpha(menuAlpha);
- mSettingsButton.setAlpha(menuAlpha);
- mDismissButton.setAlpha(menuAlpha);
- final float interpolatedAlpha =
- MENU_BACKGROUND_ALPHA * menuAlpha + DISMISS_BACKGROUND_ALPHA * fraction;
- alpha = (int) (interpolatedAlpha * 255);
- } else {
- if (mMenuState == MENU_STATE_CLOSE) {
- mDismissButton.setAlpha(menuAlpha);
- }
- alpha = (int) (fraction * DISMISS_BACKGROUND_ALPHA * 255);
- }
- mBackgroundDrawable.setAlpha(alpha);
- }
-
private void notifyMenuStateChange(int menuState, boolean resize, Runnable callback) {
mMenuState = menuState;
mController.onMenuStateChanged(menuState, resize, callback);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
index cc86cf9..fe1d44c7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
@@ -385,23 +385,20 @@
* Flings the PiP to the closest snap target.
*/
void flingToSnapTarget(
- float velocityX, float velocityY,
- @Nullable Runnable updateAction, @Nullable Runnable endAction) {
- movetoTarget(velocityX, velocityY, updateAction, endAction, false /* isStash */);
+ float velocityX, float velocityY, @Nullable Runnable endAction) {
+ movetoTarget(velocityX, velocityY, endAction, false /* isStash */);
}
/**
* Stash PiP to the closest edge.
*/
void stashToEdge(
- float velocityX, float velocityY,
- @Nullable Runnable updateAction, @Nullable Runnable endAction) {
- movetoTarget(velocityX, velocityY, updateAction, endAction, true /* isStash */);
+ float velocityX, float velocityY, @Nullable Runnable endAction) {
+ movetoTarget(velocityX, velocityY, endAction, true /* isStash */);
}
private void movetoTarget(
- float velocityX, float velocityY,
- @Nullable Runnable updateAction, @Nullable Runnable endAction, boolean isStash) {
+ float velocityX, float velocityY, @Nullable Runnable endAction, boolean isStash) {
// If we're flinging to a snap target now, we're not springing to catch up to the touch
// location now.
mSpringingToTouch = false;
@@ -416,11 +413,6 @@
FloatProperties.RECT_Y, velocityY, mFlingConfigY, mSpringConfig)
.withEndActions(endAction);
- if (updateAction != null) {
- mTemporaryBoundsPhysicsAnimator.addUpdateListener(
- (target, values) -> updateAction.run());
- }
-
final float offset = ((float) mBounds.width()) * (1.0f - STASH_RATIO);
final float leftEdge = isStash ? mMovementBounds.left - offset : mMovementBounds.left;
final float rightEdge = isStash ? mMovementBounds.right + offset : mMovementBounds.right;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index 6b31772..07beb43 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -26,40 +26,26 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
-import android.graphics.drawable.TransitionDrawable;
import android.os.Handler;
import android.os.RemoteException;
import android.provider.DeviceConfig;
import android.util.Log;
import android.util.Size;
-import android.view.Gravity;
import android.view.IPinnedStackController;
import android.view.InputEvent;
import android.view.MotionEvent;
-import android.view.View;
import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
-import android.widget.FrameLayout;
-
-import androidx.annotation.NonNull;
-import androidx.dynamicanimation.animation.DynamicAnimation;
-import androidx.dynamicanimation.animation.SpringForce;
import com.android.internal.annotations.VisibleForTesting;
import com.android.wm.shell.R;
-import com.android.wm.shell.animation.PhysicsAnimator;
-import com.android.wm.shell.common.DismissCircleView;
import com.android.wm.shell.common.FloatingContentCoordinator;
-import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.pip.PipBoundsHandler;
import com.android.wm.shell.pip.PipTaskOrganizer;
@@ -67,8 +53,6 @@
import java.io.PrintWriter;
-import kotlin.Unit;
-
/**
* Manages all the touch handling for PIP on the Phone, including moving, dismissing and expanding
* the PIP.
@@ -82,14 +66,12 @@
/* The multiplier to apply scale the target size by when applying the magnetic field radius */
private static final float MAGNETIC_FIELD_RADIUS_MULTIPLIER = 1.25f;
- // Allow dragging the PIP to a location to close it
- private final boolean mEnableDismissDragToEdge;
// Allow PIP to resize to a slightly bigger state upon touch
private final boolean mEnableResize;
private final Context mContext;
- private final WindowManager mWindowManager;
private final PipBoundsHandler mPipBoundsHandler;
private final PipUiEventLogger mPipUiEventLogger;
+ private final PipDismissTargetHandler mPipDismissTargetHandler;
private PipResizeGestureHandler mPipResizeGestureHandler;
private IPinnedStackController mPinnedStackController;
@@ -105,34 +87,6 @@
*/
private boolean mEnableStash = false;
- /**
- * MagnetizedObject wrapper for PIP. This allows the magnetic target library to locate and move
- * PIP.
- */
- private MagnetizedObject<Rect> mMagnetizedPip;
-
- /**
- * Container for the dismiss circle, so that it can be animated within the container via
- * translation rather than within the WindowManager via slow layout animations.
- */
- private ViewGroup mTargetViewContainer;
-
- /** Circle view used to render the dismiss target. */
- private DismissCircleView mTargetView;
-
- /**
- * MagneticTarget instance wrapping the target view and allowing us to set its magnetic radius.
- */
- private MagnetizedObject.MagneticTarget mMagneticTarget;
-
- /** PhysicsAnimator instance for animating the dismiss target in/out. */
- private PhysicsAnimator<View> mMagneticTargetAnimator;
-
- /** Default configuration to use for springing the dismiss target in/out. */
- private final PhysicsAnimator.SpringConfig mTargetSpringConfig =
- new PhysicsAnimator.SpringConfig(
- SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
-
// The current movement bounds
private Rect mMovementBounds = new Rect();
@@ -150,12 +104,6 @@
private int mDeferResizeToNormalBoundsUntilRotation = -1;
private int mDisplayRotation;
- /**
- * Runnable that can be posted delayed to show the target. This needs to be saved as a member
- * variable so we can pass it to removeCallbacks.
- */
- private Runnable mShowTargetAction = this::showDismissTargetMaybe;
-
private Handler mHandler = new Handler();
// Behaviour states
@@ -163,7 +111,6 @@
private boolean mIsImeShowing;
private int mImeHeight;
private int mImeOffset;
- private int mDismissAreaHeight;
private boolean mIsShelfShowing;
private int mShelfHeight;
private int mMovementBoundsExtraOffsets;
@@ -221,7 +168,6 @@
mContext = context;
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
mPipBoundsHandler = pipBoundsHandler;
- mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mMenuController = menuController;
mMenuController.addListener(new PipMenuListener());
mGesture = new DefaultPipTouchGesture();
@@ -231,13 +177,14 @@
new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper,
pipTaskOrganizer, this::getMovementBounds,
this::updateMovementBounds, pipUiEventLogger, menuController);
+ mPipDismissTargetHandler = new PipDismissTargetHandler(context, pipUiEventLogger,
+ mMotionHelper, mHandler);
mTouchState = new PipTouchState(ViewConfiguration.get(context), mHandler,
() -> mMenuController.showMenuWithDelay(MENU_STATE_FULL, mMotionHelper.getBounds(),
true /* allowMenuTimeout */, willResizeMenu(), shouldShowResizeHandle()),
menuController::hideMenu);
Resources res = context.getResources();
- mEnableDismissDragToEdge = res.getBoolean(R.bool.config_pipEnableDismissDragToEdge);
mEnableResize = res.getBoolean(R.bool.config_pipEnableResizeForMenu);
reloadResources();
@@ -248,61 +195,6 @@
mPipUiEventLogger = pipUiEventLogger;
- mTargetView = new DismissCircleView(context);
- mTargetViewContainer = new FrameLayout(context);
- mTargetViewContainer.setBackgroundDrawable(
- context.getDrawable(R.drawable.floating_dismiss_gradient_transition));
- mTargetViewContainer.setClipChildren(false);
- mTargetViewContainer.addView(mTargetView);
-
- mMagnetizedPip = mMotionHelper.getMagnetizedPip();
- mMagneticTarget = mMagnetizedPip.addTarget(mTargetView, 0);
- updateMagneticTargetSize();
-
- mMagnetizedPip.setAnimateStuckToTarget(
- (target, velX, velY, flung, after) -> {
- if (mEnableDismissDragToEdge) {
- mMotionHelper.animateIntoDismissTarget(target, velX, velY, flung, after);
- }
- return Unit.INSTANCE;
- });
- mMagnetizedPip.setMagnetListener(new MagnetizedObject.MagnetListener() {
- @Override
- public void onStuckToTarget(@NonNull MagnetizedObject.MagneticTarget target) {
- // Show the dismiss target, in case the initial touch event occurred within the
- // magnetic field radius.
- if (mEnableDismissDragToEdge) {
- showDismissTargetMaybe();
- }
- }
-
- @Override
- public void onUnstuckFromTarget(@NonNull MagnetizedObject.MagneticTarget target,
- float velX, float velY, boolean wasFlungOut) {
- if (wasFlungOut) {
- mMotionHelper.flingToSnapTarget(velX, velY, null, null);
- hideDismissTarget();
- } else {
- mMotionHelper.setSpringingToTouch(true);
- }
- }
-
- @Override
- public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) {
- mMotionHelper.notifyDismissalPending();
-
- mHandler.post(() -> {
- mMotionHelper.animateDismiss();
- hideDismissTarget();
- });
-
- mPipUiEventLogger.log(
- PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_DRAG_TO_REMOVE);
- }
- });
-
- mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView);
-
mEnableStash = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_SYSTEMUI,
PIP_STASHING,
@@ -323,27 +215,7 @@
mExpandedShortestEdgeSize = res.getDimensionPixelSize(
R.dimen.pip_expanded_shortest_edge_size);
mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
- mDismissAreaHeight = res.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height);
- updateMagneticTargetSize();
- }
-
- private void updateMagneticTargetSize() {
- if (mTargetView == null) {
- return;
- }
-
- final Resources res = mContext.getResources();
- final int targetSize = res.getDimensionPixelSize(R.dimen.dismiss_circle_size);
- final FrameLayout.LayoutParams newParams =
- new FrameLayout.LayoutParams(targetSize, targetSize);
- newParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
- newParams.bottomMargin = mContext.getResources().getDimensionPixelSize(
- R.dimen.floating_dismiss_bottom_margin);
- mTargetView.setLayoutParams(newParams);
-
- // Set the magnetic field radius equal to the target size from the center of the target
- mMagneticTarget.setMagneticFieldRadiusPx(
- (int) (targetSize * MAGNETIC_FIELD_RADIUS_MULTIPLIER));
+ mPipDismissTargetHandler.updateMagneticTargetSize();
}
private boolean shouldShowResizeHandle() {
@@ -368,7 +240,7 @@
}
public void onActivityPinned() {
- createOrUpdateDismissTarget();
+ mPipDismissTargetHandler.createOrUpdateDismissTarget();
mShowPipMenuOnAnimationEnd = true;
mPipResizeGestureHandler.onActivityPinned();
@@ -378,7 +250,7 @@
public void onActivityUnpinned(ComponentName topPipActivity) {
if (topPipActivity == null) {
// Clean up state after the last PiP activity is removed
- cleanUpDismissTarget();
+ mPipDismissTargetHandler.cleanUpDismissTarget();
mFloatingContentCoordinator.onContentRemoved(mMotionHelper);
}
@@ -409,7 +281,7 @@
reloadResources();
// Recreate the dismiss target for the new orientation.
- createOrUpdateDismissTarget();
+ mPipDismissTargetHandler.createOrUpdateDismissTarget();
}
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
@@ -553,94 +425,6 @@
}
}
- /** Adds the magnetic target view to the WindowManager so it's ready to be animated in. */
- private void createOrUpdateDismissTarget() {
- if (!mTargetViewContainer.isAttachedToWindow()) {
- mHandler.removeCallbacks(mShowTargetAction);
- mMagneticTargetAnimator.cancel();
-
- mTargetViewContainer.setVisibility(View.INVISIBLE);
-
- try {
- mWindowManager.addView(mTargetViewContainer, getDismissTargetLayoutParams());
- } catch (IllegalStateException e) {
- // This shouldn't happen, but if the target is already added, just update its layout
- // params.
- mWindowManager.updateViewLayout(
- mTargetViewContainer, getDismissTargetLayoutParams());
- }
- } else {
- mWindowManager.updateViewLayout(mTargetViewContainer, getDismissTargetLayoutParams());
- }
- }
-
- /** Returns layout params for the dismiss target, using the latest display metrics. */
- private WindowManager.LayoutParams getDismissTargetLayoutParams() {
- final Point windowSize = new Point();
- mWindowManager.getDefaultDisplay().getRealSize(windowSize);
-
- final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- WindowManager.LayoutParams.MATCH_PARENT,
- mDismissAreaHeight,
- 0, windowSize.y - mDismissAreaHeight,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
- PixelFormat.TRANSLUCENT);
-
- lp.setTitle("pip-dismiss-overlay");
- lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
- lp.setFitInsetsTypes(0 /* types */);
-
- return lp;
- }
-
- /** Makes the dismiss target visible and animates it in, if it isn't already visible. */
- private void showDismissTargetMaybe() {
- createOrUpdateDismissTarget();
-
- if (mTargetViewContainer.getVisibility() != View.VISIBLE) {
-
- mTargetView.setTranslationY(mTargetViewContainer.getHeight());
- mTargetViewContainer.setVisibility(View.VISIBLE);
-
- // Cancel in case we were in the middle of animating it out.
- mMagneticTargetAnimator.cancel();
- mMagneticTargetAnimator
- .spring(DynamicAnimation.TRANSLATION_Y, 0f, mTargetSpringConfig)
- .start();
-
- ((TransitionDrawable) mTargetViewContainer.getBackground()).startTransition(
- DISMISS_TRANSITION_DURATION_MS);
- }
- }
-
- /** Animates the magnetic dismiss target out and then sets it to GONE. */
- private void hideDismissTarget() {
- mHandler.removeCallbacks(mShowTargetAction);
- mMagneticTargetAnimator
- .spring(DynamicAnimation.TRANSLATION_Y,
- mTargetViewContainer.getHeight(),
- mTargetSpringConfig)
- .withEndActions(() -> mTargetViewContainer.setVisibility(View.GONE))
- .start();
-
- ((TransitionDrawable) mTargetViewContainer.getBackground()).reverseTransition(
- DISMISS_TRANSITION_DURATION_MS);
- }
-
- /**
- * Removes the dismiss target and cancels any pending callbacks to show it.
- */
- private void cleanUpDismissTarget() {
- mHandler.removeCallbacks(mShowTargetAction);
-
- if (mTargetViewContainer.isAttachedToWindow()) {
- mWindowManager.removeViewImmediate(mTargetViewContainer);
- }
- }
-
/**
* TODO Add appropriate description
*/
@@ -650,7 +434,7 @@
if (!isRegistered && mTouchState.isUserInteracting()) {
// If the input consumer is unregistered while the user is interacting, then we may not
// get the final TOUCH_UP event, so clean up the dismiss target as well
- cleanUpDismissTarget();
+ mPipDismissTargetHandler.cleanUpDismissTarget();
}
}
@@ -683,7 +467,7 @@
}
if ((ev.getAction() == MotionEvent.ACTION_DOWN || mTouchState.isUserInteracting())
- && mMagnetizedPip.maybeConsumeMotionEvent(ev)) {
+ && mPipDismissTargetHandler.maybeConsumeMotionEvent(ev)) {
// If the first touch event occurs within the magnetic field, pass the ACTION_DOWN event
// to the touch state. Touch state needs a DOWN event in order to later process MOVE
// events it'll receive if the object is dragged out of the magnetic field.
@@ -793,25 +577,6 @@
}
/**
- * Updates the appearance of the menu and scrim on top of the PiP while dismissing.
- */
- private void updateDismissFraction() {
- if (mMenuController != null) {
- Rect bounds = mMotionHelper.getBounds();
- final float target = mInsetBounds.bottom;
- float fraction = 0f;
- if (bounds.bottom > target) {
- final float distance = bounds.bottom - target;
- fraction = Math.min(distance / bounds.height(), 1f);
- }
- if (Float.compare(fraction, 0f) != 0 || mMenuController.isMenuVisible()) {
- // Update if the fraction > 0, or if fraction == 0 and the menu was already visible
- mMenuController.setDismissFraction(fraction);
- }
- }
- }
-
- /**
* Sets the controller to update the system of changes from user interaction.
*/
void setPinnedStackController(IPinnedStackController controller) {
@@ -958,13 +723,7 @@
if (touchState.startedDragging()) {
mSavedSnapFraction = -1f;
-
- if (mEnableDismissDragToEdge) {
- if (mTargetViewContainer.getVisibility() != View.VISIBLE) {
- mHandler.removeCallbacks(mShowTargetAction);
- showDismissTargetMaybe();
- }
- }
+ mPipDismissTargetHandler.showDismissTargetMaybe();
}
if (touchState.isDragging()) {
@@ -995,9 +754,7 @@
@Override
public boolean onUp(PipTouchState touchState) {
- if (mEnableDismissDragToEdge) {
- hideDismissTarget();
- }
+ mPipDismissTargetHandler.hideDismissTargetMaybe();
if (!touchState.isUserInteracting()) {
return false;
@@ -1023,12 +780,9 @@
if (mEnableStash
&& (animatingBounds.right > mPipBoundsHandler.getDisplayBounds().right
|| animatingBounds.left < mPipBoundsHandler.getDisplayBounds().left)) {
- mMotionHelper.stashToEdge(vel.x, vel.y,
- PipTouchHandler.this::updateDismissFraction /* updateAction */,
- this::flingEndAction /* endAction */);
+ mMotionHelper.stashToEdge(vel.x, vel.y, this::flingEndAction /* endAction */);
} else {
mMotionHelper.flingToSnapTarget(vel.x, vel.y,
- PipTouchHandler.this::updateDismissFraction /* updateAction */,
this::flingEndAction /* endAction */);
}
} else if (mTouchState.isDoubleTap()) {
@@ -1122,7 +876,6 @@
pw.println(innerPrefix + "mIsShelfShowing=" + mIsShelfShowing);
pw.println(innerPrefix + "mShelfHeight=" + mShelfHeight);
pw.println(innerPrefix + "mSavedSnapFraction=" + mSavedSnapFraction);
- pw.println(innerPrefix + "mEnableDragToEdgeDismiss=" + mEnableDismissDragToEdge);
pw.println(innerPrefix + "mMovementBoundsExtraOffsets=" + mMovementBoundsExtraOffsets);
mPipBoundsHandler.dump(pw, innerPrefix);
mTouchState.dump(pw, innerPrefix);
diff --git a/libs/hwui/hwui/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h
index 2989676..77a2142 100644
--- a/libs/hwui/hwui/MinikinSkia.h
+++ b/libs/hwui/hwui/MinikinSkia.h
@@ -49,6 +49,8 @@
void GetFontExtent(minikin::MinikinExtent* extent, const minikin::MinikinPaint& paint,
const minikin::FontFakery& fakery) const override;
+ const std::string& GetFontPath() const override { return mFilePath; }
+
SkTypeface* GetSkTypeface() const;
sk_sp<SkTypeface> RefSkTypeface() const;
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index ccc328c..03f1d62 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -188,7 +188,7 @@
std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>(
std::move(typeface), data, st.st_size, kRobotoFont, 0,
std::vector<minikin::FontVariation>());
- std::vector<minikin::Font> fonts;
+ std::vector<std::shared_ptr<minikin::Font>> fonts;
fonts.push_back(minikin::Font::Builder(font).build());
std::shared_ptr<minikin::FontCollection> collection = std::make_shared<minikin::FontCollection>(
diff --git a/libs/hwui/jni/FontFamily.cpp b/libs/hwui/jni/FontFamily.cpp
index 68eaa0a..2e85840 100644
--- a/libs/hwui/jni/FontFamily.cpp
+++ b/libs/hwui/jni/FontFamily.cpp
@@ -42,7 +42,7 @@
: langId(langId), variant(static_cast<minikin::FamilyVariant>(variant)) {}
uint32_t langId;
minikin::FamilyVariant variant;
- std::vector<minikin::Font> fonts;
+ std::vector<std::shared_ptr<minikin::Font>> fonts;
std::vector<minikin::FontVariation> axes;
};
diff --git a/libs/hwui/jni/FontUtils.h b/libs/hwui/jni/FontUtils.h
index f93a0da..ba4e56e 100644
--- a/libs/hwui/jni/FontUtils.h
+++ b/libs/hwui/jni/FontUtils.h
@@ -19,6 +19,7 @@
#include <jni.h>
#include <memory>
+#include <utility>
#include <minikin/Font.h>
@@ -34,18 +35,10 @@
};
struct FontWrapper {
- FontWrapper(minikin::Font&& font) : font(std::move(font)) {}
- minikin::Font font;
+ explicit FontWrapper(std::shared_ptr<minikin::Font>&& font) : font(font) {}
+ std::shared_ptr<minikin::Font> font;
};
-// We assume FontWrapper's address is the same as underlying Font's address.
-// This assumption is used for looking up Java font object from native address.
-// The Font object can be created without Java's Font object but all Java's Font objects point to
-// the native FontWrapper. So when looking up Java object from minikin::Layout which gives us Font
-// address, we lookup Font Java object from Font address with assumption that it is the same as
-// FontWrapper address.
-static_assert(offsetof(FontWrapper, font) == 0);
-
// Utility wrapper for java.util.List
class ListHelper {
public:
diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp
index 0eb4095..6bc318d 100644
--- a/libs/hwui/jni/fonts/Font.cpp
+++ b/libs/hwui/jni/fonts/Font.cpp
@@ -118,7 +118,7 @@
std::make_shared<MinikinFontSkia>(std::move(face), fontPtr, fontSize,
std::string_view(fontPath.c_str(), fontPath.size()),
ttcIndex, builder->axes);
- minikin::Font font = minikin::Font::Builder(minikinFont).setWeight(weight)
+ std::shared_ptr<minikin::Font> font = minikin::Font::Builder(minikinFont).setWeight(weight)
.setSlant(static_cast<minikin::FontStyle::Slant>(italic)).build();
return reinterpret_cast<jlong>(new FontWrapper(std::move(font)));
}
@@ -127,7 +127,7 @@
static jlong Font_Builder_clone(JNIEnv* env, jobject clazz, jlong fontPtr, jlong builderPtr,
jint weight, jboolean italic, jint ttcIndex) {
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
- MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font.typeface().get());
+ MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->typeface().get());
std::unique_ptr<NativeFontBuilder> builder(toBuilder(builderPtr));
// Reconstruct SkTypeface with different arguments from existing SkTypeface.
@@ -148,8 +148,10 @@
minikinSkia->getFilePath(),
minikinSkia->GetFontIndex(),
builder->axes);
- minikin::Font newFont = minikin::Font::Builder(newMinikinFont).setWeight(weight)
- .setSlant(static_cast<minikin::FontStyle::Slant>(italic)).build();
+ std::shared_ptr<minikin::Font> newFont = minikin::Font::Builder(newMinikinFont)
+ .setWeight(weight)
+ .setSlant(static_cast<minikin::FontStyle::Slant>(italic))
+ .build();
return reinterpret_cast<jlong>(new FontWrapper(std::move(newFont)));
}
@@ -164,7 +166,7 @@
static jfloat Font_getGlyphBounds(JNIEnv* env, jobject, jlong fontHandle, jint glyphId,
jlong paintHandle, jobject rect) {
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
- MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font.typeface().get());
+ MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->typeface().get());
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
SkFont* skFont = &paint->getSkFont();
@@ -184,7 +186,7 @@
static jfloat Font_getFontMetrics(JNIEnv* env, jobject, jlong fontHandle, jlong paintHandle,
jobject metricsObj) {
FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
- MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font.typeface().get());
+ MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font->typeface().get());
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
SkFont* skFont = &paint->getSkFont();
@@ -200,11 +202,11 @@
// Critical Native
static jlong Font_getFontInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontHandle) {
- FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
- MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font.typeface().get());
+ const minikin::Font* font = reinterpret_cast<minikin::Font*>(fontHandle);
+ MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->typeface().get());
- uint64_t result = font->font.style().weight();
- result |= font->font.style().slant() == minikin::FontStyle::Slant::ITALIC ? 0x10000 : 0x00000;
+ uint64_t result = font->style().weight();
+ result |= font->style().slant() == minikin::FontStyle::Slant::ITALIC ? 0x10000 : 0x00000;
result |= ((static_cast<uint64_t>(minikinSkia->GetFontIndex())) << 32);
result |= ((static_cast<uint64_t>(minikinSkia->GetAxes().size())) << 48);
return result;
@@ -212,13 +214,19 @@
// Critical Native
static jlong Font_getAxisInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontHandle, jint index) {
- FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
- MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->font.typeface().get());
+ const minikin::Font* font = reinterpret_cast<minikin::Font*>(fontHandle);
+ MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->typeface().get());
const minikin::FontVariation& var = minikinSkia->GetAxes().at(index);
uint32_t floatBinary = *reinterpret_cast<const uint32_t*>(&var.value);
return (static_cast<uint64_t>(var.axisTag) << 32) | static_cast<uint64_t>(floatBinary);
}
+// Critical Native
+static jlong Font_getNativeFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontHandle) {
+ FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
+ return reinterpret_cast<jlong>(font->font.get());
+}
+
///////////////////////////////////////////////////////////////////////////////
struct FontBufferWrapper {
@@ -234,8 +242,8 @@
// Critical Native
static jlong FontBufferHelper_refFontBuffer(CRITICAL_JNI_PARAMS_COMMA jlong fontHandle) {
- FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
- return reinterpret_cast<jlong>(new FontBufferWrapper(font->font.typeface()));
+ const minikin::Font* font = reinterpret_cast<minikin::Font*>(fontHandle);
+ return reinterpret_cast<jlong>(new FontBufferWrapper(font->typeface()));
}
// Fast Native
@@ -266,6 +274,7 @@
{ "nGetFontMetrics", "(JJLandroid/graphics/Paint$FontMetrics;)F", (void*) Font_getFontMetrics },
{ "nGetFontInfo", "(J)J", (void*) Font_getFontInfo },
{ "nGetAxisInfo", "(JI)J", (void*) Font_getAxisInfo },
+ { "nGetNativeFontPtr", "(J)J", (void*) Font_getNativeFontPtr },
};
static const JNINativeMethod gFontBufferHelperMethods[] = {
diff --git a/libs/hwui/jni/fonts/FontFamily.cpp b/libs/hwui/jni/fonts/FontFamily.cpp
index df619d9..37e5276 100644
--- a/libs/hwui/jni/fonts/FontFamily.cpp
+++ b/libs/hwui/jni/fonts/FontFamily.cpp
@@ -30,7 +30,7 @@
namespace android {
struct NativeFamilyBuilder {
- std::vector<minikin::Font> fonts;
+ std::vector<std::shared_ptr<minikin::Font>> fonts;
};
static inline NativeFamilyBuilder* toBuilder(jlong ptr) {
diff --git a/libs/hwui/tests/unit/TypefaceTests.cpp b/libs/hwui/tests/unit/TypefaceTests.cpp
index b5baafd..5d2aa2f 100644
--- a/libs/hwui/tests/unit/TypefaceTests.cpp
+++ b/libs/hwui/tests/unit/TypefaceTests.cpp
@@ -59,7 +59,7 @@
std::shared_ptr<minikin::MinikinFont> font =
std::make_shared<MinikinFontSkia>(std::move(typeface), data, st.st_size, fileName, 0,
std::vector<minikin::FontVariation>());
- std::vector<minikin::Font> fonts;
+ std::vector<std::shared_ptr<minikin::Font>> fonts;
fonts.push_back(minikin::Font::Builder(font).build());
return std::make_shared<minikin::FontFamily>(std::move(fonts));
}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 31dcd7e..5ae9dd2 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -46,7 +46,7 @@
*/
interface ILocationManager
{
- Location getLastLocation(String provider, String packageName, String attributionTag);
+ @nullable Location getLastLocation(String provider, String packageName, String attributionTag);
@nullable ICancellationSignal getCurrentLocation(String provider, in LocationRequest request, in ILocationCallback callback, String packageName, String attributionTag, String listenerId);
void registerLocationListener(String provider, in LocationRequest request, in ILocationListener listener, String packageName, String attributionTag, String listenerId);
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index c57794f..3bb4781 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -750,7 +750,7 @@
s.append(qualityToString(mQuality)).append(" ");
}
if (mInterval != PASSIVE_INTERVAL) {
- s.append("interval=");
+ s.append("@");
TimeUtils.formatDuration(mInterval, s);
} else {
s.append("PASSIVE");
@@ -765,7 +765,8 @@
if (mMaxUpdates != Integer.MAX_VALUE) {
s.append(" maxUpdates=").append(mMaxUpdates);
}
- if (mMinUpdateIntervalMillis < mInterval) {
+ if (mMinUpdateIntervalMillis != IMPLICIT_MIN_UPDATE_INTERVAL
+ && mMinUpdateIntervalMillis < mInterval) {
s.append(" minUpdateInterval=");
TimeUtils.formatDuration(mMinUpdateIntervalMillis, s);
}
diff --git a/location/java/android/location/util/identity/CallerIdentity.java b/location/java/android/location/util/identity/CallerIdentity.java
index c32970f..e023aa1 100644
--- a/location/java/android/location/util/identity/CallerIdentity.java
+++ b/location/java/android/location/util/identity/CallerIdentity.java
@@ -150,6 +150,11 @@
return mListenerId;
}
+ /** Returns true if this represents a system identity. */
+ public boolean isSystem() {
+ return mUid == Process.SYSTEM_UID;
+ }
+
/**
* Adds this identity to the worksource supplied, or if not worksource is supplied, creates a
* new worksource representing this identity.
diff --git a/media/java/android/media/tv/TvChannelInfo.java b/media/java/android/media/tv/TvChannelInfo.java
index 635b130..11cb1f7 100644
--- a/media/java/android/media/tv/TvChannelInfo.java
+++ b/media/java/android/media/tv/TvChannelInfo.java
@@ -22,19 +22,44 @@
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
/**
+ * This class is used to specify information of a TV channel.
* @hide
*/
public final class TvChannelInfo implements Parcelable {
static final String TAG = "TvChannelInfo";
+
+ /**
+ * App tag for {@link #getAppTag()}: the corresponding application of the channel is the same as
+ * the caller.
+ * <p>{@link #getAppType()} returns {@link #APP_TYPE_SELF} if and only if the app tag is
+ * {@link #APP_TAG_SELF}.
+ */
public static final int APP_TAG_SELF = 0;
+ /**
+ * App tag for {@link #getAppType()}: the corresponding application of the channel is the same
+ * as the caller.
+ * <p>{@link #getAppType()} returns {@link #APP_TYPE_SELF} if and only if the app tag is
+ * {@link #APP_TAG_SELF}.
+ */
public static final int APP_TYPE_SELF = 1;
+ /**
+ * App tag for {@link #getAppType()}: the corresponding app of the channel is a system
+ * application.
+ */
public static final int APP_TYPE_SYSTEM = 2;
+ /**
+ * App tag for {@link #getAppType()}: the corresponding app of the channel is not a system
+ * application.
+ */
public static final int APP_TYPE_NON_SYSTEM = 3;
/** @hide */
@@ -68,6 +93,7 @@
@AppType private final int mAppType;
private final int mAppTag;
+ /** @hide */
public TvChannelInfo(
String inputId, @Nullable Uri channelUri, boolean isRecordingSession,
boolean isForeground, @AppType int appType, int appTag) {
@@ -90,24 +116,41 @@
mAppTag = source.readInt();
}
+ /**
+ * Returns the TV input ID of the channel.
+ */
+ @NonNull
public String getInputId() {
return mInputId;
}
+ /**
+ * Returns the channel URI of the channel.
+ * <p>Returns {@code null} if it's a passthrough input or the permission is not granted.
+ */
+ @Nullable
public Uri getChannelUri() {
return mChannelUri;
}
+ /**
+ * Returns {@code true} if the channel session is a recording session.
+ * @see TvInputService.RecordingSession
+ */
public boolean isRecordingSession() {
return mIsRecordingSession;
}
+ /**
+ * Returns {@code true} if the application is a foreground application.
+ * @see android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
+ */
public boolean isForeground() {
return mIsForeground;
}
/**
- * Gets app tag.
+ * Returns the app tag.
* <p>App tag is used to differentiate one app from another.
* {@link #APP_TAG_SELF} is for current app.
*/
@@ -115,6 +158,9 @@
return mAppTag;
}
+ /**
+ * Returns the app type.
+ */
@AppType
public int getAppType() {
return mAppType;
@@ -126,7 +172,7 @@
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mInputId);
String uriString = mChannelUri == null ? null : mChannelUri.toString();
dest.writeString(uriString);
@@ -145,4 +191,26 @@
+ ";appType=" + mAppType
+ ";appTag=" + mAppTag;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof TvChannelInfo)) {
+ return false;
+ }
+
+ TvChannelInfo other = (TvChannelInfo) o;
+
+ return TextUtils.equals(mInputId, other.getInputId())
+ && Objects.equals(mChannelUri, other.mChannelUri)
+ && mIsRecordingSession == other.mIsRecordingSession
+ && mIsForeground == other.mIsForeground
+ && mAppType == other.mAppType
+ && mAppTag == other.mAppTag;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ mInputId, mChannelUri, mIsRecordingSession, mIsForeground, mAppType, mAppTag);
+ }
}
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index d38369f..c80f3c6 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -900,8 +900,13 @@
public void onTvInputInfoUpdated(TvInputInfo inputInfo) {
}
- /** @hide */
- public void onCurrentTvChannelInfosUpdated(List<TvChannelInfo> tvChannelInfos) {
+ /**
+ * This is called when the information about current TV channels has been updated.
+ *
+ * @param tvChannelInfos a list of {@link TvChannelInfo} objects of new current channels.
+ * @hide
+ */
+ public void onCurrentTvChannelInfosUpdated(@NonNull List<TvChannelInfo> tvChannelInfos) {
}
}
@@ -1976,8 +1981,15 @@
}
/**
+ * Returns the list of TV channel information for {@link TvInputService.Session} that are
+ * currently in use.
+ * <p> Permission com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS is required to get
+ * the channel URIs. If the permission is not granted, {@link TvChannelInfo#getChannelUri()}
+ * returns {@code null}.
* @hide
*/
+ @RequiresPermission("com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS")
+ @NonNull
public List<TvChannelInfo> getCurrentTvChannelInfos() {
try {
return mService.getCurrentTvChannelInfos(mUserId);
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index 0af6cbf..0a466f4 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -317,10 +317,9 @@
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
sp<SurfaceControl> newParentSurfaceControl = ASurfaceControl_to_SurfaceControl(
newParentASurfaceControl);
- sp<IBinder> newParentHandle = (newParentSurfaceControl)? newParentSurfaceControl->getHandle() : nullptr;
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
- transaction->reparent(surfaceControl, newParentHandle);
+ transaction->reparent(surfaceControl, newParentSurfaceControl);
}
void ASurfaceTransaction_setVisibility(ASurfaceTransaction* aSurfaceTransaction,
diff --git a/non-updatable-api/Android.bp b/non-updatable-api/Android.bp
index 4037781..00b9019 100644
--- a/non-updatable-api/Android.bp
+++ b/non-updatable-api/Android.bp
@@ -23,13 +23,31 @@
}
filegroup {
+ name: "non-updatable-removed.txt",
+ srcs: ["removed.txt"],
+ visibility: ["//frameworks/base/api"],
+}
+
+filegroup {
name: "non-updatable-system-current.txt",
srcs: ["system-current.txt"],
visibility: ["//frameworks/base/api"],
}
filegroup {
+ name: "non-updatable-system-removed.txt",
+ srcs: ["system-removed.txt"],
+ visibility: ["//frameworks/base/api"],
+}
+
+filegroup {
name: "non-updatable-module-lib-current.txt",
srcs: ["module-lib-current.txt"],
visibility: ["//frameworks/base/api"],
}
+
+filegroup {
+ name: "non-updatable-module-lib-removed.txt",
+ srcs: ["module-lib-removed.txt"],
+ visibility: ["//frameworks/base/api"],
+}
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index 3cc1e42..983f20a 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -646,10 +646,10 @@
field public static final int font = 16844082; // 0x1010532
field public static final int fontFamily = 16843692; // 0x10103ac
field public static final int fontFeatureSettings = 16843959; // 0x10104b7
- field public static final int fontProviderAuthority = 16844112; // 0x1010550
- field public static final int fontProviderCerts = 16844125; // 0x101055d
- field public static final int fontProviderPackage = 16844119; // 0x1010557
- field public static final int fontProviderQuery = 16844113; // 0x1010551
+ field @Deprecated public static final int fontProviderAuthority = 16844112; // 0x1010550
+ field @Deprecated public static final int fontProviderCerts = 16844125; // 0x101055d
+ field @Deprecated public static final int fontProviderPackage = 16844119; // 0x1010557
+ field @Deprecated public static final int fontProviderQuery = 16844113; // 0x1010551
field public static final int fontStyle = 16844095; // 0x101053f
field public static final int fontVariationSettings = 16844144; // 0x1010570
field public static final int fontWeight = 16844083; // 0x1010533
@@ -35210,7 +35210,7 @@
method public int dataCapacity();
method public int dataPosition();
method public int dataSize();
- method public void enforceInterface(String);
+ method public void enforceInterface(@NonNull String);
method public boolean hasFileDescriptors();
method public byte[] marshall();
method @NonNull public static android.os.Parcel obtain();
@@ -35281,7 +35281,7 @@
method public void writeFloatArray(@Nullable float[]);
method public void writeInt(int);
method public void writeIntArray(@Nullable int[]);
- method public void writeInterfaceToken(String);
+ method public void writeInterfaceToken(@NonNull String);
method public void writeList(@Nullable java.util.List);
method public void writeLong(long);
method public void writeLongArray(@Nullable long[]);
@@ -38725,62 +38725,62 @@
method public final int update(android.net.Uri, android.content.ContentValues, String, String[]);
}
- public final class FontRequest {
- ctor public FontRequest(@NonNull String, @NonNull String, @NonNull String);
- ctor public FontRequest(@NonNull String, @NonNull String, @NonNull String, @NonNull java.util.List<java.util.List<byte[]>>);
- method public java.util.List<java.util.List<byte[]>> getCertificates();
- method public String getProviderAuthority();
- method public String getProviderPackage();
- method public String getQuery();
+ @Deprecated public final class FontRequest {
+ ctor @Deprecated public FontRequest(@NonNull String, @NonNull String, @NonNull String);
+ ctor @Deprecated public FontRequest(@NonNull String, @NonNull String, @NonNull String, @NonNull java.util.List<java.util.List<byte[]>>);
+ method @Deprecated public java.util.List<java.util.List<byte[]>> getCertificates();
+ method @Deprecated public String getProviderAuthority();
+ method @Deprecated public String getProviderPackage();
+ method @Deprecated public String getQuery();
}
- public class FontsContract {
- method public static android.graphics.Typeface buildTypeface(@NonNull android.content.Context, @Nullable android.os.CancellationSignal, @NonNull android.provider.FontsContract.FontInfo[]);
- method @NonNull public static android.provider.FontsContract.FontFamilyResult fetchFonts(@NonNull android.content.Context, @Nullable android.os.CancellationSignal, @NonNull android.provider.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
- method public static void requestFonts(@NonNull android.content.Context, @NonNull android.provider.FontRequest, @NonNull android.os.Handler, @Nullable android.os.CancellationSignal, @NonNull android.provider.FontsContract.FontRequestCallback);
+ @Deprecated public class FontsContract {
+ method @Deprecated public static android.graphics.Typeface buildTypeface(@NonNull android.content.Context, @Nullable android.os.CancellationSignal, @NonNull android.provider.FontsContract.FontInfo[]);
+ method @Deprecated @NonNull public static android.provider.FontsContract.FontFamilyResult fetchFonts(@NonNull android.content.Context, @Nullable android.os.CancellationSignal, @NonNull android.provider.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @Deprecated public static void requestFonts(@NonNull android.content.Context, @NonNull android.provider.FontRequest, @NonNull android.os.Handler, @Nullable android.os.CancellationSignal, @NonNull android.provider.FontsContract.FontRequestCallback);
}
- public static final class FontsContract.Columns implements android.provider.BaseColumns {
- field public static final String FILE_ID = "file_id";
- field public static final String ITALIC = "font_italic";
- field public static final String RESULT_CODE = "result_code";
- field public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
- field public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
- field public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
- field public static final int RESULT_CODE_OK = 0; // 0x0
- field public static final String TTC_INDEX = "font_ttc_index";
- field public static final String VARIATION_SETTINGS = "font_variation_settings";
- field public static final String WEIGHT = "font_weight";
+ @Deprecated public static final class FontsContract.Columns implements android.provider.BaseColumns {
+ field @Deprecated public static final String FILE_ID = "file_id";
+ field @Deprecated public static final String ITALIC = "font_italic";
+ field @Deprecated public static final String RESULT_CODE = "result_code";
+ field @Deprecated public static final int RESULT_CODE_FONT_NOT_FOUND = 1; // 0x1
+ field @Deprecated public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; // 0x2
+ field @Deprecated public static final int RESULT_CODE_MALFORMED_QUERY = 3; // 0x3
+ field @Deprecated public static final int RESULT_CODE_OK = 0; // 0x0
+ field @Deprecated public static final String TTC_INDEX = "font_ttc_index";
+ field @Deprecated public static final String VARIATION_SETTINGS = "font_variation_settings";
+ field @Deprecated public static final String WEIGHT = "font_weight";
}
- public static class FontsContract.FontFamilyResult {
- method @NonNull public android.provider.FontsContract.FontInfo[] getFonts();
- method public int getStatusCode();
- field public static final int STATUS_OK = 0; // 0x0
- field public static final int STATUS_REJECTED = 3; // 0x3
- field public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; // 0x2
- field public static final int STATUS_WRONG_CERTIFICATES = 1; // 0x1
+ @Deprecated public static class FontsContract.FontFamilyResult {
+ method @Deprecated @NonNull public android.provider.FontsContract.FontInfo[] getFonts();
+ method @Deprecated public int getStatusCode();
+ field @Deprecated public static final int STATUS_OK = 0; // 0x0
+ field @Deprecated public static final int STATUS_REJECTED = 3; // 0x3
+ field @Deprecated public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; // 0x2
+ field @Deprecated public static final int STATUS_WRONG_CERTIFICATES = 1; // 0x1
}
- public static class FontsContract.FontInfo {
- method @Nullable public android.graphics.fonts.FontVariationAxis[] getAxes();
- method public int getResultCode();
- method @IntRange(from=0) public int getTtcIndex();
- method @NonNull public android.net.Uri getUri();
- method @IntRange(from=1, to=1000) public int getWeight();
- method public boolean isItalic();
+ @Deprecated public static class FontsContract.FontInfo {
+ method @Deprecated @Nullable public android.graphics.fonts.FontVariationAxis[] getAxes();
+ method @Deprecated public int getResultCode();
+ method @Deprecated @IntRange(from=0) public int getTtcIndex();
+ method @Deprecated @NonNull public android.net.Uri getUri();
+ method @Deprecated @IntRange(from=1, to=1000) public int getWeight();
+ method @Deprecated public boolean isItalic();
}
- public static class FontsContract.FontRequestCallback {
- ctor public FontsContract.FontRequestCallback();
- method public void onTypefaceRequestFailed(int);
- method public void onTypefaceRetrieved(android.graphics.Typeface);
- field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
- field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
- field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
- field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
- field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
- field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
+ @Deprecated public static class FontsContract.FontRequestCallback {
+ ctor @Deprecated public FontsContract.FontRequestCallback();
+ method @Deprecated public void onTypefaceRequestFailed(int);
+ method @Deprecated public void onTypefaceRetrieved(android.graphics.Typeface);
+ field @Deprecated public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+ field @Deprecated public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+ field @Deprecated public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+ field @Deprecated public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+ field @Deprecated public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+ field @Deprecated public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
}
@Deprecated public final class LiveFolders implements android.provider.BaseColumns {
diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt
index 11cd6a9..003a363 100644
--- a/non-updatable-api/module-lib-current.txt
+++ b/non-updatable-api/module-lib-current.txt
@@ -19,7 +19,7 @@
package android.app.role {
public final class RoleManager {
- method @Nullable public String getDefaultSmsPackage(int);
+ method @Nullable public String getSmsRoleHolder(int);
}
}
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index 7a64d28..04847d5 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -95,6 +95,7 @@
field public static final String INJECT_EVENTS = "android.permission.INJECT_EVENTS";
field public static final String INSTALL_DYNAMIC_SYSTEM = "android.permission.INSTALL_DYNAMIC_SYSTEM";
field public static final String INSTALL_GRANT_RUNTIME_PERMISSIONS = "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS";
+ field public static final String INSTALL_LOCATION_TIME_ZONE_PROVIDER = "android.permission.INSTALL_LOCATION_TIME_ZONE_PROVIDER";
field public static final String INSTALL_PACKAGE_UPDATES = "android.permission.INSTALL_PACKAGE_UPDATES";
field public static final String INSTALL_SELF_UPDATES = "android.permission.INSTALL_SELF_UPDATES";
field public static final String INTENT_FILTER_VERIFICATION_AGENT = "android.permission.INTENT_FILTER_VERIFICATION_AGENT";
@@ -125,6 +126,7 @@
field public static final String MANAGE_SENSOR_PRIVACY = "android.permission.MANAGE_SENSOR_PRIVACY";
field public static final String MANAGE_SOUND_TRIGGER = "android.permission.MANAGE_SOUND_TRIGGER";
field public static final String MANAGE_SUBSCRIPTION_PLANS = "android.permission.MANAGE_SUBSCRIPTION_PLANS";
+ field public static final String MANAGE_TIME_AND_ZONE_DETECTION = "android.permission.MANAGE_TIME_AND_ZONE_DETECTION";
field public static final String MANAGE_USB = "android.permission.MANAGE_USB";
field public static final String MANAGE_USERS = "android.permission.MANAGE_USERS";
field public static final String MANAGE_USER_OEM_UNLOCK_STATE = "android.permission.MANAGE_USER_OEM_UNLOCK_STATE";
@@ -305,6 +307,7 @@
field public static final int config_helpPackageNameValue = 17039388; // 0x104001c
field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
field public static final int config_systemGallery = 17039399; // 0x1040027
+ field public static final int config_systemVideoCall = 17039401; // 0x1040029
}
public static final class R.style {
@@ -1329,6 +1332,57 @@
}
+package android.app.time {
+
+ public final class TimeManager {
+ method @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public void addTimeZoneDetectorListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.time.TimeManager.TimeZoneDetectorListener);
+ method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public android.app.time.TimeZoneCapabilitiesAndConfig getTimeZoneCapabilitiesAndConfig();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public void removeTimeZoneDetectorListener(@NonNull android.app.time.TimeManager.TimeZoneDetectorListener);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION) public boolean updateTimeZoneConfiguration(@NonNull android.app.time.TimeZoneConfiguration);
+ }
+
+ @java.lang.FunctionalInterface public static interface TimeManager.TimeZoneDetectorListener {
+ method public void onChange();
+ }
+
+ public final class TimeZoneCapabilities implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getConfigureAutoDetectionEnabledCapability();
+ method public int getConfigureGeoDetectionEnabledCapability();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CAPABILITY_NOT_ALLOWED = 20; // 0x14
+ field public static final int CAPABILITY_NOT_APPLICABLE = 30; // 0x1e
+ field public static final int CAPABILITY_NOT_SUPPORTED = 10; // 0xa
+ field public static final int CAPABILITY_POSSESSED = 40; // 0x28
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.time.TimeZoneCapabilities> CREATOR;
+ }
+
+ public final class TimeZoneCapabilitiesAndConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.app.time.TimeZoneCapabilities getCapabilities();
+ method @NonNull public android.app.time.TimeZoneConfiguration getConfiguration();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.time.TimeZoneCapabilitiesAndConfig> CREATOR;
+ }
+
+ public final class TimeZoneConfiguration implements android.os.Parcelable {
+ method public int describeContents();
+ method public boolean isAutoDetectionEnabled();
+ method public boolean isGeoDetectionEnabled();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.time.TimeZoneConfiguration> CREATOR;
+ }
+
+ public static final class TimeZoneConfiguration.Builder {
+ ctor public TimeZoneConfiguration.Builder();
+ ctor public TimeZoneConfiguration.Builder(@NonNull android.app.time.TimeZoneConfiguration);
+ method @NonNull public android.app.time.TimeZoneConfiguration build();
+ method @NonNull public android.app.time.TimeZoneConfiguration.Builder setAutoDetectionEnabled(boolean);
+ method @NonNull public android.app.time.TimeZoneConfiguration.Builder setGeoDetectionEnabled(boolean);
+ }
+
+}
+
package android.app.usage {
public final class CacheQuotaHint implements android.os.Parcelable {
@@ -10272,6 +10326,7 @@
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<java.lang.String> getEquivalentHomePlmns();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index d2485cc..506b608 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -892,9 +892,6 @@
Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED,
GlobalSettingsProto.Location.SETTINGS_LINK_TO_PERMISSIONS_ENABLED);
dumpSetting(s, p,
- Settings.Global.LOCATION_GLOBAL_KILL_SWITCH,
- GlobalSettingsProto.Location.GLOBAL_KILL_SWITCH);
- dumpSetting(s, p,
Settings.Global.GNSS_SATELLITE_BLACKLIST,
GlobalSettingsProto.Location.GNSS_SATELLITE_BLACKLIST);
dumpSetting(s, p,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 3ccb1f4..710c016 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -328,10 +328,6 @@
return SettingsState.getUserIdFromKey(key);
}
- public static String settingTypeToString(int type) {
- return SettingsState.settingTypeToString(type);
- }
-
public static String keyToString(int key) {
return SettingsState.keyToString(key);
}
@@ -373,8 +369,7 @@
}
case Settings.CALL_METHOD_GET_SECURE: {
- Setting setting = getSecureSetting(name, requestingUserId,
- /*enableOverride=*/ true);
+ Setting setting = getSecureSetting(name, requestingUserId);
return packageValueForCallResult(setting, isTrackingGeneration(args));
}
@@ -581,7 +576,7 @@
}
private ArrayList<String> buildSettingsList(Cursor cursor) {
- final ArrayList<String> lines = new ArrayList<String>();
+ final ArrayList<String> lines = new ArrayList<>();
try {
while (cursor != null && cursor.moveToNext()) {
lines.add(cursor.getString(1) + "=" + cursor.getString(2));
@@ -1381,10 +1376,6 @@
}
private Setting getSecureSetting(String name, int requestingUserId) {
- return getSecureSetting(name, requestingUserId, /*enableOverride=*/ false);
- }
-
- private Setting getSecureSetting(String name, int requestingUserId, boolean enableOverride) {
if (DEBUG) {
Slog.v(LOG_TAG, "getSecureSetting(" + name + ", " + requestingUserId + ")");
}
@@ -1414,14 +1405,6 @@
return getSsaidSettingLocked(callingPkg, owningUserId);
}
}
- if (enableOverride) {
- if (Secure.LOCATION_MODE.equals(name)) {
- final Setting overridden = getLocationModeSetting(owningUserId);
- if (overridden != null) {
- return overridden;
- }
- }
- }
// Not the SSAID; do a straight lookup
synchronized (mLock) {
@@ -1511,35 +1494,6 @@
return null;
}
- private Setting getLocationModeSetting(int owningUserId) {
- synchronized (mLock) {
- final Setting setting = getGlobalSetting(
- Global.LOCATION_GLOBAL_KILL_SWITCH);
- if (!"1".equals(setting.getValue())) {
- return null;
- }
- // Global kill-switch is enabled. Return an empty value.
- final SettingsState settingsState = mSettingsRegistry.getSettingsLocked(
- SETTINGS_TYPE_SECURE, owningUserId);
- return settingsState.new Setting(
- Secure.LOCATION_MODE,
- "", // value
- "", // tag
- "", // default value
- "", // package name
- false, // from system
- "0" // id
- ) {
- @Override
- public boolean update(String value, boolean setDefault, String packageName,
- String tag, boolean forceNonSystemPackage, boolean overrideableByRestore) {
- Slog.wtf(LOG_TAG, "update shouldn't be called on this instance.");
- return false;
- }
- };
- }
- }
-
private boolean insertSecureSetting(String name, String value, String tag,
boolean makeDefault, int requestingUserId, boolean forceNotify,
boolean overrideableByRestore) {
@@ -1808,12 +1762,8 @@
private boolean hasWriteSecureSettingsPermission() {
// Write secure settings is a more protected permission. If caller has it we are good.
- if (getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
- == PackageManager.PERMISSION_GRANTED) {
- return true;
- }
-
- return false;
+ return getContext().checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+ == PackageManager.PERMISSION_GRANTED;
}
private void validateSystemSettingValue(String name, String value) {
@@ -3174,12 +3124,6 @@
if (isGlobalSettingsKey(key) || isConfigSettingsKey(key)) {
final long token = Binder.clearCallingIdentity();
try {
- if (Global.LOCATION_GLOBAL_KILL_SWITCH.equals(name)
- && isGlobalSettingsKey(key)) {
- // When the global kill switch is updated, send the
- // change notification for the location setting.
- notifyLocationChangeForRunningUsers();
- }
notifySettingChangeForRunningUsers(key, name);
} finally {
Binder.restoreCallingIdentity(token);
@@ -3257,26 +3201,6 @@
}
}
- private void notifyLocationChangeForRunningUsers() {
- final List<UserInfo> users = mUserManager.getAliveUsers();
-
- for (int i = 0; i < users.size(); i++) {
- final int userId = users.get(i).id;
-
- if (!mUserManager.isUserRunning(UserHandle.of(userId))) {
- continue;
- }
-
- // Increment the generation first, so observers always see the new value
- final int key = makeKey(SETTINGS_TYPE_SECURE, userId);
- mGenerationRegistry.incrementGeneration(key);
-
- final Uri uri = getNotificationUriFor(key, Secure.LOCATION_MODE);
- mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
- userId, 0, uri).sendToTarget();
- }
- }
-
private boolean isConfigSettingsKey(int key) {
return getTypeFromKey(key) == SETTINGS_TYPE_CONFIG;
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 6678cf6..b061df1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -34,7 +34,6 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
-import android.provider.Settings.Global;
import android.providers.settings.SettingsOperationProto;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -47,7 +46,6 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
import libcore.io.IoUtils;
@@ -817,13 +815,6 @@
for (int i = 0; i < settingCount; i++) {
Setting setting = settings.valueAt(i);
- if (setting.isTransient()) {
- if (DEBUG_PERSISTENCE) {
- Slog.i(LOG_TAG, "[SKIPPED PERSISTING]" + setting.getName());
- }
- continue;
- }
-
writeSingleSetting(mVersion, serializer, setting.getId(), setting.getName(),
setting.getValue(), setting.getDefaultValue(), setting.getPackageName(),
setting.getTag(), setting.isDefaultFromSystem(),
@@ -1109,8 +1100,7 @@
ATTR_DEFAULT_VALUE_BASE64);
String isPreservedInRestoreString = parser.getAttributeValue(null,
ATTR_PRESERVE_IN_RESTORE);
- boolean isPreservedInRestore = isPreservedInRestoreString != null
- && Boolean.parseBoolean(isPreservedInRestoreString);
+ boolean isPreservedInRestore = Boolean.parseBoolean(isPreservedInRestoreString);
String tag = null;
boolean fromSystem = false;
if (defaultValue != null) {
@@ -1308,14 +1298,6 @@
/* resetToDefault */ true);
}
- public boolean isTransient() {
- switch (getTypeFromKey(getKey())) {
- case SETTINGS_TYPE_GLOBAL:
- return ArrayUtils.contains(Global.TRANSIENT_SETTINGS, getName());
- }
- return false;
- }
-
public boolean update(String value, boolean setDefault, String packageName, String tag,
boolean forceNonSystemPackage, boolean overrideableByRestore) {
return update(value, setDefault, packageName, tag, forceNonSystemPackage,
@@ -1444,7 +1426,7 @@
}
private static String fromBytes(byte[] bytes) {
- final StringBuffer sb = new StringBuffer(bytes.length / 2);
+ final StringBuilder sb = new StringBuilder(bytes.length / 2);
final int last = bytes.length - 1;
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 72dfe74..7d3390d 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Instellings"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vergrotingvenster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Vergrotingvensterkontroles"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Toestelkontroles"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Voeg kontroles vir jou gekoppelde toestelle by"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Stel toestelkontroles op"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ontkoppel)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Kon nie koppel nie. Probeer weer."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Bind nuwe toestel saam"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 0ec236d..a91182e 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ቅንብሮች"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"የማጉያ መስኮት"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"የማጉያ መስኮት መቆጣጠሪያዎች"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"የመሣሪያ መቆጣጠሪያዎች"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"ለእርስዎ የተገናኙ መሣሪያዎች መቆጣጠሪያዎችን ያክሉ"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"የመሣሪያ መቆጣጠሪያዎችን ያቀናብሩ"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ግንኙነት ተቋርጧል)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ማገናኘት አልተቻለም። እንደገና ይሞክሩ።"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"አዲስ መሣሪያ ያጣምሩ"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index b09e5b9..74a9b64 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -1032,6 +1032,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"الإعدادات"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"نافذة التكبير"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"عناصر التحكم في نافذة التكبير"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"أدوات التحكم بالأجهزة"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"إضافة عناصر تحكّم لأجهزتك المتصلة"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"إعداد أدوات التحكم بالجهاز"</string>
@@ -1049,7 +1061,7 @@
<string name="accessibility_control_favorite" msgid="8694362691985545985">"تمت الإضافة إلى المفضّلة"</string>
<string name="accessibility_control_favorite_position" msgid="54220258048929221">"تمت الإضافة إلى المفضّلة، الموضع <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_control_not_favorite" msgid="1291760269563092359">"تمت الإزالة من المفضّلة"</string>
- <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"إضافة إلى المُفضلة"</string>
+ <string name="accessibility_control_change_favorite" msgid="2943178027582253261">"إضافة إلى المحتوى المفضّل"</string>
<string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"إزالة من المفضّلة"</string>
<string name="accessibility_control_move" msgid="8980344493796647792">"نقل إلى الموضع <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="controls_favorite_default_title" msgid="967742178688938137">"عناصر التحكّم"</string>
@@ -1099,4 +1111,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (غير متّصل)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"تعذّر الاتصال. يُرجى إعادة المحاولة."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"إقران جهاز جديد"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 61ba6dc..297d774 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ছেটিংসমূহ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"বিবৰ্ধন ৱিণ্ড’"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"বিবৰ্ধন ৱিণ্ড’ৰ নিয়ন্ত্ৰণসমূহ"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ডিভাইচৰ নিয়ন্ত্ৰণসমূহ"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"আপোনাৰ সংযোজিত ডিভাইচসমূহৰ বাবে নিয়ন্ত্ৰণসমূহ যোগ কৰক"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"ডিভাইচৰ নিয়ন্ত্ৰণসমূহ ছেট আপ কৰক"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (সংযোগ বিচ্ছিন্ন হৈছে)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"সংযোগ কৰিব পৰা নগ’ল। পুনৰ চেষ্টা কৰক।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"নতুন ডিভাইচ পেয়াৰ কৰক"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index bee0e5f..debad02 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Ayarlar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Böyütmə Pəncərəsi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Böyütmə Pəncərəsi Kontrolları"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Cihaz idarəetmələri"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Qoşulmuş cihazlarınız üçün nizamlayıcılar əlavə edin"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Cihaz idarəetmələrini ayarlayın"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (bağlantı kəsilib)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Qoşulmaq alınmadı. Yenə cəhd edin."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yeni cihazı qoşalaşdırın"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 5966356..be31c2d 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -1017,6 +1017,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Podešavanja"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Prozor za uvećanje"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za uvećanje"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Kontrole uređaja"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Dodajte kontrole za povezane uređaje"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Podesite kontrole uređaja"</string>
@@ -1081,4 +1093,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (veza je prekinuta)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezivanje nije uspelo. Probajte ponovo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Upari novi uređaj"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index cedc375..e3831a8 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -1022,6 +1022,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Налады"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Акно павелічэння"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Налады акна павелічэння"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Элементы кіравання прыладай"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Дадайце элементы кіравання для падключаных прылад"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Наладзіць элементы кіравання прыладай"</string>
@@ -1087,4 +1099,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (адключана)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не ўдалося падключыцца. Паўтарыце спробу."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Спалучыць з новай прыладай"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 1408840..d959178 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Настройки"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Прозорец за ниво на мащаба"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Контроли за прозореца за ниво на мащаба"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Контроли за устройството"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Добавяне на контроли за свързаните ви устройства"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Настройване на контролите за устройството"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (връзката е прекратена)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Неуспешно свързване. Опитайте отново."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Сдвояване на ново устройство"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index aed9522..fffa555 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"সেটিংস"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"উইন্ডো বড় করে দেখা"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"উইন্ডো কন্ট্রোল বড় করে দেখা"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ডিভাইস কন্ট্রোল"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"আপনার কানেক্ট করা ডিভাইসের জন্য কন্ট্রোল যোগ করুন"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"ডিভাইস কন্ট্রোল সেট-আপ করুন"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (কানেক্ট করা নেই)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"কানেক্ট করা যায়নি। আবার চেষ্টা করুন।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"নতুন ডিভাইস পেয়ার করুন"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 41a2671..f5410cf 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -1017,6 +1017,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Postavke"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Prozor za uvećavanje"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za uvećavanje"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Kontrole uređaja"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Dodajte kontrole za povezane uređaje"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Postavite kontrole uređaja"</string>
@@ -1081,4 +1093,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (veza je prekinuta)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezivanje nije uspjelo. Pokušajte ponovo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uparite novi uređaj"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 0a03680..28bf3bb 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Configuració"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Finestra d\'ampliació"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Finestra de controls d\'ampliació"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Controls de dispositius"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Afegeix controls per als teus dispositius connectats"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Configura els controls de dispositius"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconnectat)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"No s\'ha pogut connectar. Torna-ho a provar."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincula un dispositiu nou"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 419e625..c66f200 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -1022,6 +1022,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Nastavení"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Zvětšovací okno"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ovládací prvky zvětšovacího okna"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Ovládání zařízení"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Přidejte ovládací prvky pro připojená zařízení"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Nastavení ovládání zařízení"</string>
@@ -1087,4 +1099,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (odpojeno)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Spojení se nezdařilo. Zkuste to znovu."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Spárovat nové zařízení"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index f2e8a3f..5b0566d 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Indstillinger"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vindue med forstørrelse"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Vindue med forstørrelsesstyring"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Enhedsstyring"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Tilføj styring af dine tilsluttede enheder"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Konfigurer enhedsstyring"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ingen forbindelse)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Der kunne ikke oprettes forbindelse. Prøv igen."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Par ny enhed"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 4dbd74a..0ab1f0e 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Einstellungen"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vergrößerungsfenster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Einstellungen für Vergrößerungsfenster"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Gerätesteuerung"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Steuerelemente für verbundene Geräte hinzufügen"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Gerätesteuerung einrichten"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (nicht verbunden)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Verbindung nicht möglich. Versuch es noch einmal."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Neues Gerät koppeln"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 1b912c7..6d86e91 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Ρυθμίσεις"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Παράθυρο μεγέθυνσης"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Στοιχεία ελέγχου παραθύρου μεγέθυνσης"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Στοιχεία ελέγχου συσκευής"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Προσθήκη στοιχείων ελέγχου για τις συνδεδεμένες συσκευές σας."</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Ρύθμιση στοιχείων ελέγχου συσκευής"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (αποσυνδέθηκε)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Δεν ήταν δυνατή η σύνδεση. Δοκιμάστε ξανά."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Σύζευξη νέας συσκευής"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 065c17b..cb03d40 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -1012,6 +1012,12 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Settings"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom in"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Zoom out"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Move up"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Device controls"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Add controls for your connected devices"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Set up device controls"</string>
@@ -1075,4 +1081,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnected)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Couldn\'t connect. Try again."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 1cc6625..8e5849e 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -1012,6 +1012,12 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Settings"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom in"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Zoom out"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Move up"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Device controls"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Add controls for your connected devices"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Set up device controls"</string>
@@ -1075,4 +1081,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnected)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Couldn\'t connect. Try again."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 065c17b..cb03d40 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -1012,6 +1012,12 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Settings"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom in"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Zoom out"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Move up"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Device controls"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Add controls for your connected devices"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Set up device controls"</string>
@@ -1075,4 +1081,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnected)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Couldn\'t connect. Try again."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 065c17b..cb03d40 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -1012,6 +1012,12 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Settings"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Magnification window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Magnification window controls"</string>
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom in"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Zoom out"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Move up"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Device controls"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Add controls for your connected devices"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Set up device controls"</string>
@@ -1075,4 +1081,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnected)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Couldn\'t connect. Try again."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 7702337..e107ed5 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -1012,6 +1012,12 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Settings"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Magnification Window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Magnification Window Controls"</string>
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Zoom in"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Zoom out"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Move up"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Move down"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Move left"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Move right"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Device controls"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Add controls for your connected devices"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Set up device controls"</string>
@@ -1075,4 +1081,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnected)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Couldn\'t connect. Try again."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 8a8f1e7..be37623 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Configuración"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ventana de ampliación"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controles de ampliación de la ventana"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Controles de dispositivos"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Agrega controles para los dispositivos conectados"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurar controles de dispositivos"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconectado)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"No se pudo establecer la conexión. Vuelve a intentarlo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular dispositivo nuevo"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 20b50ab..08b17cc 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Ajustes"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ventana de ampliación"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ventana de controles de ampliación"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Control de dispositivos"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Añade controles para tus dispositivos conectados"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurar control de dispositivos"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconectado)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"No se ha podido conectar. Inténtalo de nuevo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular nuevo dispositivo"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index ced0604..b33ad01 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Seaded"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Suurendamisaken"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Suurendamisakna juhtelemendid"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Seadmete juhikud"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Lisage juhtelemendid ühendatud seadmete jaoks"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Seadmete juhtimisvidinate seadistamine"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (pole ühendatud)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ühenduse loomine ebaõnnestus. Proovige uuesti."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uue seadme sidumine"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index e8d2f47..3f1a53c 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Ezarpenak"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Lupa-leihoa"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Lupa-leihoaren aukerak"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Gailuak kontrolatzeko widgetak"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Gehitu konektatutako gailuak kontrolatzeko widgetak"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Konfiguratu gailuak kontrolatzeko widgetak"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (deskonektatuta)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ezin izan da konektatu. Saiatu berriro."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parekatu beste gailu batekin"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index f6cf179..e5606a2 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -246,7 +246,7 @@
<string name="accessibility_remove_notification" msgid="1641455251495815527">"پاک کردن اعلان"</string>
<string name="accessibility_gps_enabled" msgid="4061313248217660858">"GPS فعال شد."</string>
<string name="accessibility_gps_acquiring" msgid="896207402196024040">"دستیابی به GPS."</string>
- <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter فعال شد."</string>
+ <string name="accessibility_tty_enabled" msgid="1123180388823381118">"تلهتایپ فعال شد."</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"زنگ لرزشی."</string>
<string name="accessibility_ringer_silent" msgid="8994620163934249882">"زنگ بیصدا."</string>
<!-- no translation found for accessibility_casting (8708751252897282313) -->
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"تنظیمات"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"پنجره بزرگنمایی"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"کنترلهای پنجره بزرگنمایی"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"کنترلهای دستگاه"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"افزودن کنترلها برای دستگاههای متصل"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"تنظیم کنترلهای دستگاه"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (اتصال قطع شد)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"متصل نشد. دوباره امتحان کنید."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"مرتبط کردن دستگاه جدید"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 3d9a6db..e00b50e 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Asetukset"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Suurennusikkuna"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Suurennusikkunan ohjaimet"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Laitteiden hallinta"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Lisää ohjaimia yhdistettyjä laitteita varten"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Laitteiden hallinnan käyttöönotto"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (yhteys katkaistu)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ei yhteyttä. Yritä uudelleen."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Muodosta uusi laitepari"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index ff89ce2..03e205d 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Paramètres"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Commandes pour la fenêtre d\'agrandissement"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Commandes des appareils"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Ajoutez des commandes pour vos appareils connectés"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurer les commandes des appareils"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (déconnecté)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Impossible de se connecter. Réessayez."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Associer un autre appareil"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index a126cfa..82df63a 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Paramètres"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Fenêtre des commandes d\'agrandissement"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Commandes des appareils"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Ajouter des commandes pour vos appareils connectés"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurer les commandes des appareils"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (déconnecté)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Impossible de se connecter. Réessayez."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Associer un nouvel appareil"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 9075a69..9be451d 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -246,7 +246,7 @@
<string name="accessibility_remove_notification" msgid="1641455251495815527">"Eliminar notificación."</string>
<string name="accessibility_gps_enabled" msgid="4061313248217660858">"GPS activado"</string>
<string name="accessibility_gps_acquiring" msgid="896207402196024040">"Obtendo GPS."</string>
- <string name="accessibility_tty_enabled" msgid="1123180388823381118">"TeleTypewriter activado"</string>
+ <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Teletipo activado"</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Timbre en vibración"</string>
<string name="accessibility_ringer_silent" msgid="8994620163934249882">"Timbre silenciado"</string>
<!-- no translation found for accessibility_casting (8708751252897282313) -->
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Configuración"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ventá de superposición"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controis de ampliación da ventá"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Control de dispositivos"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Engade controis para os dispositivos conectados"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurar o control de dispositivos"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (dispositivo desconectado)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Non se puido establecer a conexión. Téntao de novo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular dispositivo novo"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index e8b4460..864d05f 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"સેટિંગ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"વિસ્તૃતીકરણ વિંડો"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"વિસ્તૃતીકરણ વિંડોના નિયંત્રણો"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ડિવાઇસનાં નિયંત્રણો"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"તમારા કનેક્ટ કરેલા ડિવાઇસ માટે નિયંત્રણો ઉમેરો"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"ડિવાઇસનાં નિયંત્રણો સેટઅપ કરો"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ડિસ્કનેક્ટ થયેલું)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"કનેક્ટ કરી શકાયું નહીં. ફરી પ્રયાસ કરો."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"નવા ડિવાઇસ સાથે જોડાણ કરો"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 9a563d9..e11055c 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -1014,6 +1014,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"सेटिंग"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"स्क्रीन को बड़ा करके दिखाने वाली विंडो"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"स्क्रीन को बड़ा करके दिखाने वाली विंडो के नियंत्रण"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"डिवाइस कंट्रोल"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"कनेक्ट किए गए डिवाइस के लिए कंट्रोल जोड़ें"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"डिवाइस कंट्रोल सेट अप करें"</string>
@@ -1077,4 +1089,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (डिसकनेक्ट किया गया)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"कनेक्ट नहीं किया जा सका. फिर से कोशिश करें."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नया डिवाइस जोड़ें"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 649299b1c..d5033fa 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -1017,6 +1017,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Postavke"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Prozor za povećavanje"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrole prozora za povećavanje"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Kontrole uređaja"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Dodavanje kontrola za povezane uređaje"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Postavljanje kontrola uređaja"</string>
@@ -1081,4 +1093,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (nije povezano)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezivanje nije bilo moguće. Pokušajte ponovo."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Upari novi uređaj"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index f658bb7..6d960e7 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Beállítások"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Nagyítás ablaka"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Nagyítási vezérlők ablaka"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Eszközvezérlők"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Vezérlők hozzáadása a csatlakoztatott eszközökhöz"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Eszközvezérlők beállítása"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (leválasztva)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Sikertelen csatlakozás. Próbálja újra."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Új eszköz párosítása"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 171773c..9e746fa 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -246,7 +246,7 @@
<string name="accessibility_remove_notification" msgid="1641455251495815527">"Մաքրել ծանուցումը:"</string>
<string name="accessibility_gps_enabled" msgid="4061313248217660858">"GPS-ը միացված է:"</string>
<string name="accessibility_gps_acquiring" msgid="896207402196024040">"GPS-ի ստացում:"</string>
- <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Հեռամուտքագրիչը միացված է:"</string>
+ <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Հեռատիպը միացված է:"</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Թրթռազանգ:"</string>
<string name="accessibility_ringer_silent" msgid="8994620163934249882">"Զանգակը լռեցված է:"</string>
<!-- no translation found for accessibility_casting (8708751252897282313) -->
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Կարգավորումներ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Խոշորացման պատուհան"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Խոշորացման պատուհանի կառավարման տարրեր"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Սարքերի կառավարման տարրեր"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Ավելացրեք կառավարման տարրեր ձեր միացված սարքերի համար"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Սարքերի կառավարման տարրերի կարգավորում"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (անջատված է)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Չհաջողվեց միանալ։ Նորից փորձեք։"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Նոր սարքի զուգակցում"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 12f42e8..380e943 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -597,7 +597,7 @@
<string name="screen_pinning_description_accessible" msgid="7386449191953535332">"Ini akan terus ditampilkan sampai Anda melepas pin. Sentuh lama tombol Ringkasan untuk melepas pin."</string>
<string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"Ini akan terus ditampilkan sampai Anda melepas pin. Sentuh lama tombol Beranda untuk melepas pin."</string>
<string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"Data pribadi dapat diakses (seperti kontak dan konten email)."</string>
- <string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Aplikasi yang dipasangi pin dapat membuka aplikasi lain."</string>
+ <string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"Aplikasi yang disematkan dapat membuka aplikasi lain."</string>
<string name="screen_pinning_toast" msgid="8177286912533744328">"Untuk melepas pin aplikasi ini, sentuh & lama tombol Kembali dan Ringkasan"</string>
<string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"Untuk melepas pin aplikasi ini, sentuh & lama tombol Kembali dan Layar utama"</string>
<string name="screen_pinning_toast_gesture_nav" msgid="170699893395336705">"Untuk melepas pin aplikasi ini, geser ke atas & tahan"</string>
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Setelan"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Jendela Pembesaran"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrol Jendela Pembesaran"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Kontrol perangkat"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Tambahkan kontrol untuk perangkat terhubung"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Siapkan kontrol perangkat"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (terputus)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Tidak dapat terhubung. Coba lagi."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sambungkan perangkat baru"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 4a750a5..dd12ed6 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Stillingar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Stækkunargluggi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Stækkunarstillingar glugga"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Tækjastjórnun"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Bæta við stýringum fyrir tengd tæki"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Setja upp tækjastjórnun"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (aftengt)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Tenging mistókst. Reyndu aftur."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Para nýtt tæki"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index eb76a4b..851228f 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Impostazioni"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Finestra ingrandimento"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Finestra controlli di ingrandimento"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Controllo dei dispositivi"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Aggiungi controlli per i dispositivi connessi"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Configura il controllo dei dispositivi"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (disconnesso)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Impossibile connettersi. Riprova."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Accoppia nuovo dispositivo"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index e6fbdb5..d4ad45e 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -1022,6 +1022,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"הגדרות"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"חלון הגדלה"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"בקרות של חלון ההגדלה"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"פקדי מכשירים"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"יש להוסיף פקדים למכשירים המחוברים"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"הגדרה של פקדי מכשירים"</string>
@@ -1087,4 +1099,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (מנותק)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"לא ניתן היה להתחבר. יש לנסות שוב."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"התאמה של מכשיר חדש"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b358f3d..7547853 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"設定"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"拡大ウィンドウ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"拡大ウィンドウ コントロール"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"デバイス コントロール"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"接続済みデバイスのコントロールを追加します"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"デバイス コントロールの設定"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>(未接続)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"接続できませんでした。もう一度お試しください。"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"新しいデバイスとのペア設定"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 4e85d60..69b1d14 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"პარამეტრები"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"გადიდების ფანჯარა"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"გადიდების კონტროლის ფანჯარა"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"მოწყობილ. მართვის საშუალებები"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"მართვის საშუალებების დამატება თქვენს დაკავშირებულ მოწყობილობებზე"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"მოწყობილობის მართვის საშუალებების დაყენება"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (კავშირი გაწყვეტილია)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"დაკავშირება ვერ მოხერხდა. ცადეთ ხელახლა."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ახალი მოწყობილობის დაწყვილება"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index f172106..b86f32e 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Параметрлер"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ұлғайту терезесі"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ұлғайту терезесінің басқару элементтері"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Құрылғыны басқару элементтері"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Жалғанған құрылғылар үшін басқару виджеттерін қосу"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Құрылғыны басқару элементтерін реттеу"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ажыратылған)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Қосылмады. Қайта қосылып көріңіз."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Жаңа құрылғыны жұптау"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index b126a11..e895140 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ការកំណត់"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"វិនដូការពង្រីក"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"វិនដូគ្រប់គ្រងការពង្រីក"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ផ្ទាំងគ្រប់គ្រងឧបករណ៍"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"បញ្ចូលផ្ទាំងគ្រប់គ្រងសម្រាប់ឧបករណ៍ដែលអ្នកបានភ្ជាប់"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"រៀបចំផ្ទាំងគ្រប់គ្រងឧបករណ៍"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (បានផ្ដាច់)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"មិនអាចភ្ជាប់បានទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ផ្គូផ្គងឧបករណ៍ថ្មី"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 475677b..2a9f649 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ವರ್ಧನೆಯ ವಿಂಡೋ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ವರ್ಧನೆಯ ವಿಂಡೋ ನಿಯಂತ್ರಣಗಳು"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ಸಾಧನ ನಿಯಂತ್ರಣಗಳು"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"ನಿಮ್ಮ ಸಂಪರ್ಕಿತ ಸಾಧನಗಳಿಗೆ ನಿಯಂತ್ರಣಗಳನ್ನು ಸೇರಿಸಿ"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"ಸಾಧನ ನಿಯಂತ್ರಣಗಳನ್ನು ಸೆಟಪ್ ಮಾಡಿ"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ಹೊಸ ಸಾಧನವನ್ನು ಜೋಡಿಸಿ"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index ac7f04e..559205c 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"설정"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"확대 창"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"확대 창 컨트롤"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"기기 컨트롤"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"연결된 기기의 컨트롤을 추가하세요."</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"기기 컨트롤 설정"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>(연결 끊김)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"연결할 수 없습니다. 다시 시도하세요."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"새 기기와 페어링"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index b1fab07..a688150 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Жөндөөлөр"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Чоңойтуу терезеси"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Чоңойтуу терезесин башкаруу каражаттары"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Түзмөктү башкаруу элементтери"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Байланышкан түзмөктөрүңүздү башкаруу элементтерин кошосуз"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Түзмөктү башкаруу элементтерин жөндөө"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ажыратылды)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Байланышпай койду. Кайталоо."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Жаңы түзмөктү жупташтыруу"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 67642d3..1a6c338 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ການຕັ້ງຄ່າ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ໜ້າຈໍການຂະຫຍາຍ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ການຄວບຄຸມໜ້າຈໍການຂະຫຍາຍ"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ການຄວບຄຸມອຸປະກອນ"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"ເພີ່ມການຄວບຄຸມສຳລັບອຸປະກອນທີ່ເຊື່ອມຕໍ່ແລ້ວຂອງທ່ານ"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"ຕັ້ງຄ່າການຄວບຄຸມອຸປະກອນ"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ຕັດການເຊື່ອມຕໍ່ແລ້ວ)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ບໍ່ສາມາດເຊື່ອມຕໍ່ໄດ້. ລອງໃໝ່."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ຈັບຄູ່ອຸປະກອນໃໝ່"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index e17f6e4..6fb84dd8 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -1022,6 +1022,12 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Nustatymai"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Didinimo langas"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Didinimo lango valdikliai"</string>
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Artinti"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Tolinti"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Perkelti aukštyn"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Perkelti žemyn"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Perkelti kairėn"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Perkelti dešinėn"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Įrenginio valdikliai"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Pridėkite prijungtų įrenginių valdiklių"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Įrenginio valdiklių nustatymas"</string>
@@ -1087,4 +1093,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"„<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“ (atjungta)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nepavyko prijungti. Bandykite dar kartą."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Naujo įrenginio susiejimas"</string>
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijos numeris"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Versijos numeris nukopijuotas į iškarpinę."</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 96d563c..9864a61 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -1017,6 +1017,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Iestatījumi"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Palielināšanas logs"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Palielināšanas loga vadīklas"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Ierīču vadīklas"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Pievienojiet vadīklas pievienotajām ierīcēm"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Ierīču vadīklu iestatīšana"</string>
@@ -1081,4 +1093,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (savienojums pārtraukts)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nevarēja izveidot savienojumu. Mēģiniet vēlreiz."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Savienošana pārī ar jaunu ierīci"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index f53147e..362cbdc 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Поставки"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Прозорец за зголемување"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Контроли на прозорец за зголемување"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Контроли за уредите"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Додајте контроли за поврзаните уреди"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Поставете ги контролите за уредите"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (исклучен)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не можеше да се поврзе. Обидете се повторно."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Спарете нов уред"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 80f0106..95634b8 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ക്രമീകരണം"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"മാഗ്നിഫിക്കേഷൻ വിൻഡോ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"മാഗ്നിഫിക്കേഷൻ വിൻഡോ നിയന്ത്രണങ്ങൾ"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ഉപകരണ നിയന്ത്രണങ്ങൾ"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"കണക്റ്റ് ചെയ്ത ഉപകരണങ്ങൾക്ക് നിയന്ത്രണങ്ങൾ ചേർക്കുക"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"ഉപകരണ നിയന്ത്രണങ്ങൾ സജ്ജീകരിക്കുക"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (വിച്ഛേദിച്ചു)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"കണക്റ്റ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"പുതിയ ഉപകരണവുമായി ജോടിയാക്കുക"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 1c82e48..a2e1745 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Тохиргоо"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Томруулалтын цонх"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Томруулалтын цонхны хяналт"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Төхөөрөмжийн хяналт"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Холбогдсон төхөөрөмжүүд дээрээ хяналт нэмэх"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Төхөөрөмжийн хяналтыг тохируулах"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (салсан)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Холбогдож чадсангүй. Дахин оролдоно уу."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Шинэ төхөөрөмж хослуулах"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index b26f89f..7a62c17 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"सेटिंग्ज"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"मॅग्निफिकेशन विंडो"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"मॅग्निफिकेशन विंडो नियंत्रणे"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"डिव्हाइस नियंत्रणे"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"तुमच्या कनेक्ट केलेल्या डिव्हाइससाठी नियंत्रणे जोडा"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"डिव्हाइस नियंत्रणे सेट करा"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (डिस्कनेक्ट केले)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"कनेक्ट करू शकलो नाही. पुन्हा प्रयत्न करा."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नवीन डिव्हाइससोबत पेअर करा"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 92bc807..2b501bb 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Tetapan"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Tetingkap Pembesaran"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kawalan Tetingkap Pembesaran"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Kawalan peranti"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Tambah kawalan untuk peranti yang disambungkan"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Sediakan kawalan peranti"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (diputuskan sambungan)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Tidak boleh menyambung. Cuba lagi."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Gandingkan peranti baharu"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 9cc9398..1cbf17fe 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ဆက်တင်များ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ဝင်းဒိုး ချဲ့ခြင်း"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ဝင်းဒိုး ထိန်းချုပ်မှုများ ချဲ့ခြင်း"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"စက်ထိန်းစနစ်"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"ချိတ်ဆက်စက်များအတွက် ထိန်းချုပ်မှုများထည့်ပါ"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"စက်ထိန်းစနစ် ထည့်သွင်းခြင်း"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ချိတ်ဆက်မထားပါ)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ချိတ်ဆက်၍ မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"စက်အသစ် တွဲချိတ်ရန်"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 92ae689..6d6d66f 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Innstillinger"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Forstørringsvindu"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontroller for forstørringsvindu"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Enhetsstyring"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Legg til kontroller for de tilkoblede enhetene dine"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Konfigurer enhetsstyring"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (frakoblet)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Kunne ikke koble til. Prøv på nytt."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Koble til en ny enhet"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 1346874..e1dd8c0 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"सेटिङ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"म्याग्निफिकेसन विन्डो"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"म्याग्निफिकेसन विन्डोका नियन्त्रणहरू"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"यन्त्र नियन्त्रण गर्ने विजेटहरू"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"आफ्ना जोडिएका यन्त्रहरूका लागि नियन्त्रण सुविधाहरू थप्नुहोस्"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"यन्त्र नियन्त्रण गर्ने विजेटहरू सेटअप गर्नुहोस्"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (डिस्कनेक्ट गरिएको)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"कनेक्ट गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नयाँ यन्त्रको जोडा बनाउनुहोस्"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 139b57b..e2db22c 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Instellingen"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Vergrotingsvenster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Bediening van vergrotingsvenster"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Apparaatbediening"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Bedieningselementen voor je gekoppelde apparaten toevoegen"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Apparaatbediening instellen"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (verbinding verbroken)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Kan geen verbinding maken. Probeer het nog eens."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Nieuw apparaat koppelen"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 3973734..970e61c 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ସେଟିଂସ୍"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ମ୍ୟାଗ୍ନିଫିକେସନ୍ ୱିଣ୍ଡୋ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ଡିଭାଇସ୍ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"ଆପଣଙ୍କ ସଂଯୁକ୍ତ ଡିଭାଇସଗୁଡ଼ିକ ପାଇଁ ନିୟନ୍ତ୍ରଣ ଯୋଗ କରନ୍ତୁ"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"ଡିଭାଇସ୍ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ସେଟ୍ ଅପ୍ କରନ୍ତୁ"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ବିଚ୍ଛିନ୍ନ କରାଯାଇଛି)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ସଂଯୋଗ କରାଯାଇପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ନୂଆ ଡିଭାଇସକୁ ପେୟାର୍ କରନ୍ତୁ"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index e727f48a..690d6e5b 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ਸੈਟਿੰਗਾਂ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ਵੱਡਦਰਸ਼ੀਕਰਨ Window"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ਵੱਡਦਰਸ਼ੀਕਰਨ Window ਦੇ ਕੰਟਰੋਲ"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ਡੀਵਾਈਸ ਕੰਟਰੋਲ"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"ਆਪਣੇ ਕਨੈਕਟ ਕੀਤੇ ਡੀਵਾਈਸਾਂ ਲਈ ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"ਡੀਵਾਈਸ ਕੰਟਰੋਲਾਂ ਦਾ ਸੈੱਟਅੱਪ ਕਰੋ"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ਡਿਸਕਨੈਕਟ ਹੋਇਆ)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ਨਵਾਂ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index f188aaa..9b31c52 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -1022,6 +1022,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Ustawienia"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Okno powiększenia"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Elementy sterujące okna powiększenia"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Sterowanie urządzeniami"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Dodaj elementy sterujące połączonymi urządzeniami"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Konfigurowanie sterowania urządzeniami"</string>
@@ -1087,4 +1099,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (rozłączono)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nie udało się połączyć. Spróbuj ponownie."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sparuj nowe urządzenie"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 8c8adae..b76ebda 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -1012,6 +1012,12 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Configurações"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Janela de ampliação"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controles da janela de ampliação"</string>
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Aumentar zoom"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Diminuir zoom"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Mover para cima"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Mover para baixo"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Mover para a esquerda"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Mover para a direita"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Controles do dispositivo"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Adiciona controles aos dispositivos conectados"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurar controles do dispositivo"</string>
@@ -1075,4 +1081,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconectado)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Não foi possível conectar. Tente novamente."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parear novo dispositivo"</string>
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Número da versão copiado para a área de transferência."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 082e14e..089bbd4 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Definições"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Janela de ampliação"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controlos da janela de ampliação"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Controlos de dispositivos"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Adicione controlos para os dispositivos associados."</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Configure os controlos de dispositivos"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desligado)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Não foi possível ligar. Tente novamente."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sincronize o novo dispositivo"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 8c8adae..b76ebda 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -1012,6 +1012,12 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Configurações"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Janela de ampliação"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controles da janela de ampliação"</string>
+ <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Aumentar zoom"</string>
+ <string name="accessibility_control_zoom_out" msgid="69578832020304084">"Diminuir zoom"</string>
+ <string name="accessibility_control_move_up" msgid="6622825494014720136">"Mover para cima"</string>
+ <string name="accessibility_control_move_down" msgid="5390922476900974512">"Mover para baixo"</string>
+ <string name="accessibility_control_move_left" msgid="8156206978511401995">"Mover para a esquerda"</string>
+ <string name="accessibility_control_move_right" msgid="8926821093629582888">"Mover para a direita"</string>
<string name="quick_controls_title" msgid="6839108006171302273">"Controles do dispositivo"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Adiciona controles aos dispositivos conectados"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurar controles do dispositivo"</string>
@@ -1075,4 +1081,6 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (desconectado)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Não foi possível conectar. Tente novamente."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parear novo dispositivo"</string>
+ <string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
+ <string name="build_number_copy_toast" msgid="877720921605503046">"Número da versão copiado para a área de transferência."</string>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 4128c21..3194b9f 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -1017,6 +1017,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Setări"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fereastra de mărire"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Comenzi pentru fereastra de mărire"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Comenzile dispozitivelor"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Adăugați comenzi pentru dispozitivele conectate"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurați comenzile dispozitivelor"</string>
@@ -1081,4 +1093,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (s-a deconectat)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nu s-a putut conecta. Reîncercați."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Asociați un nou dispozitiv"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 7584173..26e3433 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -1022,6 +1022,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Настройки"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Окно увеличения"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Настройки окна увеличения"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Управление устройствами"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Добавьте виджеты для управления устройствами."</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Настройте виджеты управления устройствами"</string>
@@ -1087,4 +1099,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (отключено)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не удалось подключиться. Повторите попытку."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Подключить новое устройство"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 98e8d1f..8eea1ed 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"සැකසීම්"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"විශාලන කවුළුව"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"විශාලනය කිරීමේ කවුළු පාලන"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"උපාංග පාලන"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"ඔබේ සම්බන්ධිත උපාංග සඳහා පාලන එක් කරන්න"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"උපාංග පාලන පිහිටුවන්න"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (විසන්ධි විය)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"සම්බන්ධ වීමට නොහැකි විය. නැවත උත්සාහ කරන්න."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"නව උපාංගය යුගල කරන්න"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index d9c6279..47045d8 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -1022,6 +1022,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Nastavenia"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Okno priblíženia"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Ovládacie prvky okna priblíženia"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Ovládanie zariadení"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Pridajte si ovládače pripojených zariadení"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Nastavenie ovládania zariadení"</string>
@@ -1087,4 +1099,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (odpojené)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nepodarilo sa pripojiť. Skúste to znova."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Spárovať nové zariadenie"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 778938c..7b68a3a 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -1022,6 +1022,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Nastavitve"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Povečevalno okno"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrolniki povečevalnega okna"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Kontrolniki naprave"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Dodajte kontrolnike za povezane naprave"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Nastavitev kontrolnikov naprave"</string>
@@ -1087,4 +1099,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (povezava prekinjena)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Povezave ni bilo mogoče vzpostaviti. Poskusite znova."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Seznanitev nove naprave"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 5172303..b7ebb2a 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -246,7 +246,7 @@
<string name="accessibility_remove_notification" msgid="1641455251495815527">"Pastro njoftimin."</string>
<string name="accessibility_gps_enabled" msgid="4061313248217660858">"GPS-ja është e aktivizuar."</string>
<string name="accessibility_gps_acquiring" msgid="896207402196024040">"Po siguron GPS-në."</string>
- <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Teleprinteri është i aktivizuar."</string>
+ <string name="accessibility_tty_enabled" msgid="1123180388823381118">"Teletajpi është i aktivizuar."</string>
<string name="accessibility_ringer_vibrate" msgid="6261841170896561364">"Zile me dridhje."</string>
<string name="accessibility_ringer_silent" msgid="8994620163934249882">"Zilja është heshtur."</string>
<!-- no translation found for accessibility_casting (8708751252897282313) -->
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Cilësimet"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Dritarja e zmadhimit"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kontrollet e dritares së zmadhimit"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Kontrollet e pajisjes"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Shto kontrolle për pajisjet e tua të lidhura"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Konfiguro kontrollet e pajisjes"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (e shkëputur)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Nuk mund të lidhej. Provo sërish."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Çifto pajisjen e re"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 90f1c5a..b6a90cd 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -1017,6 +1017,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Подешавања"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Прозор за увећање"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Контроле прозора за увећање"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Контроле уређаја"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Додајте контроле за повезане уређаје"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Подесите контроле уређаја"</string>
@@ -1081,4 +1093,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (веза је прекинута)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Повезивање није успело. Пробајте поново."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Упари нови уређај"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 8918f51..890f504 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Inställningar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Förstoringsfönster"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Inställningar för förstoringsfönster"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Enhetsstyrning"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Lägg till snabbkontroller för anslutna enheter"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Konfigurera enhetsstyrning"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (frånkopplad)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Det gick inte att ansluta. Försök igen."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parkoppla en ny enhet"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 3949f2df..34042ad 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Mipangilio"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Dirisha la Ukuzaji"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Vidhibiti vya Dirisha la Ukuzaji"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Vidhibiti vya vifaa"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Weka vidhibiti vya vifaa ulivyounganisha"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Weka mipangilio ya vidhibiti vya vifaa"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (hakijaunganishwa)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Imeshindwa kuunganisha. Jaribu tena."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Oanisha kifaa kipya"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index d91f1fd..b30859f 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -879,12 +879,12 @@
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"குறைந்த முன்னுரிமை உள்ள அறிவிப்பு ஐகான்களைக் காட்டு"</string>
<string name="other" msgid="429768510980739978">"மற்றவை"</string>
- <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"டைலை அகற்றும்"</string>
- <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"கடைசியில் டைலைச் சேர்க்கும்"</string>
- <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"டைலை நகர்த்து"</string>
- <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"டைலைச் சேர்"</string>
- <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> இடத்திற்கு நகர்த்தும்"</string>
- <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> என்ற இடத்தில் சேர்க்கும்"</string>
+ <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"கட்டத்தை அகற்றும்"</string>
+ <string name="accessibility_qs_edit_tile_add_action" msgid="5051211910345301833">"கடைசியில் கட்டத்தைச் சேர்க்கும்"</string>
+ <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"கட்டத்தை நகர்த்து"</string>
+ <string name="accessibility_qs_edit_tile_start_add" msgid="7560798153975555772">"கட்டத்தைச் சேர்"</string>
+ <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g>க்கு நகர்த்தும்"</string>
+ <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g>ல் சேர்க்கும்"</string>
<string name="accessibility_qs_edit_position" msgid="4509277359815711830">"இடம்: <xliff:g id="POSITION">%1$d</xliff:g>"</string>
<string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"விரைவு அமைப்புகள் திருத்தி."</string>
<string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> அறிவிப்பு: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"அமைப்புகள்"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"பெரிதாக்கல் சாளரம்"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"பெரிதாக்கல் சாளரக் கட்டுப்பாடுகள்"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"சாதனக் கட்டுப்பாடுகள்"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"இணைக்கப்பட்ட சாதனங்களில் கட்டுப்பாடுகளைச் சேர்க்கலாம்"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"சாதனக் கட்டுப்பாடுகளை அமைத்தல்"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (இணைப்பு துண்டிக்கப்பட்டது)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"இணைக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"புதிய சாதனத்தை இணைத்தல்"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index d7a27b8..cb134a1 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"సెట్టింగ్లు"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"మాగ్నిఫికేషన్ విండో"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"మాగ్నిఫికేషన్ నియంత్రణల విండో"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"పరికరం నియంత్రణలు"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"మీ కనెక్ట్ అయిన పరికరాలకు నియంత్రణలను జోడించండి"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"పరికరం నియంత్రణలను సెటప్ చేయడం"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (డిస్కనెక్ట్ అయ్యింది)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"కనెక్ట్ చేయడం సాధ్యపడలేదు. మళ్లీ ట్రై చేయండి."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"కొత్త పరికరాన్ని పెయిర్ చేయండి"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index cb6089f..d678353 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"การตั้งค่า"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"หน้าต่างการขยาย"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"การควบคุมหน้าต่างการขยาย"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"ระบบควบคุมอุปกรณ์"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"เพิ่มตัวควบคุมของอุปกรณ์ที่เชื่อมต่อ"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"ตั้งค่าระบบควบคุมอุปกรณ์"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (ยกเลิกการเชื่อมต่อแล้ว)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"เชื่อมต่อไม่ได้ ลองใหม่"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"จับคู่อุปกรณ์ใหม่"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 7e6aa62..21fdd31 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Mga Setting"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Window ng Pag-magnify"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Mga Kontrol sa Pag-magnify ng Window"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Mga kontrol ng device"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Magdagdag ng kontrol para sa mga nakakonektang device"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"I-set up ang mga kontrol ng device"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (nakadiskonekta)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Hindi makakonekta. Subukan ulit."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Magpares ng bagong device"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index dac352f..3e04d19 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Ayarlar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Büyütme Penceresi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Büyütme Penceresi Kontrolleri"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Cihaz denetimleri"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Bağlı cihazlarınız için denetimler ekleyin"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Cihaz denetimlerini kur"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (bağlı değil)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Bağlanılamadı. Tekrar deneyin."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yeni cihaz eşle"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 26053af..a7c6bef 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -1022,6 +1022,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Налаштування"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Вікно збільшення"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Елементи керування вікна збільшення"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Керування пристроями"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Додайте елементи керування для підключених пристроїв"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Налаштувати елементи керування пристроями"</string>
@@ -1087,4 +1099,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (відключено)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Не вдалося підключитися. Повторіть спробу."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Підключити новий пристрій"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 4bd192fd..f24492c 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ترتیبات"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"میگنیفکیشن ونڈو"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"میگنیفکیشن ونڈو کنٹرولز"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"آلہ کے کنٹرولز"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"اپنے منسلک آلات کے لیے کنٹرولز شامل کریں"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"آلہ کے کنٹرولز سیٹ اپ کریں"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (غیر منسلک ہو گیا)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"منسلک نہیں ہو سکا۔ پھر کوشش کریں۔"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"نئے آلہ کا جوڑا بنائیں"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 7c3728a..32c2406 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Sozlamalar"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Kattalashtirish oynasi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Kattalashtirish oynasi sozlamalari"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Qurilmalarni boshqarish"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Ulangan qurilmalar uchun boshqaruv elementlari"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Qurilma boshqaruv elementlarini sozlash"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (uzilgan)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ulanmadi. Qayta urining."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yangi qurilmani ulash"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index f23f742..d9c80df 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Cài đặt"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Cửa sổ phóng to"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Các tùy chọn điều khiển cửa sổ phóng to"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Điều khiển thiết bị"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Thêm các tùy chọn điều khiển cho các thiết bị đã kết nối của bạn"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Thiết lập các tùy chọn điều khiển thiết bị"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (đã ngắt kết nối)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Không thể kết nối. Hãy thử lại."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Ghép nối thiết bị mới"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 9b81cb0..9f9424d 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"设置"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"放大窗口"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"放大窗口控件"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"设备控制器"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"为您所连接的设备添加控件"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"设置设备控件"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>(已断开连接)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"无法连接。请重试。"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"与新设备配对"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index dbb9e03..2825a9e 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"設定"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"放大視窗"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"放大視窗控制項"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"裝置控制"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"為連接的裝置新增控制選項"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"設定裝置控制"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (已中斷連線)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"無法連線,請再試一次。"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"配對新裝置"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 4e4db70..8acf2c6 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"設定"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"放大視窗"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"放大視窗控制項"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"裝置控制"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"新增已連結裝置的控制項"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"設定裝置控制"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (已中斷連線)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"無法連線,請再試一次。"</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"配對新裝置"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 65e9a1c..4935206 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -1012,6 +1012,18 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Amasethingi"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Iwindi Lesikhulisi"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Izilawuli Zewindi Lesikhulisi"</string>
+ <!-- no translation found for accessibility_control_zoom_in (1189272315480097417) -->
+ <skip />
+ <!-- no translation found for accessibility_control_zoom_out (69578832020304084) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_up (6622825494014720136) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_down (5390922476900974512) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_left (8156206978511401995) -->
+ <skip />
+ <!-- no translation found for accessibility_control_move_right (8926821093629582888) -->
+ <skip />
<string name="quick_controls_title" msgid="6839108006171302273">"Izilawuli zezinsiza"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Engeza izilawuli zedivayisi yakho exhunyiwe"</string>
<string name="quick_controls_setup_title" msgid="8901436655997849822">"Setha izilawuli zezinsiza"</string>
@@ -1075,4 +1087,8 @@
<string name="media_output_dialog_disconnected" msgid="1834473104836986046">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> (inqamukile)"</string>
<string name="media_output_dialog_connect_failed" msgid="3225190634236259010">"Ayikwazanga ukuxhumeka. Zama futhi."</string>
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Bhanqa idivayisi entsha"</string>
+ <!-- no translation found for build_number_clip_data_label (3623176728412560914) -->
+ <skip />
+ <!-- no translation found for build_number_copy_toast (877720921605503046) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index ee05c6c..a98f666 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -34,7 +34,6 @@
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.AppGlobals;
-import android.app.IAssistDataReceiver;
import android.app.WindowConfiguration;
import android.content.ContentResolver;
import android.content.Context;
@@ -43,7 +42,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
-import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
@@ -228,21 +226,10 @@
/**
* Starts the recents activity. The caller should manage the thread on which this is called.
*/
- public void startRecentsActivity(Intent intent, final AssistDataReceiver assistDataReceiver,
+ public void startRecentsActivity(Intent intent, long eventTime,
final RecentsAnimationListener animationHandler, final Consumer<Boolean> resultCallback,
Handler resultCallbackHandler) {
try {
- IAssistDataReceiver receiver = null;
- if (assistDataReceiver != null) {
- receiver = new IAssistDataReceiver.Stub() {
- public void onHandleAssistData(Bundle resultData) {
- assistDataReceiver.onHandleAssistData(resultData);
- }
- public void onHandleAssistScreenshot(Bitmap screenshot) {
- assistDataReceiver.onHandleAssistScreenshot(screenshot);
- }
- };
- }
IRecentsAnimationRunner runner = null;
if (animationHandler != null) {
runner = new IRecentsAnimationRunner.Stub() {
@@ -272,7 +259,7 @@
}
};
}
- ActivityTaskManager.getService().startRecentsActivity(intent, receiver, runner);
+ ActivityTaskManager.getService().startRecentsActivity(intent, eventTime, runner);
if (resultCallback != null) {
resultCallbackHandler.post(new Runnable() {
@Override
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index aed7c21..a1c1f93 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -16,6 +16,7 @@
package com.android.systemui.shared.system;
+import android.app.PictureInPictureParams;
import android.app.WindowConfiguration;
import android.graphics.Point;
import android.graphics.Rect;
@@ -49,6 +50,7 @@
public final Rect screenSpaceBounds;
public final boolean isNotInRecents;
public final Rect contentInsets;
+ public final PictureInPictureParams pictureInPictureParams;
private final SurfaceControl mStartLeash;
@@ -66,6 +68,7 @@
isNotInRecents = app.isNotInRecents;
contentInsets = app.contentInsets;
activityType = app.windowConfiguration.getActivityType();
+ pictureInPictureParams = app.pictureInPictureParams;
mStartLeash = app.startLeash;
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index e5f2ad5..5122f6c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -27,6 +27,7 @@
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
+import android.view.InsetsState;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -81,12 +82,25 @@
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
public static final int WINDOWING_MODE_FREEFORM = WindowConfiguration.WINDOWING_MODE_FREEFORM;
+ public static final int ITYPE_EXTRA_NAVIGATION_BAR = InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
+
private static final WindowManagerWrapper sInstance = new WindowManagerWrapper();
public static WindowManagerWrapper getInstance() {
return sInstance;
}
+
+ /**
+ * Sets {@param providesInsetsTypes} as the inset types provided by {@param params}.
+ * @param params The window layout params.
+ * @param providesInsetsTypes The inset types we would like this layout params to provide.
+ */
+ public void setProvidesInsetsTypes(WindowManager.LayoutParams params,
+ int[] providesInsetsTypes) {
+ params.providesInsetsTypes = providesInsetsTypes;
+ }
+
/**
* @return the stable insets for the primary display.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
index 911bf9e..a705ec7 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
@@ -37,6 +37,7 @@
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.statusbar.CommandQueue;
import javax.inject.Inject;
@@ -66,7 +67,8 @@
@Inject
public WindowMagnification(Context context, @Main Handler mainHandler,
- CommandQueue commandQueue, ModeSwitchesController modeSwitchesController) {
+ CommandQueue commandQueue, ModeSwitchesController modeSwitchesController,
+ NavigationModeController navigationModeController) {
super(context);
mHandler = mainHandler;
mLastConfiguration = new Configuration(context.getResources().getConfiguration());
@@ -77,6 +79,9 @@
final WindowMagnificationController controller = new WindowMagnificationController(mContext,
mHandler, new SfVsyncFrameCallbackProvider(), null,
new SurfaceControl.Transaction(), this);
+ final int navBarMode = navigationModeController.addListener(
+ controller::onNavigationModeChanged);
+ controller.onNavigationModeChanged(navBarMode);
mWindowMagnificationAnimationController = new WindowMagnificationAnimationController(
mContext, controller);
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index 3832ff30..c3474bb 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -17,6 +17,8 @@
package com.android.systemui.accessibility;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -117,6 +119,9 @@
// The boundary of magnification frame.
private final Rect mMagnificationFrameBoundary = new Rect();
+ private int mNavBarMode;
+ private int mNavGestureHeight;
+
private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
private Choreographer.FrameCallback mMirrorViewGeometryVsyncCallback;
private Locale mLocale;
@@ -195,6 +200,19 @@
R.dimen.magnification_drag_view_size);
mOuterBorderSize = mResources.getDimensionPixelSize(
R.dimen.magnification_outer_border_margin);
+ updateNavigationBarDimensions();
+ }
+
+ private void updateNavigationBarDimensions() {
+ if (!supportsSwipeUpGesture()) {
+ mNavGestureHeight = 0;
+ return;
+ }
+ mNavGestureHeight = (mDisplaySize.x > mDisplaySize.y)
+ ? mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_height_landscape)
+ : mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_gesture_height);
}
/**
@@ -239,6 +257,13 @@
}
}
+ /** Handles MirrorWindow position when the navigation bar mode changed. */
+ public void onNavigationModeChanged(int mode) {
+ mNavBarMode = mode;
+ updateNavigationBarDimensions();
+ updateMirrorViewLayout();
+ }
+
/** Handles MirrorWindow position when the device rotation changed. */
private void onRotate() {
final Display display = mContext.getDisplay();
@@ -246,6 +271,7 @@
display.getRealSize(mDisplaySize);
setMagnificationFrameBoundary();
mRotation = display.getRotation();
+ updateNavigationBarDimensions();
if (!isWindowVisible()) {
return;
@@ -401,15 +427,23 @@
* moved close to the screen edges.
*/
private void updateMirrorViewLayout() {
+ if (!isWindowVisible()) {
+ return;
+ }
+ final int maxMirrorViewX = mDisplaySize.x - mMirrorView.getWidth();
+ final int maxMirrorViewY = mDisplaySize.y - mMirrorView.getHeight() - mNavGestureHeight;
WindowManager.LayoutParams params =
(WindowManager.LayoutParams) mMirrorView.getLayoutParams();
params.x = mMagnificationFrame.left - mMirrorSurfaceMargin;
params.y = mMagnificationFrame.top - mMirrorSurfaceMargin;
+ // If nav bar mode supports swipe-up gesture, the Y position of mirror view should not
+ // overlap nav bar window to prevent window-dragging obscured.
+ if (supportsSwipeUpGesture()) {
+ params.y = Math.min(params.y, maxMirrorViewY);
+ }
// Translates MirrorView position to make MirrorSurfaceView that is inside MirrorView
// able to move close to the screen edges.
- final int maxMirrorViewX = mDisplaySize.x - mMirrorView.getWidth();
- final int maxMirrorViewY = mDisplaySize.y - mMirrorView.getHeight();
final float translationX;
final float translationY;
if (params.x < 0) {
@@ -621,6 +655,10 @@
return mMirrorView != null;
}
+ private boolean supportsSwipeUpGesture() {
+ return mNavBarMode == NAV_BAR_MODE_2BUTTON || mNavBarMode == NAV_BAR_MODE_GESTURAL;
+ }
+
private CharSequence formatStateDescription(float scale) {
// Cache the locale-appropriate NumberFormat. Configuration locale is guaranteed
// non-null, so the first time this is called we will always get the appropriate
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
index fa33284..1e239b1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
@@ -17,30 +17,44 @@
package com.android.systemui.qs;
import com.android.systemui.R;
+import com.android.systemui.util.ViewController;
import javax.inject.Inject;
-public class QSContainerImplController {
- private final QSContainerImpl mView;
+class QSContainerImplController extends ViewController<QSContainerImpl> {
private final QuickStatusBarHeaderController mQuickStatusBarHeaderController;
private QSContainerImplController(QSContainerImpl view,
QuickStatusBarHeaderController.Builder quickStatusBarHeaderControllerBuilder) {
- mView = view;
+ super(view);
mQuickStatusBarHeaderController = quickStatusBarHeaderControllerBuilder
.setQuickStatusBarHeader(mView.findViewById(R.id.header)).build();
}
+ @Override
+ public void init() {
+ super.init();
+ mQuickStatusBarHeaderController.init();
+ }
+
public void setListening(boolean listening) {
mQuickStatusBarHeaderController.setListening(listening);
}
- public static class Builder {
+ @Override
+ protected void onViewAttached() {
+ }
+
+ @Override
+ protected void onViewDetached() {
+ }
+
+ static class Builder {
private final QuickStatusBarHeaderController.Builder mQuickStatusBarHeaderControllerBuilder;
private QSContainerImpl mView;
@Inject
- public Builder(
+ Builder(
QuickStatusBarHeaderController.Builder quickStatusBarHeaderControllerBuilder) {
mQuickStatusBarHeaderControllerBuilder = quickStatusBarHeaderControllerBuilder;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index f1bb899..3a78365 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -142,7 +142,7 @@
mQSContainerImplController = mQSContainerImplControllerBuilder
.setQSContainerImpl((QSContainerImpl) view)
.build();
-
+ mQSContainerImplController.init();
mQSDetail.setQsPanel(mQSPanel, mHeader, (View) mFooter);
mQSAnimator = new QSAnimator(this, mHeader.findViewById(R.id.quick_qs_panel), mQSPanel);
@@ -367,14 +367,13 @@
if (DEBUG) Log.d(TAG, "setListening " + listening);
mListening = listening;
mQSContainerImplController.setListening(listening);
- mHeader.setListening(listening);
mFooter.setListening(listening);
mQSPanel.setListening(mListening, mQsExpanded);
}
@Override
public void setHeaderListening(boolean listening) {
- mHeader.setListening(listening);
+ mQSContainerImplController.setListening(listening);
mFooter.setListening(listening);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 544249a..a9fbc74 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -17,27 +17,16 @@
import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
-
import android.annotation.ColorInt;
-import android.app.AlarmManager;
+import android.app.AlarmManager.AlarmClockInfo;
import android.content.Context;
-import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
import android.media.AudioManager;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.provider.AlarmClock;
-import android.provider.Settings;
-import android.service.notification.ZenModeConfig;
-import android.text.format.DateUtils;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.MathUtils;
import android.util.Pair;
import android.view.ContextThemeWrapper;
@@ -53,93 +42,48 @@
import android.widget.TextView;
import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
-import com.android.internal.logging.UiEventLogger;
import com.android.settingslib.Utils;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.DualToneHandler;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.demomode.DemoMode;
-import com.android.systemui.demomode.DemoModeController;
-import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.privacy.OngoingPrivacyChip;
-import com.android.systemui.privacy.PrivacyChipEvent;
-import com.android.systemui.privacy.PrivacyItem;
-import com.android.systemui.privacy.PrivacyItemController;
import com.android.systemui.qs.QSDetail.Callback;
-import com.android.systemui.qs.carrier.QSCarrierGroup;
-import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
import com.android.systemui.statusbar.phone.StatusBarWindowView;
-import com.android.systemui.statusbar.phone.StatusIconContainer;
import com.android.systemui.statusbar.policy.Clock;
-import com.android.systemui.statusbar.policy.DateView;
-import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.util.RingerModeTracker;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Locale;
import java.util.Objects;
-import javax.inject.Inject;
-import javax.inject.Named;
-
/**
* View that contains the top-most bits of the screen (primarily the status bar with date, time, and
* battery) and also contains the {@link QuickQSPanel} along with some of the panel's inner
* contents.
*/
-public class QuickStatusBarHeader extends RelativeLayout implements
- View.OnClickListener, NextAlarmController.NextAlarmChangeCallback,
- ZenModeController.Callback, LifecycleOwner {
- private static final String TAG = "QuickStatusBarHeader";
- private static final boolean DEBUG = false;
+public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwner {
- /** Delay for auto fading out the long press tooltip after it's fully visible (in ms). */
- private static final long AUTO_FADE_OUT_DELAY_MS = DateUtils.SECOND_IN_MILLIS * 6;
- private static final int FADE_ANIMATION_DURATION_MS = 300;
- private static final int TOOLTIP_NOT_YET_SHOWN_COUNT = 0;
public static final int MAX_TOOLTIP_SHOWN_COUNT = 2;
- private final NextAlarmController mAlarmController;
- private final ZenModeController mZenController;
- private final StatusBarIconController mStatusBarIconController;
- private final ActivityStarter mActivityStarter;
-
- private QSPanel mQsPanel;
-
private boolean mExpanded;
- private boolean mListening;
private boolean mQsDisabled;
- private QSCarrierGroup mCarrierGroup;
protected QuickQSPanel mHeaderQsPanel;
- protected QSTileHost mHost;
- private TintedIconManager mIconManager;
private TouchAnimator mStatusIconsAlphaAnimator;
private TouchAnimator mHeaderTextContainerAlphaAnimator;
private TouchAnimator mPrivacyChipAlphaAnimator;
private DualToneHandler mDualToneHandler;
- private final CommandQueue mCommandQueue;
private View mSystemIconsView;
private View mQuickQsStatusIcons;
private View mHeaderTextContainerView;
- private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
- private AlarmManager.AlarmClockInfo mNextAlarm;
-
private ImageView mNextAlarmIcon;
/** {@link TextView} containing the actual text indicating when the next alarm will go off. */
private TextView mNextAlarmTextView;
@@ -149,23 +93,13 @@
private TextView mRingerModeTextView;
private View mRingerContainer;
private Clock mClockView;
- private DateView mDateView;
private OngoingPrivacyChip mPrivacyChip;
private Space mSpace;
private BatteryMeterView mBatteryRemainingIcon;
- private RingerModeTracker mRingerModeTracker;
- private DemoModeController mDemoModeController;
- private DemoMode mDemoModeReceiver;
- private UserTracker mUserTracker;
- private boolean mAllIndicatorsEnabled;
- private boolean mMicCameraIndicatorsEnabled;
- private PrivacyItemController mPrivacyItemController;
- private final UiEventLogger mUiEventLogger;
// Used for RingerModeTracker
private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
- private boolean mHasTopCutout = false;
private int mStatusBarPaddingTop = 0;
private int mRoundedCornerPadding = 0;
private int mContentMarginStart;
@@ -175,59 +109,11 @@
private int mCutOutPaddingRight;
private float mExpandedHeaderAlpha = 1.0f;
private float mKeyguardExpansionFraction;
- private boolean mPrivacyChipLogged = false;
- private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() {
- @Override
- public void onPrivacyItemsChanged(List<PrivacyItem> privacyItems) {
- mPrivacyChip.setPrivacyList(privacyItems);
- setChipVisibility(!privacyItems.isEmpty());
- }
-
- @Override
- public void onFlagAllChanged(boolean flag) {
- if (mAllIndicatorsEnabled != flag) {
- mAllIndicatorsEnabled = flag;
- update();
- }
- }
-
- @Override
- public void onFlagMicCameraChanged(boolean flag) {
- if (mMicCameraIndicatorsEnabled != flag) {
- mMicCameraIndicatorsEnabled = flag;
- update();
- }
- }
-
- private void update() {
- StatusIconContainer iconContainer = requireViewById(R.id.statusIcons);
- iconContainer.setIgnoredSlots(getIgnoredIconSlots());
- setChipVisibility(!mPrivacyChip.getPrivacyList().isEmpty());
- }
- };
-
- @Inject
- public QuickStatusBarHeader(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
- NextAlarmController nextAlarmController, ZenModeController zenModeController,
- StatusBarIconController statusBarIconController,
- ActivityStarter activityStarter, PrivacyItemController privacyItemController,
- CommandQueue commandQueue, RingerModeTracker ringerModeTracker,
- UiEventLogger uiEventLogger, DemoModeController demoModeController,
- UserTracker userTracker) {
+ public QuickStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs);
- mAlarmController = nextAlarmController;
- mZenController = zenModeController;
- mStatusBarIconController = statusBarIconController;
- mActivityStarter = activityStarter;
- mPrivacyItemController = privacyItemController;
mDualToneHandler = new DualToneHandler(
new ContextThemeWrapper(context, R.style.QSHeaderTheme));
- mCommandQueue = commandQueue;
- mRingerModeTracker = ringerModeTracker;
- mUiEventLogger = uiEventLogger;
- mDemoModeController = demoModeController;
- mUserTracker = userTracker;
}
@Override
@@ -237,11 +123,6 @@
mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
mSystemIconsView = findViewById(R.id.quick_status_bar_system_icons);
mQuickQsStatusIcons = findViewById(R.id.quick_qs_status_icons);
- StatusIconContainer iconContainer = findViewById(R.id.statusIcons);
- // Ignore privacy icons because they show in the space above QQS
- iconContainer.addIgnoredSlots(getIgnoredIconSlots());
- iconContainer.setShouldRestrictIcons(false);
- mIconManager = new TintedIconManager(iconContainer, mCommandQueue);
// Views corresponding to the header info section (e.g. ringer and next alarm).
mHeaderTextContainerView = findViewById(R.id.header_text_container);
@@ -249,36 +130,18 @@
mNextAlarmIcon = findViewById(R.id.next_alarm_icon);
mNextAlarmTextView = findViewById(R.id.next_alarm_text);
mNextAlarmContainer = findViewById(R.id.alarm_container);
- mNextAlarmContainer.setOnClickListener(this::onClick);
mRingerModeIcon = findViewById(R.id.ringer_mode_icon);
mRingerModeTextView = findViewById(R.id.ringer_mode_text);
mRingerContainer = findViewById(R.id.ringer_container);
- mRingerContainer.setOnClickListener(this::onClick);
mPrivacyChip = findViewById(R.id.privacy_chip);
- mPrivacyChip.setOnClickListener(this::onClick);
- mCarrierGroup = findViewById(R.id.carrier_group);
-
updateResources();
Rect tintArea = new Rect(0, 0, 0, 0);
- int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
- android.R.attr.colorForeground);
- float intensity = getColorIntensity(colorForeground);
- int fillColor = mDualToneHandler.getSingleColor(intensity);
-
// Set light text on the header icons because they will always be on a black background
applyDarkness(R.id.clock, tintArea, 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
- // Set the correct tint for the status icons so they contrast
- mIconManager.setTint(fillColor);
- mNextAlarmIcon.setImageTintList(ColorStateList.valueOf(fillColor));
- mRingerModeIcon.setImageTintList(ColorStateList.valueOf(fillColor));
-
mClockView = findViewById(R.id.clock);
- mClockView.setOnClickListener(this);
- mDemoModeReceiver = new ClockDemoModeReceiver(mClockView);
- mDateView = findViewById(R.id.date);
mSpace = findViewById(R.id.space);
// Tint for the battery icons are handled in setupHost()
@@ -290,33 +153,28 @@
mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
mRingerModeTextView.setSelected(true);
mNextAlarmTextView.setSelected(true);
+ }
- mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
- mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
+ void onAttach(TintedIconManager iconManager) {
+ int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
+ android.R.attr.colorForeground);
+ float intensity = getColorIntensity(colorForeground);
+ int fillColor = mDualToneHandler.getSingleColor(intensity);
+
+ // Set the correct tint for the status icons so they contrast
+ iconManager.setTint(fillColor);
+ mNextAlarmIcon.setImageTintList(ColorStateList.valueOf(fillColor));
+ mRingerModeIcon.setImageTintList(ColorStateList.valueOf(fillColor));
}
public QuickQSPanel getHeaderQsPanel() {
return mHeaderQsPanel;
}
- private List<String> getIgnoredIconSlots() {
- ArrayList<String> ignored = new ArrayList<>();
- if (getChipEnabled()) {
- ignored.add(mContext.getResources().getString(
- com.android.internal.R.string.status_bar_camera));
- ignored.add(mContext.getResources().getString(
- com.android.internal.R.string.status_bar_microphone));
- if (mAllIndicatorsEnabled) {
- ignored.add(mContext.getResources().getString(
- com.android.internal.R.string.status_bar_location));
- }
- }
-
- return ignored;
- }
-
- private void updateStatusText() {
- boolean changed = updateRingerStatus() || updateAlarmStatus();
+ void updateStatusText(int ringerMode, AlarmClockInfo nextAlarm, boolean zenOverridingRinger,
+ boolean use24HourFormat) {
+ boolean changed = updateRingerStatus(ringerMode, zenOverridingRinger)
+ || updateAlarmStatus(nextAlarm, use24HourFormat);
if (changed) {
boolean alarmVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
@@ -326,32 +184,17 @@
}
}
- private void setChipVisibility(boolean chipVisible) {
- if (chipVisible && getChipEnabled()) {
- mPrivacyChip.setVisibility(View.VISIBLE);
- // Makes sure that the chip is logged as viewed at most once each time QS is opened
- // mListening makes sure that the callback didn't return after the user closed QS
- if (!mPrivacyChipLogged && mListening) {
- mPrivacyChipLogged = true;
- mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_VIEW);
- }
- } else {
- mPrivacyChip.setVisibility(View.GONE);
- }
- }
-
- private boolean updateRingerStatus() {
+ private boolean updateRingerStatus(int ringerMode, boolean zenOverridingRinger) {
boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
CharSequence originalRingerText = mRingerModeTextView.getText();
boolean ringerVisible = false;
- if (!ZenModeConfig.isZenOverridingRinger(mZenController.getZen(),
- mZenController.getConsolidatedPolicy())) {
- if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
+ if (!zenOverridingRinger) {
+ if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
mRingerModeIcon.setImageResource(R.drawable.ic_volume_ringer_vibrate);
mRingerModeTextView.setText(R.string.qs_status_phone_vibrate);
ringerVisible = true;
- } else if (mRingerMode == AudioManager.RINGER_MODE_SILENT) {
+ } else if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
mRingerModeIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
mRingerModeTextView.setText(R.string.qs_status_phone_muted);
ringerVisible = true;
@@ -365,14 +208,14 @@
!Objects.equals(originalRingerText, mRingerModeTextView.getText());
}
- private boolean updateAlarmStatus() {
+ private boolean updateAlarmStatus(AlarmClockInfo nextAlarm, boolean use24HourFormat) {
boolean isOriginalVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
CharSequence originalAlarmText = mNextAlarmTextView.getText();
boolean alarmVisible = false;
- if (mNextAlarm != null) {
+ if (nextAlarm != null) {
alarmVisible = true;
- mNextAlarmTextView.setText(formatNextAlarm(mNextAlarm));
+ mNextAlarmTextView.setText(formatNextAlarm(nextAlarm, use24HourFormat));
}
mNextAlarmIcon.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
mNextAlarmTextView.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
@@ -419,7 +262,7 @@
setMinimumHeight(sbHeight + qqsHeight);
}
- private void updateResources() {
+ void updateResources() {
Resources resources = mContext.getResources();
updateMinimumHeight();
@@ -529,18 +372,6 @@
}
@Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- mRingerModeTracker.getRingerModeInternal().observe(this, ringer -> {
- mRingerMode = ringer;
- updateStatusText();
- });
- mStatusBarIconController.addIconGroup(mIconManager);
- mDemoModeController.addCallback(mDemoModeReceiver);
- requestApplyInsets();
- }
-
- @Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
// Handle padding of the clock
DisplayCutout cutout = insets.getDisplayCutout();
@@ -563,17 +394,14 @@
if (cutout != null) {
Rect topCutout = cutout.getBoundingRectTop();
if (topCutout.isEmpty() || cornerCutout) {
- mHasTopCutout = false;
lp.width = 0;
mSpace.setVisibility(View.GONE);
} else {
- mHasTopCutout = true;
lp.width = topCutout.width();
mSpace.setVisibility(View.VISIBLE);
}
}
mSpace.setLayoutParams(lp);
- setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
mCutOutPaddingLeft = padding.first;
mCutOutPaddingRight = padding.second;
mWaterfallTopInset = cutout == null ? 0 : cutout.getWaterfallInsets().top;
@@ -611,103 +439,14 @@
0);
}
- @Override
- @VisibleForTesting
- public void onDetachedFromWindow() {
- setListening(false);
- mRingerModeTracker.getRingerModeInternal().removeObservers(this);
- mStatusBarIconController.removeIconGroup(mIconManager);
- mDemoModeController.removeCallback(mDemoModeReceiver);
- super.onDetachedFromWindow();
- }
-
- public void setListening(boolean listening) {
- if (listening == mListening) {
- return;
- }
- mHeaderQsPanel.setListening(listening);
- if (mHeaderQsPanel.switchTileLayout()) {
- updateResources();
- }
- mListening = listening;
-
- if (listening) {
- mZenController.addCallback(this);
- mAlarmController.addCallback(this);
- mLifecycle.setCurrentState(Lifecycle.State.RESUMED);
- // Get the most up to date info
- mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
- mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
- mPrivacyItemController.addCallback(mPICCallback);
- } else {
- mZenController.removeCallback(this);
- mAlarmController.removeCallback(this);
- mLifecycle.setCurrentState(Lifecycle.State.CREATED);
- mPrivacyItemController.removeCallback(mPICCallback);
- mPrivacyChipLogged = false;
- }
- }
-
- @Override
- public void onClick(View v) {
- if (v == mClockView) {
- mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
- AlarmClock.ACTION_SHOW_ALARMS), 0);
- } else if (v == mNextAlarmContainer && mNextAlarmContainer.isVisibleToUser()) {
- if (mNextAlarm.getShowIntent() != null) {
- mActivityStarter.postStartActivityDismissingKeyguard(
- mNextAlarm.getShowIntent());
- } else {
- Log.d(TAG, "No PendingIntent for next alarm. Using default intent");
- mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
- AlarmClock.ACTION_SHOW_ALARMS), 0);
- }
- } else if (v == mPrivacyChip) {
- // If the privacy chip is visible, it means there were some indicators
- Handler mUiHandler = new Handler(Looper.getMainLooper());
- mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_CLICK);
- mUiHandler.post(() -> {
- mActivityStarter.postStartActivityDismissingKeyguard(
- new Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE), 0);
- mHost.collapsePanels();
- });
- } else if (v == mRingerContainer && mRingerContainer.isVisibleToUser()) {
- mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
- Settings.ACTION_SOUND_SETTINGS), 0);
- }
- }
-
- @Override
- public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
- mNextAlarm = nextAlarm;
- updateStatusText();
- }
-
- @Override
- public void onZenChanged(int zen) {
- updateStatusText();
- }
-
- @Override
- public void onConfigChanged(ZenModeConfig config) {
- updateStatusText();
- }
-
public void updateEverything() {
post(() -> setClickable(!mExpanded));
}
public void setQSPanel(final QSPanel qsPanel) {
- mQsPanel = qsPanel;
- setupHost(qsPanel.getHost());
- }
-
- public void setupHost(final QSTileHost host) {
- mHost = host;
//host.setHeaderView(mExpandIndicator);
- mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
- mHeaderQsPanel.setHost(host, null /* No customization in header */);
-
+ mHeaderQsPanel.setQSPanelAndHeader(qsPanel, this);
+ mHeaderQsPanel.setHost(qsPanel.getHost(), null /* No customization in header */);
Rect tintArea = new Rect(0, 0, 0, 0);
int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
@@ -721,12 +460,11 @@
mHeaderQsPanel.setCallback(qsPanelCallback);
}
- private String formatNextAlarm(AlarmManager.AlarmClockInfo info) {
+ private String formatNextAlarm(AlarmClockInfo info, boolean use24HourFormat) {
if (info == null) {
return "";
}
- String skeleton = android.text.format.DateFormat
- .is24HourFormat(mContext, mUserTracker.getUserId()) ? "EHm" : "Ehma";
+ String skeleton = use24HourFormat ? "EHm" : "Ehma";
String pattern = android.text.format.DateFormat
.getBestDateTimePattern(Locale.getDefault(), skeleton);
return android.text.format.DateFormat.format(pattern, info.getTriggerTime()).toString();
@@ -777,37 +515,4 @@
updateHeaderTextContainerAlphaAnimator();
}
}
-
- private boolean getChipEnabled() {
- return mMicCameraIndicatorsEnabled || mAllIndicatorsEnabled;
- }
-
- private static class ClockDemoModeReceiver implements DemoMode {
- private Clock mClockView;
-
- @Override
- public List<String> demoCommands() {
- return List.of(COMMAND_CLOCK);
- }
-
- ClockDemoModeReceiver(Clock clockView) {
- mClockView = clockView;
- }
-
- @Override
- public void dispatchDemoCommand(String command, Bundle args) {
- mClockView.dispatchDemoCommand(command, args);
- }
-
- @Override
- public void onDemoModeStarted() {
- mClockView.onDemoModeStarted();
- }
-
- @Override
- public void onDemoModeFinished() {
- mClockView.onDemoModeFinished();
- }
- }
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index d899acb..676a300 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -16,36 +16,393 @@
package com.android.systemui.qs;
+import android.app.AlarmManager.AlarmClockInfo;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.AlarmClock;
+import android.provider.Settings;
+import android.service.notification.ZenModeConfig;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
+
+import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
+import com.android.systemui.demomode.DemoMode;
+import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.privacy.OngoingPrivacyChip;
+import com.android.systemui.privacy.PrivacyChipEvent;
+import com.android.systemui.privacy.PrivacyItem;
+import com.android.systemui.privacy.PrivacyItemController;
import com.android.systemui.qs.carrier.QSCarrierGroupController;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusIconContainer;
+import com.android.systemui.statusbar.policy.Clock;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.statusbar.policy.ZenModeController.Callback;
+import com.android.systemui.util.RingerModeTracker;
+import com.android.systemui.util.ViewController;
+
+import java.util.ArrayList;
+import java.util.List;
import javax.inject.Inject;
-public class QuickStatusBarHeaderController {
- private final QuickStatusBarHeader mView;
+/**
+ * Controller for {@link QuickStatusBarHeader}.
+ */
+class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader> {
+ private static final String TAG = "QuickStatusBarHeader";
+
+ private final ZenModeController mZenModeController;
+ private final NextAlarmController mNextAlarmController;
+ private final PrivacyItemController mPrivacyItemController;
+ private final RingerModeTracker mRingerModeTracker;
+ private final ActivityStarter mActivityStarter;
+ private final UiEventLogger mUiEventLogger;
private final QSCarrierGroupController mQSCarrierGroupController;
+ private final QuickQSPanel mHeaderQsPanel;
+ private final LifecycleRegistry mLifecycle;
+ private final OngoingPrivacyChip mPrivacyChip;
+ private final Clock mClockView;
+ private final View mNextAlarmContainer;
+ private final View mRingerContainer;
+ private final QSTileHost mQSTileHost;
+ private final StatusBarIconController mStatusBarIconController;
+ private final CommandQueue mCommandQueue;
+ private final DemoModeController mDemoModeController;
+ private final UserTracker mUserTracker;
+ private final StatusIconContainer mIconContainer;
+ private final StatusBarIconController.TintedIconManager mIconManager;
+ private final DemoMode mDemoModeReceiver;
+
+ private boolean mListening;
+ private AlarmClockInfo mNextAlarm;
+ private boolean mAllIndicatorsEnabled;
+ private boolean mMicCameraIndicatorsEnabled;
+ private boolean mPrivacyChipLogged;
+ private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
+
+ private final ZenModeController.Callback mZenModeControllerCallback = new Callback() {
+ @Override
+ public void onZenChanged(int zen) {
+ mView.updateStatusText(mRingerMode, mNextAlarm, isZenOverridingRinger(),
+ use24HourFormat());
+ }
+
+ @Override
+ public void onConfigChanged(ZenModeConfig config) {
+ mView.updateStatusText(mRingerMode, mNextAlarm, isZenOverridingRinger(),
+ use24HourFormat());
+ }
+ };
+
+ private boolean use24HourFormat() {
+ return android.text.format.DateFormat.is24HourFormat(
+ mView.getContext(), mUserTracker.getUserId());
+
+ }
+
+ private final NextAlarmChangeCallback mNextAlarmChangeCallback = new NextAlarmChangeCallback() {
+ @Override
+ public void onNextAlarmChanged(AlarmClockInfo nextAlarm) {
+ mNextAlarm = nextAlarm;
+ mView.updateStatusText(mRingerMode, mNextAlarm, isZenOverridingRinger(),
+ use24HourFormat());
+ }
+ };
+
+ private final LifecycleOwner mLifecycleOwner = new LifecycleOwner() {
+ @NonNull
+ @Override
+ public Lifecycle getLifecycle() {
+ return mLifecycle;
+ }
+ };
+
+ private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() {
+ @Override
+ public void onPrivacyItemsChanged(@NonNull List<PrivacyItem> privacyItems) {
+ mPrivacyChip.setPrivacyList(privacyItems);
+ setChipVisibility(!privacyItems.isEmpty());
+ }
+
+ @Override
+ public void onFlagAllChanged(boolean flag) {
+ if (mAllIndicatorsEnabled != flag) {
+ mAllIndicatorsEnabled = flag;
+ update();
+ }
+ }
+
+ @Override
+ public void onFlagMicCameraChanged(boolean flag) {
+ if (mMicCameraIndicatorsEnabled != flag) {
+ mMicCameraIndicatorsEnabled = flag;
+ update();
+ }
+ }
+
+ private void update() {
+ StatusIconContainer iconContainer = mView.requireViewById(R.id.statusIcons);
+ iconContainer.setIgnoredSlots(getIgnoredIconSlots());
+ setChipVisibility(!mPrivacyChip.getPrivacyList().isEmpty());
+ }
+ };
+
+ private View.OnClickListener mOnClickListener = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (v == mClockView) {
+ mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
+ AlarmClock.ACTION_SHOW_ALARMS), 0);
+ } else if (v == mNextAlarmContainer && mNextAlarmContainer.isVisibleToUser()) {
+ if (mNextAlarm.getShowIntent() != null) {
+ mActivityStarter.postStartActivityDismissingKeyguard(
+ mNextAlarm.getShowIntent());
+ } else {
+ Log.d(TAG, "No PendingIntent for next alarm. Using default intent");
+ mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
+ AlarmClock.ACTION_SHOW_ALARMS), 0);
+ }
+ } else if (v == mPrivacyChip) {
+ // If the privacy chip is visible, it means there were some indicators
+ Handler mUiHandler = new Handler(Looper.getMainLooper());
+ mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_CLICK);
+ mUiHandler.post(() -> {
+ mActivityStarter.postStartActivityDismissingKeyguard(
+ new Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE), 0);
+ mQSTileHost.collapsePanels();
+ });
+ } else if (v == mRingerContainer && mRingerContainer.isVisibleToUser()) {
+ mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
+ Settings.ACTION_SOUND_SETTINGS), 0);
+ }
+ }
+ };
private QuickStatusBarHeaderController(QuickStatusBarHeader view,
+ ZenModeController zenModeController, NextAlarmController nextAlarmController,
+ PrivacyItemController privacyItemController, RingerModeTracker ringerModeTracker,
+ ActivityStarter activityStarter, UiEventLogger uiEventLogger,
+ QSTileHost qsTileHost, StatusBarIconController statusBarIconController,
+ CommandQueue commandQueue, DemoModeController demoModeController,
+ UserTracker userTracker,
QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder) {
- mView = view;
+ super(view);
+ mZenModeController = zenModeController;
+ mNextAlarmController = nextAlarmController;
+ mPrivacyItemController = privacyItemController;
+ mRingerModeTracker = ringerModeTracker;
+ mActivityStarter = activityStarter;
+ mUiEventLogger = uiEventLogger;
+ mQSTileHost = qsTileHost;
+ mStatusBarIconController = statusBarIconController;
+ mCommandQueue = commandQueue;
+ mDemoModeController = demoModeController;
+ mUserTracker = userTracker;
+ mLifecycle = new LifecycleRegistry(mLifecycleOwner);
+
mQSCarrierGroupController = qsCarrierGroupControllerBuilder
.setQSCarrierGroup(mView.findViewById(R.id.carrier_group))
.build();
+
+
+ mPrivacyChip = mView.findViewById(R.id.privacy_chip);
+ mHeaderQsPanel = mView.findViewById(R.id.quick_qs_panel);
+ mNextAlarmContainer = mView.findViewById(R.id.alarm_container);
+ mClockView = mView.findViewById(R.id.clock);
+ mRingerContainer = mView.findViewById(R.id.ringer_container);
+ mIconContainer = mView.findViewById(R.id.statusIcons);
+
+ mIconManager = new StatusBarIconController.TintedIconManager(mIconContainer, mCommandQueue);
+ mDemoModeReceiver = new ClockDemoModeReceiver(mClockView);
+ }
+
+ @Override
+ protected void onViewAttached() {
+ mRingerModeTracker.getRingerModeInternal().observe(mLifecycleOwner, ringer -> {
+ mRingerMode = ringer;
+ mView.updateStatusText(mRingerMode, mNextAlarm, isZenOverridingRinger(),
+ use24HourFormat());
+ });
+
+ mClockView.setOnClickListener(mOnClickListener);
+ mNextAlarmContainer.setOnClickListener(mOnClickListener);
+ mRingerContainer.setOnClickListener(mOnClickListener);
+ mPrivacyChip.setOnClickListener(mOnClickListener);
+
+ // Ignore privacy icons because they show in the space above QQS
+ mIconContainer.addIgnoredSlots(getIgnoredIconSlots());
+ mIconContainer.setShouldRestrictIcons(false);
+ mStatusBarIconController.addIconGroup(mIconManager);
+
+ mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
+ mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
+
+ setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
+
+ mView.onAttach(mIconManager);
+
+ mDemoModeController.addCallback(mDemoModeReceiver);
+ }
+
+ @Override
+ protected void onViewDetached() {
+ mRingerModeTracker.getRingerModeInternal().removeObservers(mLifecycleOwner);
+ mClockView.setOnClickListener(null);
+ mNextAlarmContainer.setOnClickListener(null);
+ mRingerContainer.setOnClickListener(null);
+ mPrivacyChip.setOnClickListener(null);
+ mStatusBarIconController.removeIconGroup(mIconManager);
+ mDemoModeController.removeCallback(mDemoModeReceiver);
+ setListening(false);
}
public void setListening(boolean listening) {
mQSCarrierGroupController.setListening(listening);
- // TODO: move mView.setListening logic into here.
- mView.setListening(listening);
+
+ if (listening == mListening) {
+ return;
+ }
+ mListening = listening;
+
+ mHeaderQsPanel.setListening(listening);
+ if (mHeaderQsPanel.switchTileLayout()) {
+ mView.updateResources();
+ }
+
+ if (listening) {
+ mZenModeController.addCallback(mZenModeControllerCallback);
+ mNextAlarmController.addCallback(mNextAlarmChangeCallback);
+ mLifecycle.setCurrentState(Lifecycle.State.RESUMED);
+ // Get the most up to date info
+ mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
+ mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
+ mPrivacyItemController.addCallback(mPICCallback);
+ } else {
+ mZenModeController.removeCallback(mZenModeControllerCallback);
+ mNextAlarmController.removeCallback(mNextAlarmChangeCallback);
+ mLifecycle.setCurrentState(Lifecycle.State.CREATED);
+ mPrivacyItemController.removeCallback(mPICCallback);
+ mPrivacyChipLogged = false;
+ }
+ }
+
+ private void setChipVisibility(boolean chipVisible) {
+ if (chipVisible && getChipEnabled()) {
+ mPrivacyChip.setVisibility(View.VISIBLE);
+ // Makes sure that the chip is logged as viewed at most once each time QS is opened
+ // mListening makes sure that the callback didn't return after the user closed QS
+ if (!mPrivacyChipLogged && mListening) {
+ mPrivacyChipLogged = true;
+ mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_VIEW);
+ }
+ } else {
+ mPrivacyChip.setVisibility(View.GONE);
+ }
+ }
+
+ private List<String> getIgnoredIconSlots() {
+ ArrayList<String> ignored = new ArrayList<>();
+ if (getChipEnabled()) {
+ ignored.add(mView.getResources().getString(
+ com.android.internal.R.string.status_bar_camera));
+ ignored.add(mView.getResources().getString(
+ com.android.internal.R.string.status_bar_microphone));
+ if (mAllIndicatorsEnabled) {
+ ignored.add(mView.getResources().getString(
+ com.android.internal.R.string.status_bar_location));
+ }
+ }
+
+ return ignored;
+ }
+
+ private boolean getChipEnabled() {
+ return mMicCameraIndicatorsEnabled || mAllIndicatorsEnabled;
+ }
+
+ private boolean isZenOverridingRinger() {
+ return ZenModeConfig.isZenOverridingRinger(mZenModeController.getZen(),
+ mZenModeController.getConsolidatedPolicy());
}
- public static class Builder {
+ private static class ClockDemoModeReceiver implements DemoMode {
+ private Clock mClockView;
+
+ @Override
+ public List<String> demoCommands() {
+ return List.of(COMMAND_CLOCK);
+ }
+
+ ClockDemoModeReceiver(Clock clockView) {
+ mClockView = clockView;
+ }
+
+ @Override
+ public void dispatchDemoCommand(String command, Bundle args) {
+ mClockView.dispatchDemoCommand(command, args);
+ }
+
+ @Override
+ public void onDemoModeStarted() {
+ mClockView.onDemoModeStarted();
+ }
+
+ @Override
+ public void onDemoModeFinished() {
+ mClockView.onDemoModeFinished();
+ }
+ }
+
+ static class Builder {
+ private final ZenModeController mZenModeController;
+ private final NextAlarmController mNextAlarmController;
+ private final PrivacyItemController mPrivacyItemController;
+ private final RingerModeTracker mRingerModeTracker;
+ private final ActivityStarter mActivityStarter;
+ private final UiEventLogger mUiEventLogger;
+ private final QSTileHost mQsTileHost;
+ private final StatusBarIconController mStatusBarIconController;
+ private final CommandQueue mCommandQueue;
+ private final DemoModeController mDemoModeController;
+ private final UserTracker mUserTracker;
private final QSCarrierGroupController.Builder mQSCarrierGroupControllerBuilder;
private QuickStatusBarHeader mView;
@Inject
- public Builder(QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder) {
+ Builder(ZenModeController zenModeController, NextAlarmController nextAlarmController,
+ PrivacyItemController privacyItemController, RingerModeTracker ringerModeTracker,
+ ActivityStarter activityStarter, UiEventLogger uiEventLogger, QSTileHost qsTileHost,
+ StatusBarIconController statusBarIconController, CommandQueue commandQueue,
+ DemoModeController demoModeController, UserTracker userTracker,
+ QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder) {
+ mZenModeController = zenModeController;
+ mNextAlarmController = nextAlarmController;
+ mPrivacyItemController = privacyItemController;
+ mRingerModeTracker = ringerModeTracker;
+ mActivityStarter = activityStarter;
+ mUiEventLogger = uiEventLogger;
+ mQsTileHost = qsTileHost;
+ mStatusBarIconController = statusBarIconController;
+ mCommandQueue = commandQueue;
+ mDemoModeController = demoModeController;
+ mUserTracker = userTracker;
mQSCarrierGroupControllerBuilder = qsCarrierGroupControllerBuilder;
}
@@ -54,8 +411,13 @@
return this;
}
- public QuickStatusBarHeaderController build() {
- return new QuickStatusBarHeaderController(mView, mQSCarrierGroupControllerBuilder);
+
+ QuickStatusBarHeaderController build() {
+ return new QuickStatusBarHeaderController(mView, mZenModeController,
+ mNextAlarmController, mPrivacyItemController, mRingerModeTracker,
+ mActivityStarter, mUiEventLogger, mQsTileHost, mStatusBarIconController,
+ mCommandQueue, mDemoModeController, mUserTracker,
+ mQSCarrierGroupControllerBuilder);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenInternalAudioRecorder.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenInternalAudioRecorder.java
index df03c3e..0aa9d4d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenInternalAudioRecorder.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenInternalAudioRecorder.java
@@ -48,6 +48,7 @@
private long mTotalBytes;
private MediaMuxer mMuxer;
private boolean mMic;
+ private boolean mStarted;
private int mTrackId = -1;
@@ -263,10 +264,14 @@
* start recording
* @throws IllegalStateException if recording fails to initialize
*/
- public void start() throws IllegalStateException {
- if (mThread != null) {
- Log.e(TAG, "a recording is being done in parallel or stop is not called");
+ public synchronized void start() throws IllegalStateException {
+ if (mStarted) {
+ if (mThread == null) {
+ throw new IllegalStateException("Recording stopped and can't restart (single use)");
+ }
+ throw new IllegalStateException("Recording already started");
}
+ mStarted = true;
mAudioRecord.startRecording();
if (mMic) mAudioRecordMic.startRecording();
Log.d(TAG, "channel count " + mAudioRecord.getChannelCount());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
index 7aeca64..c9d1b71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
@@ -284,25 +284,28 @@
mAnimator.setTarget(mIndicatorView);
mAnimator.setProperty(View.ALPHA);
mAnimator.addListener(new AnimatorListenerAdapter() {
+ boolean mCancelled;
+
@Override
public void onAnimationStart(Animator animation, boolean isReverse) {
- if (DEBUG) Log.d(TAG, "onAnimationStart");
+ if (DEBUG) Log.d(TAG, "AnimatorListenerAdapter#onAnimationStart");
+ mCancelled = false;
}
@Override
public void onAnimationCancel(Animator animation) {
- if (DEBUG) Log.d(TAG, "onAnimationCancel");
+ if (DEBUG) Log.d(TAG, "AnimatorListenerAdapter#onAnimationCancel");
+ mCancelled = true;
}
@Override
public void onAnimationEnd(Animator animation) {
- if (DEBUG) Log.d(TAG, "onAnimationEnd");
-
- if (mState == STATE_APPEARING) {
- mState = STATE_SHOWN;
- } else if (mState == STATE_DISAPPEARING) {
- removeIndicatorView();
- mState = STATE_NOT_SHOWN;
+ if (DEBUG) Log.d(TAG, "AnimatorListenerAdapter#onAnimationEnd");
+ // When ValueAnimator#cancel() is called it always calls onAnimationCancel(...)
+ // and then onAnimationEnd(...). We, however, only want to proceed here if the
+ // animation ended "naturally".
+ if (!mCancelled) {
+ onAnimationFinished();
}
}
});
@@ -319,6 +322,17 @@
mAnimator.start();
}
+ private void onAnimationFinished() {
+ if (DEBUG) Log.d(TAG, "onAnimationFinished");
+
+ if (mState == STATE_APPEARING) {
+ mState = STATE_SHOWN;
+ } else if (mState == STATE_DISAPPEARING) {
+ removeIndicatorView();
+ mState = STATE_NOT_SHOWN;
+ }
+ }
+
private boolean hasActiveRecorders() {
for (int index = mAudioActivityObservers.length - 1; index >= 0; index--) {
for (String activePackage : mAudioActivityObservers[index].getActivePackages()) {
@@ -330,6 +344,8 @@
}
private void removeIndicatorView() {
+ if (DEBUG) Log.d(TAG, "removeIndicatorView");
+
final WindowManager windowManager = (WindowManager) mContext.getSystemService(
Context.WINDOW_SERVICE);
windowManager.removeView(mIndicatorView);
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index a6cd350..344f0d2 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -27,7 +27,6 @@
import com.android.systemui.qs.QSFooterImpl;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QuickQSPanel;
-import com.android.systemui.qs.QuickStatusBarHeader;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
@@ -93,10 +92,6 @@
}
/**
- * Creates the QuickStatusBarHeader.
- */
- QuickStatusBarHeader createQsHeader();
- /**
* Creates the QSFooterImpl.
*/
QSFooterImpl createQsFooter();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
index 1e969c2..fa78d1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
@@ -36,6 +36,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.statusbar.CommandQueue;
import org.junit.Before;
@@ -65,6 +66,8 @@
@Mock
private ModeSwitchesController mModeSwitchesController;
@Mock
+ private NavigationModeController mNavigationModeController;
+ @Mock
private IRemoteMagnificationAnimationCallback mAnimationCallback;
private IWindowMagnificationConnection mIWindowMagnificationConnection;
private WindowMagnification mWindowMagnification;
@@ -79,7 +82,8 @@
}).when(mAccessibilityManager).setWindowMagnificationConnection(
any(IWindowMagnificationConnection.class));
mWindowMagnification = new WindowMagnification(getContext(),
- getContext().getMainThreadHandler(), mCommandQueue, mModeSwitchesController);
+ getContext().getMainThreadHandler(), mCommandQueue, mModeSwitchesController,
+ mNavigationModeController);
mWindowMagnification.mWindowMagnificationAnimationController =
mWindowMagnificationAnimationController;
mWindowMagnification.requestWindowMagnificationConnection(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index c6440f4..5f2fd69 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -17,6 +17,7 @@
package com.android.systemui.accessibility;
import static android.view.Choreographer.FrameCallback;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import static org.hamcrest.Matchers.containsString;
@@ -28,6 +29,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
@@ -294,4 +296,15 @@
assertTrue(
mMirrorView.performAccessibilityAction(R.id.accessibility_action_move_left, null));
}
+
+ @Test
+ public void onNavigationModeChanged_updateMirrorViewLayout() {
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ Float.NaN);
+ mWindowMagnificationController.onNavigationModeChanged(NAV_BAR_MODE_GESTURAL);
+ });
+
+ verify(mWindowManager).updateViewLayout(eq(mMirrorView), any());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
index 936558b..4a0e216 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
@@ -35,6 +35,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.statusbar.CommandQueue;
import org.junit.Before;
@@ -53,6 +54,8 @@
private AccessibilityManager mAccessibilityManager;
@Mock
private ModeSwitchesController mModeSwitchesController;
+ @Mock
+ private NavigationModeController mNavigationModeController;
private CommandQueue mCommandQueue;
private WindowMagnification mWindowMagnification;
@@ -63,7 +66,8 @@
mCommandQueue = new CommandQueue(getContext());
mWindowMagnification = new WindowMagnification(getContext(),
- getContext().getMainThreadHandler(), mCommandQueue, mModeSwitchesController);
+ getContext().getMainThreadHandler(), mCommandQueue, mModeSwitchesController,
+ mNavigationModeController);
mWindowMagnification.start();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
index ca328fb..9ebb587 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
@@ -36,6 +36,7 @@
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.phone.ShadeController;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -73,6 +74,11 @@
when(mMediaDevice.getFeatures()).thenReturn(mFeatures);
}
+ @After
+ public void tearDown() {
+ mMediaOutputDialog.dismissDialog();
+ }
+
@Test
public void getStopButtonVisibility_remoteDevice_returnVisible() {
mFeatures.add(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 1c2d0840..e472cb2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -37,7 +37,6 @@
import com.android.internal.logging.UiEventLogger;
import com.android.keyguard.CarrierText;
import com.android.systemui.Dependency;
-import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -116,11 +115,6 @@
qs.setListening(false);
processAllMessages();
-
- // Manually push header through detach so it can handle standard cleanup it does on
- // removed from window.
- ((QuickStatusBarHeader) qs.getView().findViewById(R.id.header)).onDetachedFromWindow();
-
host.destroy();
processAllMessages();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index f3cdbf7..c085689 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -21,6 +21,7 @@
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import android.app.KeyguardManager;
@@ -167,6 +168,45 @@
AccessibilityManager.FLAG_CONTENT_CONTROLS);
}
+ @Test
+ public void testVibrateOnRingerChangedToVibrate() {
+ final State initialSilentState = new State();
+ initialSilentState.ringerModeInternal = AudioManager.RINGER_MODE_SILENT;
+
+ final State vibrateState = new State();
+ vibrateState.ringerModeInternal = AudioManager.RINGER_MODE_VIBRATE;
+
+ // change ringer to silent
+ mDialog.onStateChangedH(initialSilentState);
+
+ // expected: shouldn't call vibrate yet
+ verify(mController, never()).vibrate(any());
+
+ // changed ringer to vibrate
+ mDialog.onStateChangedH(vibrateState);
+
+ // expected: vibrate device
+ verify(mController).vibrate(any());
+ }
+
+ @Test
+ public void testNoVibrateOnRingerInitialization() {
+ final State initialUnsetState = new State();
+ initialUnsetState.ringerModeInternal = -1;
+
+ // ringer not initialized yet:
+ mDialog.onStateChangedH(initialUnsetState);
+
+ final State vibrateState = new State();
+ vibrateState.ringerModeInternal = AudioManager.RINGER_MODE_VIBRATE;
+
+ // changed ringer to vibrate
+ mDialog.onStateChangedH(vibrateState);
+
+ // shouldn't call vibrate
+ verify(mController, never()).vibrate(any());
+ }
+
/*
@Test
public void testContentDescriptions() {
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 915c2f6..613d28b 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -102,6 +102,7 @@
],
libs: [
"framework-tethering",
+ "framework-wifi",
],
jarjar_rules: "jarjar-rules.txt",
optimize: {
diff --git a/packages/Tethering/src/android/net/ip/NeighborPacketForwarder.java b/packages/Tethering/src/android/net/ip/NeighborPacketForwarder.java
index 084743d..73fc833 100644
--- a/packages/Tethering/src/android/net/ip/NeighborPacketForwarder.java
+++ b/packages/Tethering/src/android/net/ip/NeighborPacketForwarder.java
@@ -25,6 +25,7 @@
import static android.system.OsConstants.SOCK_RAW;
import android.net.util.InterfaceParams;
+import android.net.util.PacketReader;
import android.net.util.SocketUtils;
import android.net.util.TetheringUtils;
import android.os.Handler;
@@ -32,8 +33,6 @@
import android.system.Os;
import android.util.Log;
-import com.android.net.module.util.PacketReader;
-
import java.io.FileDescriptor;
import java.io.IOException;
import java.net.Inet6Address;
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
index fd9e360..b285849 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
@@ -15,6 +15,7 @@
*/
package com.android.networkstack.tethering;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
import static java.util.Arrays.asList;
@@ -23,7 +24,6 @@
import android.net.ConnectivityManager;
import android.net.IpPrefix;
import android.net.LinkAddress;
-import android.net.LinkProperties;
import android.net.Network;
import android.net.ip.IpServer;
import android.net.util.PrefixUtils;
@@ -90,16 +90,24 @@
/**
* Record a new upstream IpPrefix which may conflict with tethering downstreams.
- * The downstreams will be notified if a conflict is found.
+ * The downstreams will be notified if a conflict is found. When updateUpstreamPrefix is called,
+ * UpstreamNetworkState must have an already populated LinkProperties.
*/
- public void updateUpstreamPrefix(final Network network, final LinkProperties lp) {
- final ArrayList<IpPrefix> ipv4Prefixes = getIpv4Prefixes(lp.getAllLinkAddresses());
- if (ipv4Prefixes.isEmpty()) {
- removeUpstreamPrefix(network);
+ public void updateUpstreamPrefix(final UpstreamNetworkState ns) {
+ // Do not support VPN as upstream
+ if (ns.networkCapabilities != null && ns.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
+ removeUpstreamPrefix(ns.network);
return;
}
- mUpstreamPrefixMap.put(network, ipv4Prefixes);
+ final ArrayList<IpPrefix> ipv4Prefixes = getIpv4Prefixes(
+ ns.linkProperties.getAllLinkAddresses());
+ if (ipv4Prefixes.isEmpty()) {
+ removeUpstreamPrefix(ns.network);
+ return;
+ }
+
+ mUpstreamPrefixMap.put(ns.network, ipv4Prefixes);
handleMaybePrefixConflict(ipv4Prefixes);
}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 64d5025..474f4e8 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -1678,14 +1678,6 @@
}
}
- private void addUpstreamPrefixes(final UpstreamNetworkState ns) {
- mPrivateAddressCoordinator.updateUpstreamPrefix(ns.network, ns.linkProperties);
- }
-
- private void removeUpstreamPrefixes(final UpstreamNetworkState ns) {
- mPrivateAddressCoordinator.removeUpstreamPrefix(ns.network);
- }
-
@VisibleForTesting
void handleUpstreamNetworkMonitorCallback(int arg1, Object o) {
if (arg1 == UpstreamNetworkMonitor.NOTIFY_LOCAL_PREFIXES) {
@@ -1696,10 +1688,10 @@
final UpstreamNetworkState ns = (UpstreamNetworkState) o;
switch (arg1) {
case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
- addUpstreamPrefixes(ns);
+ mPrivateAddressCoordinator.updateUpstreamPrefix(ns);
break;
case UpstreamNetworkMonitor.EVENT_ON_LOST:
- removeUpstreamPrefixes(ns);
+ mPrivateAddressCoordinator.removeUpstreamPrefix(ns.network);
break;
}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
index 8e93c2e..7b6632c 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java
@@ -15,6 +15,10 @@
*/
package com.android.networkstack.tethering;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.TetheringManager.TETHERING_ETHERNET;
import static android.net.TetheringManager.TETHERING_USB;
import static android.net.TetheringManager.TETHERING_WIFI;
@@ -30,13 +34,12 @@
import android.content.Context;
import android.net.ConnectivityManager;
-import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.ip.IpServer;
-import android.net.util.NetworkConstants;
import android.net.util.PrefixUtils;
import androidx.test.filters.SmallTest;
@@ -48,13 +51,10 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.List;
-
@RunWith(AndroidJUnit4.class)
@SmallTest
public final class PrivateAddressCoordinatorTest {
- private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
- private static final String TEST_WIFI_IFNAME = "test_wlan0";
+ private static final String TEST_IFNAME = "test0";
@Mock private IpServer mHotspotIpServer;
@Mock private IpServer mUsbIpServer;
@@ -69,7 +69,8 @@
private final LinkAddress mLegacyWifiP2pAddress = new LinkAddress("192.168.49.1/24");
private final Network mWifiNetwork = new Network(1);
private final Network mMobileNetwork = new Network(2);
- private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork};
+ private final Network mVpnNetwork = new Network(3);
+ private final Network[] mAllNetworks = {mMobileNetwork, mWifiNetwork, mVpnNetwork};
private void setUpIpServers() throws Exception {
when(mUsbIpServer.interfaceType()).thenReturn(TETHERING_USB);
@@ -184,33 +185,25 @@
assertEquals("Fail to reselect available prefix: ", predefinedPrefix, allowUseFreePrefix);
}
- private LinkProperties buildUpstreamLinkProperties(boolean withIPv4, boolean withIPv6,
- boolean isMobile) {
- final String testIface;
- final String testIpv4Address;
- if (isMobile) {
- testIface = TEST_MOBILE_IFNAME;
- testIpv4Address = "10.0.0.1";
- } else {
- testIface = TEST_WIFI_IFNAME;
- testIpv4Address = "192.168.43.5";
- }
-
+ private UpstreamNetworkState buildUpstreamNetworkState(final Network network,
+ final LinkAddress v4Addr, final LinkAddress v6Addr, final NetworkCapabilities cap) {
final LinkProperties prop = new LinkProperties();
- prop.setInterfaceName(testIface);
+ prop.setInterfaceName(TEST_IFNAME);
+ if (v4Addr != null) prop.addLinkAddress(v4Addr);
- if (withIPv4) {
- prop.addLinkAddress(
- new LinkAddress(InetAddresses.parseNumericAddress(testIpv4Address),
- NetworkConstants.IPV4_ADDR_BITS));
+ if (v6Addr != null) prop.addLinkAddress(v6Addr);
+
+ return new UpstreamNetworkState(prop, cap, network);
+ }
+
+ private NetworkCapabilities makeNetworkCapabilities(final int transportType) {
+ final NetworkCapabilities cap = new NetworkCapabilities();
+ cap.addTransportType(transportType);
+ if (transportType == TRANSPORT_VPN) {
+ cap.removeCapability(NET_CAPABILITY_NOT_VPN);
}
- if (withIPv6) {
- prop.addLinkAddress(
- new LinkAddress(InetAddresses.parseNumericAddress("2001:db8::"),
- NetworkConstants.RFC7421_PREFIX_LENGTH));
- }
- return prop;
+ return cap;
}
@Test
@@ -220,53 +213,76 @@
final IpPrefix predefinedPrefix = new IpPrefix("192.168.43.0/24");
// Force always get subAddress "43.5" for conflict testing.
when(mPrivateAddressCoordinator.getRandomSubAddr()).thenReturn(fakeHotspotSubAddr);
- // 1. Enable hotspot with prefix 192.168.43.0/24
+ // - Enable hotspot with prefix 192.168.43.0/24
final LinkAddress hotspotAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
mHotspotIpServer);
final IpPrefix hotspotPrefix = PrefixUtils.asIpPrefix(hotspotAddr);
assertEquals("Wrong wifi prefix: ", predefinedPrefix, hotspotPrefix);
when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddr);
- // 2. Update v6 only mobile network, hotspot prefix should not be removed.
- List<String> testConflicts;
- final LinkProperties v6OnlyMobileProp = buildUpstreamLinkProperties(false, true, true);
- mPrivateAddressCoordinator.updateUpstreamPrefix(mMobileNetwork, v6OnlyMobileProp);
+ // - test mobile network with null NetworkCapabilities. Ideally this should not happen,
+ // just make sure no crash in this case.
+ final UpstreamNetworkState noCapUpstream = buildUpstreamNetworkState(mMobileNetwork,
+ new LinkAddress("10.0.0.8/24"), null, null);
+ mPrivateAddressCoordinator.updateUpstreamPrefix(noCapUpstream);
+ verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
+ // - test mobile upstream with no address.
+ final UpstreamNetworkState noAddress = buildUpstreamNetworkState(mMobileNetwork,
+ null, null, makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(noCapUpstream);
+ verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
+ // - Update v6 only mobile network, hotspot prefix should not be removed.
+ final UpstreamNetworkState v6OnlyMobile = buildUpstreamNetworkState(mMobileNetwork,
+ null, new LinkAddress("2001:db8::/64"),
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(v6OnlyMobile);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
mPrivateAddressCoordinator.removeUpstreamPrefix(mMobileNetwork);
- // 3. Update v4 only mobile network, hotspot prefix should not be removed.
- final LinkProperties v4OnlyMobileProp = buildUpstreamLinkProperties(true, false, true);
- mPrivateAddressCoordinator.updateUpstreamPrefix(mMobileNetwork, v4OnlyMobileProp);
+ // - Update v4 only mobile network, hotspot prefix should not be removed.
+ final UpstreamNetworkState v4OnlyMobile = buildUpstreamNetworkState(mMobileNetwork,
+ new LinkAddress("10.0.0.8/24"), null,
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyMobile);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- // 4. Update v4v6 mobile network, hotspot prefix should not be removed.
- final LinkProperties v4v6MobileProp = buildUpstreamLinkProperties(true, true, true);
- mPrivateAddressCoordinator.updateUpstreamPrefix(mMobileNetwork, v4v6MobileProp);
+ // - Update v4v6 mobile network, hotspot prefix should not be removed.
+ final UpstreamNetworkState v4v6Mobile = buildUpstreamNetworkState(mMobileNetwork,
+ new LinkAddress("10.0.0.8/24"), new LinkAddress("2001:db8::/64"),
+ makeNetworkCapabilities(TRANSPORT_CELLULAR));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(v4v6Mobile);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- // 5. Update v6 only wifi network, hotspot prefix should not be removed.
- final LinkProperties v6OnlyWifiProp = buildUpstreamLinkProperties(false, true, false);
- mPrivateAddressCoordinator.updateUpstreamPrefix(mWifiNetwork, v6OnlyWifiProp);
+ // - Update v6 only wifi network, hotspot prefix should not be removed.
+ final UpstreamNetworkState v6OnlyWifi = buildUpstreamNetworkState(mWifiNetwork,
+ null, new LinkAddress("2001:db8::/64"), makeNetworkCapabilities(TRANSPORT_WIFI));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(v6OnlyWifi);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork);
- // 6. Update v4 only wifi network, it conflict with hotspot prefix.
- final LinkProperties v4OnlyWifiProp = buildUpstreamLinkProperties(true, false, false);
- mPrivateAddressCoordinator.updateUpstreamPrefix(mWifiNetwork, v4OnlyWifiProp);
+ // - Update vpn network, it conflict with hotspot prefix but VPN networks are ignored.
+ final UpstreamNetworkState v4OnlyVpn = buildUpstreamNetworkState(mVpnNetwork,
+ new LinkAddress("192.168.43.5/24"), null, makeNetworkCapabilities(TRANSPORT_VPN));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyVpn);
+ verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
+ // - Update v4 only wifi network, it conflict with hotspot prefix.
+ final UpstreamNetworkState v4OnlyWifi = buildUpstreamNetworkState(mWifiNetwork,
+ new LinkAddress("192.168.43.5/24"), null, makeNetworkCapabilities(TRANSPORT_WIFI));
+ mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyWifi);
verify(mHotspotIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
reset(mHotspotIpServer);
- // 7. Restart hotspot again and its prefix is different previous.
+ // - Restart hotspot again and its prefix is different previous.
mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer);
final LinkAddress hotspotAddr2 = mPrivateAddressCoordinator.requestDownstreamAddress(
mHotspotIpServer);
final IpPrefix hotspotPrefix2 = PrefixUtils.asIpPrefix(hotspotAddr2);
assertNotEquals(hotspotPrefix, hotspotPrefix2);
when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddr2);
- mPrivateAddressCoordinator.updateUpstreamPrefix(mWifiNetwork, v4OnlyWifiProp);
+ mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyWifi);
verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT);
- // 7. Usb tethering can be enabled and its prefix is different with conflict one.
+ // - Usb tethering can be enabled and its prefix is different with conflict one.
final LinkAddress usbAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
mUsbIpServer);
final IpPrefix usbPrefix = PrefixUtils.asIpPrefix(usbAddr);
assertNotEquals(predefinedPrefix, usbPrefix);
assertNotEquals(hotspotPrefix2, usbPrefix);
when(mUsbIpServer.getAddress()).thenReturn(usbAddr);
- // 8. Disable wifi upstream, then wifi's prefix can be selected again.
+ // - Disable wifi upstream, then wifi's prefix can be selected again.
mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork);
final LinkAddress ethAddr = mPrivateAddressCoordinator.requestDownstreamAddress(
mEthernetIpServer);
diff --git a/packages/services/PacProcessor/Android.bp b/packages/services/PacProcessor/Android.bp
index 494a818..1fd972c 100644
--- a/packages/services/PacProcessor/Android.bp
+++ b/packages/services/PacProcessor/Android.bp
@@ -19,7 +19,6 @@
srcs: ["src/**/*.java"],
platform_apis: true,
certificate: "platform",
- jni_libs: ["libjni_pacprocessor"],
}
filegroup {
diff --git a/packages/services/PacProcessor/jni/Android.bp b/packages/services/PacProcessor/jni/Android.bp
deleted file mode 100644
index 0e7e101..0000000
--- a/packages/services/PacProcessor/jni/Android.bp
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (C) 2013 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.
-//
-
-cc_library_shared {
- name: "libjni_pacprocessor",
-
- srcs: [
- "jni_init.cpp",
- "com_android_pacprocessor_PacNative.cpp",
- ],
-
- shared_libs: [
- "libandroidfw",
- "libandroid_runtime",
- "liblog",
- "libutils",
- "libnativehelper",
- "libpac",
- ],
-
- cflags: [
- "-Wall",
- "-Werror",
- "-Wunused",
- "-Wunreachable-code",
- ],
- sanitize: {
- cfi: true,
- },
-}
diff --git a/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp b/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp
deleted file mode 100644
index d969c69..0000000
--- a/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#define LOG_TAG "PacProcessor"
-
-#include <stdlib.h>
-#include <string>
-
-#include <utils/Log.h>
-#include <utils/Mutex.h>
-#include "android_runtime/AndroidRuntime.h"
-
-#include "jni.h"
-#include <nativehelper/JNIHelp.h>
-
-#include "proxy_resolver_v8_wrapper.h"
-
-namespace android {
-
-ProxyResolverV8Handle* proxyResolver = NULL;
-bool pacSet = false;
-
-std::u16string jstringToString16(JNIEnv* env, jstring jstr) {
- const jchar* str = env->GetStringCritical(jstr, 0);
- std::u16string str16(reinterpret_cast<const char16_t*>(str),
- env->GetStringLength(jstr));
- env->ReleaseStringCritical(jstr, str);
- return str16;
-}
-
-jstring string16ToJstring(JNIEnv* env, std::u16string string) {
- const char16_t* str = string.data();
- size_t len = string.length();
-
- return env->NewString(reinterpret_cast<const jchar*>(str), len);
-}
-
-static jboolean com_android_pacprocessor_PacNative_createV8ParserNativeLocked(JNIEnv* /* env */,
- jobject) {
- if (proxyResolver == NULL) {
- proxyResolver = ProxyResolverV8Handle_new();
- pacSet = false;
- return JNI_FALSE;
- }
- return JNI_TRUE;
-}
-
-static jboolean com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked(JNIEnv* /* env */,
- jobject) {
- if (proxyResolver != NULL) {
- ProxyResolverV8Handle_delete(proxyResolver);
- proxyResolver = NULL;
- return JNI_FALSE;
- }
- return JNI_TRUE;
-}
-
-static jboolean com_android_pacprocessor_PacNative_setProxyScriptNativeLocked(JNIEnv* env, jobject,
- jstring script) {
- std::u16string script16 = jstringToString16(env, script);
-
- if (proxyResolver == NULL) {
- ALOGE("V8 Parser not started when setting PAC script");
- return JNI_TRUE;
- }
-
- if (ProxyResolverV8Handle_SetPacScript(proxyResolver, script16.data()) != OK) {
- ALOGE("Unable to set PAC script");
- return JNI_TRUE;
- }
- pacSet = true;
-
- return JNI_FALSE;
-}
-
-static jstring com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked(JNIEnv* env, jobject,
- jstring url, jstring host) {
- std::u16string url16 = jstringToString16(env, url);
- std::u16string host16 = jstringToString16(env, host);
-
- if (proxyResolver == NULL) {
- ALOGE("V8 Parser not initialized when running PAC script");
- return NULL;
- }
-
- if (!pacSet) {
- ALOGW("Attempting to run PAC with no script set");
- return NULL;
- }
-
- std::unique_ptr<char16_t, decltype(&free)> result = std::unique_ptr<char16_t, decltype(&free)>(
- ProxyResolverV8Handle_GetProxyForURL(proxyResolver, url16.data(), host16.data()), &free);
- if (result.get() == NULL) {
- ALOGE("Error Running PAC");
- return NULL;
- }
-
- std::u16string ret(result.get());
- jstring jret = string16ToJstring(env, ret);
-
- return jret;
-}
-
-static const JNINativeMethod gMethods[] = {
- { "createV8ParserNativeLocked", "()Z",
- (void*)com_android_pacprocessor_PacNative_createV8ParserNativeLocked},
- { "destroyV8ParserNativeLocked", "()Z",
- (void*)com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked},
- { "setProxyScriptNativeLocked", "(Ljava/lang/String;)Z",
- (void*)com_android_pacprocessor_PacNative_setProxyScriptNativeLocked},
- { "makeProxyRequestNativeLocked", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
- (void*)com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked},
-};
-
-int register_com_android_pacprocessor_PacNative(JNIEnv* env) {
- return jniRegisterNativeMethods(env, "com/android/pacprocessor/PacNative",
- gMethods, NELEM(gMethods));
-}
-
-} /* namespace android */
diff --git a/packages/services/PacProcessor/jni/jni_init.cpp b/packages/services/PacProcessor/jni/jni_init.cpp
deleted file mode 100644
index de844c8..0000000
--- a/packages/services/PacProcessor/jni/jni_init.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#define LOG_TAG "PacProcessor"
-
-#include <utils/Log.h>
-#include "jni.h"
-
-namespace android {
- extern int register_com_android_pacprocessor_PacNative(JNIEnv *env);
-}
-
-using namespace android;
-
-extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) {
- JNIEnv *env;
- if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
- ALOGE("ERROR: GetEnv failed");
- return -1;
- }
-
- register_com_android_pacprocessor_PacNative(env);
-
- return JNI_VERSION_1_6;
-}
diff --git a/packages/services/PacProcessor/src/com/android/pacprocessor/LibpacInterface.java b/packages/services/PacProcessor/src/com/android/pacprocessor/LibpacInterface.java
deleted file mode 100644
index 103ef781..0000000
--- a/packages/services/PacProcessor/src/com/android/pacprocessor/LibpacInterface.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.pacprocessor;
-
-/**
- * Common interface for both Android's and WebView's implementation of PAC processor.
- *
- * @hide
- */
-interface LibpacInterface {
- default boolean startPacSupport() {
- return true;
- }
-
- default boolean stopPacSupport() {
- return true;
- }
-
- boolean setCurrentProxyScript(String script);
- String makeProxyRequest(String url, String host);
-}
diff --git a/packages/services/PacProcessor/src/com/android/pacprocessor/PacNative.java b/packages/services/PacProcessor/src/com/android/pacprocessor/PacNative.java
deleted file mode 100644
index 9c0cfc2..0000000
--- a/packages/services/PacProcessor/src/com/android/pacprocessor/PacNative.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/**
- * Copyright (c) 2013, 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.pacprocessor;
-
-import android.util.Log;
-
-/**
- * @hide
- */
-public class PacNative implements LibpacInterface {
- private static final String TAG = "PacProxy";
-
- private static final PacNative sInstance = new PacNative();
-
- private String mCurrentPac;
-
- private boolean mIsActive;
-
- // Only make native calls from inside synchronized blocks.
- private native boolean createV8ParserNativeLocked();
- private native boolean destroyV8ParserNativeLocked();
-
- private native boolean setProxyScriptNativeLocked(String script);
-
- private native String makeProxyRequestNativeLocked(String url, String host);
-
- static {
- System.loadLibrary("jni_pacprocessor");
- }
-
- private PacNative() {
-
- }
-
- public static PacNative getInstance() {
- return sInstance;
- }
-
- @Override
- public synchronized boolean startPacSupport() {
- if (createV8ParserNativeLocked()) {
- Log.e(TAG, "Unable to Create v8 Proxy Parser.");
- return false;
- }
- mIsActive = true;
- return true;
- }
-
- @Override
- public synchronized boolean stopPacSupport() {
- if (mIsActive) {
- if (destroyV8ParserNativeLocked()) {
- Log.e(TAG, "Unable to Destroy v8 Proxy Parser.");
- return false;
- }
- mIsActive = false;
- }
- return true;
- }
-
- @Override
- public synchronized boolean setCurrentProxyScript(String script) {
- if (setProxyScriptNativeLocked(script)) {
- Log.e(TAG, "Unable to parse proxy script.");
- return false;
- }
- return true;
- }
-
- @Override
- public synchronized String makeProxyRequest(String url, String host) {
- String ret = makeProxyRequestNativeLocked(url, host);
- if ((ret == null) || (ret.length() == 0)) {
- Log.e(TAG, "v8 Proxy request failed.");
- ret = null;
- }
- return ret;
- }
-
- public synchronized boolean isActive() {
- return mIsActive;
- }
-}
diff --git a/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java b/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java
index 5a7de9f..46bda06 100644
--- a/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java
+++ b/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java
@@ -17,13 +17,14 @@
import android.app.Service;
import android.content.Intent;
-import android.content.res.Resources;
import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
+import android.webkit.PacProcessor;
+import com.android.internal.annotations.GuardedBy;
import com.android.net.IProxyService;
import java.net.MalformedURLException;
@@ -31,24 +32,21 @@
public class PacService extends Service {
private static final String TAG = "PacService";
- private static final boolean sUseWebViewPacProcessor = Resources.getSystem().getBoolean(
- com.android.internal.R.bool.config_useWebViewPacProcessor);
- private final LibpacInterface mLibpac = sUseWebViewPacProcessor
- ? PacWebView.getInstance()
- : PacNative.getInstance();
+ private Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ private final PacProcessor mPacProcessor = PacProcessor.getInstance();
private ProxyServiceStub mStub = new ProxyServiceStub();
@Override
public void onCreate() {
super.onCreate();
- mLibpac.startPacSupport();
}
@Override
public void onDestroy() {
- mLibpac.stopPacSupport();
super.onDestroy();
}
@@ -74,7 +72,10 @@
throw new IllegalArgumentException("Invalid host was passed");
}
}
- return mLibpac.makeProxyRequest(url, host);
+
+ synchronized (mLock) {
+ return mPacProcessor.findProxyForUrl(url);
+ }
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Invalid URL was passed");
}
@@ -86,7 +87,11 @@
Log.e(TAG, "Only system user is allowed to call setPacFile");
throw new SecurityException();
}
- mLibpac.setCurrentProxyScript(script);
+ synchronized (mLock) {
+ if (!mPacProcessor.setProxyScript(script)) {
+ Log.e(TAG, "Unable to parse proxy script.");
+ }
+ }
}
}
}
diff --git a/packages/services/PacProcessor/src/com/android/pacprocessor/PacWebView.java b/packages/services/PacProcessor/src/com/android/pacprocessor/PacWebView.java
deleted file mode 100644
index 4dd00f1..0000000
--- a/packages/services/PacProcessor/src/com/android/pacprocessor/PacWebView.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.pacprocessor;
-
-import android.util.Log;
-import android.webkit.PacProcessor;
-
-/**
- * @hide
- */
-public class PacWebView implements LibpacInterface {
- private static final String TAG = "PacWebView";
-
- private static final PacWebView sInstance = new PacWebView();
- private PacProcessor mProcessor = PacProcessor.getInstance();
-
- public static PacWebView getInstance() {
- return sInstance;
- }
-
- @Override
- public synchronized boolean setCurrentProxyScript(String script) {
- if (!mProcessor.setProxyScript(script)) {
- Log.e(TAG, "Unable to parse proxy script.");
- return false;
- }
- return true;
- }
-
- @Override
- public synchronized String makeProxyRequest(String url, String host) {
- return mProcessor.findProxyForUrl(url);
- }
-}
diff --git a/services/Android.bp b/services/Android.bp
index ef52c2a..25a0d7e 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -3,6 +3,12 @@
plugins: [
"error_prone_android_framework",
],
+ errorprone: {
+ javacflags: [
+ "-Xep:AndroidFrameworkCompatChange:ERROR",
+ "-Xep:AndroidFrameworkUid:ERROR",
+ ],
+ },
}
filegroup {
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 6ca99d1..40b1718 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -317,7 +317,7 @@
AndroidFuture<Association> future = new AndroidFuture<>();
service.startDiscovery(request, callingPackage, callback, future);
return future;
- }).whenComplete(uncheckExceptions((association, err) -> {
+ }).cancelTimeout().whenComplete(uncheckExceptions((association, err) -> {
if (err == null) {
addAssociation(association);
} else {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index da5d1c2..8a1baf2 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -136,6 +136,8 @@
import android.net.metrics.NetworkEvent;
import android.net.netlink.InetDiagMessage;
import android.net.shared.PrivateDnsConfig;
+import android.net.util.LinkPropertiesUtils.CompareOrUpdateResult;
+import android.net.util.LinkPropertiesUtils.CompareResult;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.NetdService;
import android.os.Binder;
@@ -193,8 +195,6 @@
import com.android.internal.util.LocationPermissionChecker;
import com.android.internal.util.MessageUtils;
import com.android.internal.util.XmlUtils;
-import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult;
-import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.AutodestructReference;
import com.android.server.connectivity.DataConnectionStats;
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index d907505..4a1820a 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -25,6 +25,7 @@
import android.net.nsd.INsdManager;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
+import android.net.util.nsd.DnsSdTxtRecord;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
@@ -41,7 +42,6 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
-import com.android.net.module.util.DnsSdTxtRecord;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 6d77486..7775354 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -18,14 +18,10 @@
import static android.Manifest.permission.ACCESS_MTP;
import static android.Manifest.permission.INSTALL_PACKAGES;
-import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
-import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
-import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.OP_LEGACY_STORAGE;
import static android.app.AppOpsManager.OP_MANAGE_EXTERNAL_STORAGE;
-import static android.app.AppOpsManager.OP_READ_EXTERNAL_STORAGE;
import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES;
import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
@@ -137,7 +133,6 @@
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.AppFuseMount;
@@ -153,7 +148,6 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
-import com.android.server.SystemService.TargetUser;
import com.android.server.pm.Installer;
import com.android.server.storage.AppFuseBridge;
import com.android.server.storage.StorageSessionController;
@@ -2523,19 +2517,6 @@
abortIdleMaint(null);
}
- private void remountUidExternalStorage(int uid, int mode) {
- if (uid == Process.SYSTEM_UID) {
- // No need to remount uid for system because it has all access anyways
- return;
- }
-
- try {
- mVold.remountUid(uid, mode);
- } catch (Exception e) {
- Slog.wtf(TAG, e);
- }
- }
-
@Override
public void setDebugFlags(int flags, int mask) {
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
@@ -3847,21 +3828,6 @@
}
}
- private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() {
- @Override
- public void opChanged(int op, int uid, String packageName) throws RemoteException {
- if (!ENABLE_ISOLATED_STORAGE) return;
-
- int mountMode = getMountMode(uid, packageName);
- boolean isUidActive = LocalServices.getService(ActivityManagerInternal.class)
- .getUidProcessState(uid) != PROCESS_STATE_NONEXISTENT;
-
- if (isUidActive) {
- remountUidExternalStorage(uid, mountMode);
- }
- }
- };
-
private void addObbStateLocked(ObbState obbState) throws RemoteException {
final IBinder binder = obbState.getBinder();
List<ObbState> obbStates = mObbMounts.get(binder);
@@ -4236,19 +4202,9 @@
}
// Determine if caller is holding runtime permission
- final boolean hasRead = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
- uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE);
final boolean hasWrite = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE);
- // We're only willing to give out broad access if they also hold
- // runtime permission; this is a firm CDD requirement
- final boolean hasFull = mIPackageManager.checkUidPermission(WRITE_MEDIA_STORAGE,
- uid) == PERMISSION_GRANTED;
- if (hasFull && hasWrite) {
- return Zygote.MOUNT_EXTERNAL_FULL;
- }
-
// We're only willing to give out installer access if they also hold
// runtime permission; this is a firm CDD requirement
final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES,
@@ -4268,19 +4224,7 @@
if ((hasInstall || hasInstallOp) && hasWrite) {
return Zygote.MOUNT_EXTERNAL_INSTALLER;
}
-
- // Otherwise we're willing to give out sandboxed or non-sandboxed if
- // they hold the runtime permission
- boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE,
- uid, packageName) == MODE_ALLOWED;
-
- if (hasLegacy && hasWrite) {
- return Zygote.MOUNT_EXTERNAL_WRITE;
- } else if (hasLegacy && hasRead) {
- return Zygote.MOUNT_EXTERNAL_READ;
- } else {
- return Zygote.MOUNT_EXTERNAL_DEFAULT;
- }
+ return Zygote.MOUNT_EXTERNAL_DEFAULT;
} catch (RemoteException e) {
// Should not happen
}
@@ -4570,12 +4514,6 @@
}
@Override
- public void onExternalStoragePolicyChanged(int uid, String packageName) {
- final int mountMode = getExternalStorageMountMode(uid, packageName);
- remountUidExternalStorage(uid, mountMode);
- }
-
- @Override
public int getExternalStorageMountMode(int uid, String packageName) {
if (ENABLE_ISOLATED_STORAGE) {
return getMountMode(uid, packageName);
@@ -4720,16 +4658,6 @@
updateLegacyStorageApps(packageName, uid, mode == MODE_ALLOWED);
return;
}
-
- if (mode == MODE_ALLOWED && (code == OP_READ_EXTERNAL_STORAGE
- || code == OP_WRITE_EXTERNAL_STORAGE
- || code == OP_REQUEST_INSTALL_PACKAGES)) {
- final UserManagerInternal userManagerInternal =
- LocalServices.getService(UserManagerInternal.class);
- if (userManagerInternal.isUserInitialized(UserHandle.getUserId(uid))) {
- onExternalStoragePolicyChanged(uid, packageName);
- }
- }
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ffdcd15..2feb470 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -153,7 +153,6 @@
import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IApplicationThread;
-import android.app.IAssistDataReceiver;
import android.app.IInstrumentationWatcher;
import android.app.INotificationManager;
import android.app.IProcessObserver;
@@ -286,7 +285,6 @@
import android.util.proto.ProtoUtils;
import android.view.Display;
import android.view.Gravity;
-import android.view.IRecentsAnimationRunner;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
@@ -2840,18 +2838,6 @@
return mActivityTaskManager.startActivityFromRecents(taskId, bOptions);
}
- @Override
- public void startRecentsActivity(Intent intent, IAssistDataReceiver assistDataReceiver,
- IRecentsAnimationRunner recentsAnimationRunner) {
- mActivityTaskManager.startRecentsActivity(
- intent, assistDataReceiver, recentsAnimationRunner);
- }
-
- @Override
- public void cancelRecentsAnimation(boolean restoreHomeStackPosition) {
- mActivityTaskManager.cancelRecentsAnimation(restoreHomeStackPosition);
- }
-
/**
* This is the internal entry point for handling Activity.finish().
*
@@ -8198,12 +8184,10 @@
} finally {
Binder.restoreCallingIdentity(identity);
}
- if (uid == Process.INVALID_UID) {
- return Process.INVALID_UID;
- }
+ // If the uid is Process.INVALID_UID, the below 'if' check will be always true
if (UserHandle.getAppId(uid) != UserHandle.getAppId(callingUid)) {
// Requires the DUMP permission if the target package doesn't belong
- // to the caller.
+ // to the caller or it doesn't exist.
enforceCallingPermission(android.Manifest.permission.DUMP, function);
}
return uid;
@@ -16492,7 +16476,7 @@
@Override
public int getStorageMountMode(int pid, int uid) {
if (uid == SHELL_UID || uid == ROOT_UID) {
- return Zygote.MOUNT_EXTERNAL_FULL;
+ return Zygote.MOUNT_EXTERNAL_DEFAULT;
}
synchronized (mPidsSelfLocked) {
final ProcessRecord pr = mPidsSelfLocked.get(pid);
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 692b3f1..b6010d9 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -33,7 +33,6 @@
import android.telephony.TelephonyManager;
import android.util.IntArray;
import android.util.Slog;
-import android.util.TimeUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BatteryStatsImpl;
@@ -607,49 +606,11 @@
}
wasReset = true;
} else {
- final long totalActiveTimeMs = txTimeMs + rxTimeMs;
- long maxExpectedIdleTimeMs;
- if (totalActiveTimeMs > timePeriodMs) {
- // Cap the max idle time at zero since the active time consumed the whole time
- maxExpectedIdleTimeMs = 0;
- if (totalActiveTimeMs > timePeriodMs + MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS) {
- StringBuilder sb = new StringBuilder();
- sb.append("Total Active time ");
- TimeUtils.formatDuration(totalActiveTimeMs, sb);
- sb.append(" is longer than sample period ");
- TimeUtils.formatDuration(timePeriodMs, sb);
- sb.append(".\n");
- sb.append("Previous WiFi snapshot: ").append("idle=");
- TimeUtils.formatDuration(lastIdleMs, sb);
- sb.append(" rx=");
- TimeUtils.formatDuration(lastRxMs, sb);
- sb.append(" tx=");
- TimeUtils.formatDuration(lastTxMs, sb);
- sb.append(" e=").append(lastEnergy);
- sb.append("\n");
- sb.append("Current WiFi snapshot: ").append("idle=");
- TimeUtils.formatDuration(latest.getControllerIdleDurationMillis(), sb);
- sb.append(" rx=");
- TimeUtils.formatDuration(latest.getControllerRxDurationMillis(), sb);
- sb.append(" tx=");
- TimeUtils.formatDuration(latest.getControllerTxDurationMillis(), sb);
- sb.append(" e=").append(latest.getControllerEnergyUsedMicroJoules());
- Slog.wtf(TAG, sb.toString());
- }
- } else {
- maxExpectedIdleTimeMs = timePeriodMs - totalActiveTimeMs;
- }
// These times seem to be the most reliable.
deltaControllerTxDurationMillis = txTimeMs;
deltaControllerRxDurationMillis = rxTimeMs;
deltaControllerScanDurationMillis = scanTimeMs;
- // WiFi calculates the idle time as a difference from the on time and the various
- // Rx + Tx times. There seems to be some missing time there because this sometimes
- // becomes negative. Just cap it at 0 and ensure that it is less than the expected idle
- // time from the difference in timestamps.
- // b/21613534
- deltaControllerIdleDurationMillis =
- Math.min(maxExpectedIdleTimeMs, Math.max(0, idleTimeMs));
+ deltaControllerIdleDurationMillis = idleTimeMs;
deltaControllerEnergyUsedMicroJoules =
Math.max(0, latest.getControllerEnergyUsedMicroJoules() - lastEnergy);
wasReset = false;
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index dbf91ee..529c651 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.app.ActivityThread;
+import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
@@ -223,16 +224,17 @@
@VisibleForTesting
void populateSettings(Bundle snapshot, Map<String, Class<?>> map) {
- Context context = mActivityManagerService.mContext;
+ final Context context = mActivityManagerService.mContext;
+ final ContentResolver cr = context.getContentResolver();
for (Map.Entry<String, Class<?>> entry : map.entrySet()) {
String setting = entry.getKey();
final String value;
if (map == sSecureSettingToTypeMap) {
- value = Settings.Secure.getString(context.getContentResolver(), setting);
+ value = Settings.Secure.getStringForUser(cr, setting, cr.getUserId());
} else if (map == sSystemSettingToTypeMap) {
- value = Settings.System.getString(context.getContentResolver(), setting);
+ value = Settings.System.getStringForUser(cr, setting, cr.getUserId());
} else {
- value = Settings.Global.getString(context.getContentResolver(), setting);
+ value = Settings.Global.getString(cr, setting);
}
if (value == null) {
snapshot.remove(setting);
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 5e65563..ed47616d9 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -92,7 +92,6 @@
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
-import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
import android.system.Os;
import android.text.TextUtils;
@@ -1780,14 +1779,10 @@
final IPackageManager pm = AppGlobals.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName,
MATCH_DIRECT_BOOT_AUTO, app.userId);
- if (StorageManager.hasIsolatedStorage() && mountExtStorageFull) {
- mountExternal = Zygote.MOUNT_EXTERNAL_FULL;
- } else {
- StorageManagerInternal storageManagerInternal = LocalServices.getService(
- StorageManagerInternal.class);
- mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
- app.info.packageName);
- }
+ StorageManagerInternal storageManagerInternal = LocalServices.getService(
+ StorageManagerInternal.class);
+ mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
+ app.info.packageName);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
@@ -1918,7 +1913,9 @@
String instructionSet = null;
if (app.info.primaryCpuAbi != null) {
- instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
+ // If ABI override is specified, use the isa derived from the value of ABI override.
+ // Otherwise, use the isa derived from primary ABI
+ instructionSet = VMRuntime.getInstructionSet(requiredAbi);
}
app.gids = gids;
@@ -1927,7 +1924,7 @@
// If instructionSet is non-null, this indicates that the system_server is spawning a
// process with an ISA that may be different from its own. System (kernel and hardware)
- // compatililty for these features is checked in the decideTaggingLevel in the
+ // compatibility for these features is checked in the decideTaggingLevel in the
// system_server process (not the child process). As both MTE and TBI are only supported
// in aarch64, we can simply ensure that the new process is also aarch64. This prevents
// the mismatch where a 64-bit system server spawns a 32-bit child that thinks it should
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index c1777b8..7dbb39e 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1709,24 +1709,13 @@
if (Process.isIsolated(uid)) {
return Zygote.MOUNT_EXTERNAL_NONE;
}
- if (noteOperation(AppOpsManager.OP_READ_EXTERNAL_STORAGE, uid,
- packageName, null, true, "External storage policy", true)
- != AppOpsManager.MODE_ALLOWED) {
- return Zygote.MOUNT_EXTERNAL_NONE;
- }
- if (noteOperation(AppOpsManager.OP_WRITE_EXTERNAL_STORAGE, uid,
- packageName, null, true, "External storage policy", true)
- != AppOpsManager.MODE_ALLOWED) {
- return Zygote.MOUNT_EXTERNAL_READ;
- }
- return Zygote.MOUNT_EXTERNAL_WRITE;
+ return Zygote.MOUNT_EXTERNAL_DEFAULT;
}
@Override
public boolean hasExternalStorage(int uid, String packageName) {
final int mountMode = getMountMode(uid, packageName);
- return mountMode == Zygote.MOUNT_EXTERNAL_READ
- || mountMode == Zygote.MOUNT_EXTERNAL_WRITE;
+ return mountMode != Zygote.MOUNT_EXTERNAL_NONE;
}
});
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 4be596d..ff410fc 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -18,19 +18,26 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
import android.app.TaskStackListener;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.os.RemoteException;
import android.security.KeyStore;
+import android.util.EventLog;
import android.util.Slog;
+import com.android.server.biometrics.Utils;
+
import java.util.ArrayList;
+import java.util.List;
/**
* A class to keep track of the authentication state for a given client.
@@ -136,7 +143,54 @@
pm.incrementAuthForUser(getTargetUserId(), authenticated);
}
+ // Ensure authentication only succeeds if the client activity is on top or is keyguard.
+ boolean isBackgroundAuth = false;
+ if (authenticated && !Utils.isKeyguard(getContext(), getOwnerString())) {
+ try {
+ final List<ActivityManager.RunningTaskInfo> tasks =
+ mActivityTaskManager.getTasks(1);
+ if (tasks == null || tasks.isEmpty()) {
+ Slog.e(TAG, "No running tasks reported");
+ isBackgroundAuth = true;
+ } else {
+ final ComponentName topActivity = tasks.get(0).topActivity;
+ if (topActivity == null) {
+ Slog.e(TAG, "Unable to get top activity");
+ isBackgroundAuth = true;
+ } else {
+ final String topPackage = topActivity.getPackageName();
+ if (!topPackage.contentEquals(getOwnerString())) {
+ Slog.e(TAG, "Background authentication detected, top: " + topPackage
+ + ", client: " + this);
+ isBackgroundAuth = true;
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to get running tasks", e);
+ isBackgroundAuth = true;
+ }
+ }
+
+ // Fail authentication if we can't confirm the client activity is on top.
+ if (isBackgroundAuth) {
+ Slog.e(TAG, "Failing possible background authentication");
+ authenticated = false;
+
+ // SafetyNet logging for exploitation attempts of b/159249069.
+ final ApplicationInfo appInfo = getContext().getApplicationInfo();
+ EventLog.writeEvent(0x534e4554, "159249069", appInfo != null ? appInfo.uid : -1,
+ "Attempted background authentication");
+ }
+
if (authenticated) {
+ // SafetyNet logging for b/159249069 if constraint is violated.
+ if (isBackgroundAuth) {
+ final ApplicationInfo appInfo = getContext().getApplicationInfo();
+ EventLog.writeEvent(0x534e4554, "159249069", appInfo != null ? appInfo.uid : -1,
+ "Successful background authentication!");
+ }
+
mAlreadyDone = true;
if (listener != null) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
index 588e865..ce2d340 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
@@ -28,6 +28,7 @@
import android.os.ServiceManager;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
import java.io.PrintWriter;
@@ -37,9 +38,9 @@
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Date;
+import java.util.Deque;
import java.util.List;
import java.util.Locale;
-import java.util.Queue;
/**
* A scheduler for biometric HAL operations. Maintains a queue of {@link ClientMonitor} operations,
@@ -53,7 +54,8 @@
/**
* Contains all the necessary information for a HAL operation.
*/
- private static final class Operation {
+ @VisibleForTesting
+ static final class Operation {
/**
* The operation is added to the list of pending operations and waiting for its turn.
@@ -176,8 +178,8 @@
@NonNull private final IBiometricService mBiometricService;
@NonNull private final Handler mHandler = new Handler(Looper.getMainLooper());
@NonNull private final InternalCallback mInternalCallback;
- @NonNull private final Queue<Operation> mPendingOperations;
- @Nullable private Operation mCurrentOperation;
+ @VisibleForTesting @NonNull final Deque<Operation> mPendingOperations;
+ @VisibleForTesting @Nullable Operation mCurrentOperation;
@NonNull private final ArrayDeque<CrashState> mCrashStates;
// Internal callback, notified when an operation is complete. Notifies the requester
@@ -226,6 +228,18 @@
}
}
+ @VisibleForTesting
+ BiometricScheduler(@NonNull String tag,
+ @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
+ @NonNull IBiometricService biometricService) {
+ mBiometricTag = tag;
+ mInternalCallback = new InternalCallback();
+ mGestureAvailabilityDispatcher = gestureAvailabilityDispatcher;
+ mPendingOperations = new ArrayDeque<>();
+ mBiometricService = biometricService;
+ mCrashStates = new ArrayDeque<>();
+ }
+
/**
* Creates a new scheduler.
* @param tag for the specific instance of the scheduler. Should be unique.
@@ -234,13 +248,8 @@
*/
public BiometricScheduler(@NonNull String tag,
@Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
- mBiometricTag = tag;
- mInternalCallback = new InternalCallback();
- mGestureAvailabilityDispatcher = gestureAvailabilityDispatcher;
- mPendingOperations = new ArrayDeque<>();
- mBiometricService = IBiometricService.Stub.asInterface(
- ServiceManager.getService(Context.BIOMETRIC_SERVICE));
- mCrashStates = new ArrayDeque<>();
+ this(tag, gestureAvailabilityDispatcher, IBiometricService.Stub.asInterface(
+ ServiceManager.getService(Context.BIOMETRIC_SERVICE)));
}
/**
@@ -295,9 +304,50 @@
// to arrive at the head of the queue, before pinging it to start.
final boolean shouldStartNow = currentClient.getCookie() == 0;
if (shouldStartNow) {
- Slog.d(getTag(), "[Starting] " + mCurrentOperation);
- currentClient.start(getInternalCallback());
- mCurrentOperation.state = Operation.STATE_STARTED;
+ if (mCurrentOperation.clientMonitor.getFreshDaemon() == null) {
+ // Note down current length of queue
+ final int pendingOperationsLength = mPendingOperations.size();
+ final Operation lastOperation = mPendingOperations.peekLast();
+ Slog.e(getTag(), "[Unable To Start] " + mCurrentOperation
+ + ". Last pending operation: " + lastOperation);
+
+ // For current operations, 1) unableToStart, which notifies the caller-side, then
+ // 2) notify operation's callback, to notify applicable system service that the
+ // operation failed.
+ mCurrentOperation.clientMonitor.unableToStart();
+ if (mCurrentOperation.mClientCallback != null) {
+ mCurrentOperation.mClientCallback
+ .onClientFinished(mCurrentOperation.clientMonitor, false /* success */);
+ }
+
+ // Then for each operation currently in the pending queue at the time of this
+ // failure, do the same as above. Otherwise, it's possible that something like
+ // setActiveUser fails, but then authenticate (for the wrong user) is invoked.
+ for (int i = 0; i < pendingOperationsLength; i++) {
+ final Operation operation = mPendingOperations.pollFirst();
+ if (operation == null) {
+ Slog.e(getTag(), "Null operation, index: " + i
+ + ", expected length: " + pendingOperationsLength);
+ break;
+ }
+ operation.clientMonitor.unableToStart();
+ if (operation.mClientCallback != null) {
+ operation.mClientCallback.onClientFinished(operation.clientMonitor,
+ false /* success */);
+ }
+ Slog.w(getTag(), "[Aborted Operation] " + operation);
+ }
+
+ // It's possible that during cleanup a new set of operations came in. We can try to
+ // run these. A single request from the manager layer to the service layer may
+ // actually be multiple operations (i.e. updateActiveUser + authenticate).
+ mCurrentOperation = null;
+ startNextOperationIfIdle();
+ } else {
+ Slog.d(getTag(), "[Starting] " + mCurrentOperation);
+ currentClient.start(getInternalCallback());
+ mCurrentOperation.state = Operation.STATE_STARTED;
+ }
} else {
try {
mBiometricService.onReadyForAuthentication(currentClient.getCookie());
@@ -338,9 +388,21 @@
return;
}
- Slog.d(getTag(), "[Starting] Prepared client: " + mCurrentOperation);
- mCurrentOperation.state = Operation.STATE_STARTED;
- mCurrentOperation.clientMonitor.start(getInternalCallback());
+ if (mCurrentOperation.clientMonitor.getFreshDaemon() == null) {
+ Slog.e(getTag(), "[Unable To Start] Prepared client: " + mCurrentOperation);
+ // This is BiometricPrompt trying to auth but something's wrong with the HAL.
+ mCurrentOperation.clientMonitor.unableToStart();
+ if (mCurrentOperation.mClientCallback != null) {
+ mCurrentOperation.mClientCallback.onClientFinished(mCurrentOperation.clientMonitor,
+ false /* success */);
+ }
+ mCurrentOperation = null;
+ startNextOperationIfIdle();
+ } else {
+ Slog.d(getTag(), "[Starting] Prepared client: " + mCurrentOperation);
+ mCurrentOperation.state = Operation.STATE_STARTED;
+ mCurrentOperation.clientMonitor.start(getInternalCallback());
+ }
}
/**
diff --git a/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java
index 92c498c..bac944f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java
@@ -27,8 +27,6 @@
private static final String TAG = "GenerateChallengeClient";
- protected long mChallenge;
-
public GenerateChallengeClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
@NonNull String owner, int sensorId) {
@@ -51,12 +49,5 @@
super.start(callback);
startHalOperation();
- try {
- getListener().onChallengeGenerated(getSensorId(), mChallenge);
- mCallback.onClientFinished(this, true /* success */);
- } catch (RemoteException e) {
- Slog.e(TAG, "Remote exception", e);
- mCallback.onClientFinished(this, false /* success */);
- }
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
index bff0c3c..c2d4c15 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
@@ -48,6 +48,7 @@
import android.util.Slog;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.AcquisitionClient;
@@ -278,14 +279,13 @@
}
};
+ @VisibleForTesting
Face10(@NonNull Context context, int sensorId,
@BiometricManager.Authenticators.Types int strength,
- @NonNull LockoutResetDispatcher lockoutResetDispatcher) {
- final boolean supportsSelfIllumination = context.getResources()
- .getBoolean(R.bool.config_faceAuthSupportsSelfIllumination);
- final int maxTemplatesAllowed = context.getResources()
- .getInteger(R.integer.config_faceMaxTemplatesPerUser);
- mFaceSensorProperties = new FaceSensorPropertiesInternal(sensorId, strength,
+ @NonNull LockoutResetDispatcher lockoutResetDispatcher,
+ boolean supportsSelfIllumination, int maxTemplatesAllowed) {
+ mFaceSensorProperties = new FaceSensorPropertiesInternal(sensorId,
+ Utils.authenticatorStrengthToPropertyStrength(strength),
maxTemplatesAllowed, false /* supportsFaceDetect */, supportsSelfIllumination);
mContext = context;
mSensorId = sensorId;
@@ -305,6 +305,14 @@
}
}
+ Face10(@NonNull Context context, int sensorId,
+ @BiometricManager.Authenticators.Types int strength,
+ @NonNull LockoutResetDispatcher lockoutResetDispatcher) {
+ this(context, sensorId, strength, lockoutResetDispatcher,
+ context.getResources().getBoolean(R.bool.config_faceAuthSupportsSelfIllumination),
+ context.getResources().getInteger(R.integer.config_faceMaxTemplatesPerUser));
+ }
+
@Override
public void serviceDied(long cookie) {
Slog.e(TAG, "HAL died");
@@ -511,19 +519,17 @@
@NonNull String opPackageName) {
mHandler.post(() -> {
if (mCurrentChallengeOwner != null) {
- Slog.w(TAG, "Current challenge owner: " + mCurrentChallengeOwner
- + ", interrupted by: " + opPackageName);
final ClientMonitorCallbackConverter listener =
mCurrentChallengeOwner.getListener();
- if (listener == null) {
- Slog.w(TAG, "Null listener, skip sending interruption callback");
- return;
- }
-
- try {
- listener.onChallengeInterrupted(mSensorId);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to notify challenge interrupted", e);
+ Slog.w(TAG, "Current challenge owner: " + mCurrentChallengeOwner
+ + ", listener: " + listener
+ + ", interrupted by: " + opPackageName);
+ if (listener != null) {
+ try {
+ listener.onChallengeInterrupted(mSensorId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to notify challenge interrupted", e);
+ }
}
}
@@ -547,7 +553,8 @@
void scheduleRevokeChallenge(@NonNull IBinder token, @NonNull String owner) {
mHandler.post(() -> {
- if (!mCurrentChallengeOwner.getOwnerString().contentEquals(owner)) {
+ if (mCurrentChallengeOwner != null &&
+ !mCurrentChallengeOwner.getOwnerString().contentEquals(owner)) {
Slog.e(TAG, "scheduleRevokeChallenge, package: " + owner
+ " attempting to revoke challenge owned by: "
+ mCurrentChallengeOwner.getOwnerString());
@@ -566,6 +573,13 @@
return;
}
+ if (mCurrentChallengeOwner == null) {
+ // Can happen if revoke is incorrectly called, for example without a
+ // preceding generateChallenge
+ Slog.w(TAG, "Current challenge owner is null");
+ return;
+ }
+
final FaceGenerateChallengeClient previousChallengeOwner =
mCurrentChallengeOwner.getInterruptedClient();
mCurrentChallengeOwner = null;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceGenerateChallengeClient.java
index ba401f2..406a7cc 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceGenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceGenerateChallengeClient.java
@@ -59,7 +59,14 @@
@Override
protected void startHalOperation() {
try {
- mChallenge = getFreshDaemon().generateChallenge(CHALLENGE_TIMEOUT_SEC).value;
+ final long challenge = getFreshDaemon().generateChallenge(CHALLENGE_TIMEOUT_SEC).value;
+ try {
+ getListener().onChallengeGenerated(getSensorId(), challenge);
+ mCallback.onClientFinished(this, true /* success */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ mCallback.onClientFinished(this, false /* success */);
+ }
} catch (RemoteException e) {
Slog.e(TAG, "generateChallenge failed", e);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java
index abaaac5..5169c7d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java
@@ -45,7 +45,14 @@
@Override
protected void startHalOperation() {
try {
- mChallenge = getFreshDaemon().preEnroll();
+ final long challenge = getFreshDaemon().preEnroll();
+ try {
+ getListener().onChallengeGenerated(getSensorId(), challenge);
+ mCallback.onClientFinished(this, true /* success */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ mCallback.onClientFinished(this, false /* success */);
+ }
} catch (RemoteException e) {
Slog.e(TAG, "preEnroll failed", e);
}
diff --git a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
index fa03e59..62630300 100644
--- a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
+++ b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
@@ -60,12 +60,12 @@
import android.net.ipsec.ike.TunnelModeChildSessionParams;
import android.net.ipsec.ike.exceptions.IkeException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
+import android.net.util.IpRange;
import android.system.OsConstants;
import android.util.Log;
import com.android.internal.net.VpnProfile;
import com.android.internal.util.HexDump;
-import com.android.net.module.util.IpRange;
import java.net.Inet4Address;
import java.net.Inet6Address;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index bb6f14c..96679c3 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -16,6 +16,8 @@
package com.android.server.hdmi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.tv.cec.V1_0.CecMessage;
import android.hardware.tv.cec.V1_0.HotplugEvent;
@@ -774,6 +776,7 @@
private IHdmiCec mHdmiCec;
private final Object mLock = new Object();
private int mPhysicalAddress = INVALID_PHYSICAL_ADDRESS;
+ @Nullable private HdmiCecCallback mCallback;
@Override
public String nativeInit() {
@@ -782,7 +785,7 @@
boolean connectToHal() {
try {
- mHdmiCec = IHdmiCec.getService();
+ mHdmiCec = IHdmiCec.getService(true);
try {
mHdmiCec.linkToDeath(this, HDMI_CEC_HAL_DEATH_COOKIE);
} catch (RemoteException e) {
@@ -796,7 +799,8 @@
}
@Override
- public void setCallback(HdmiCecCallback callback) {
+ public void setCallback(@NonNull HdmiCecCallback callback) {
+ mCallback = callback;
try {
mHdmiCec.setCallback(callback);
} catch (RemoteException e) {
@@ -936,6 +940,10 @@
if (cookie == HDMI_CEC_HAL_DEATH_COOKIE) {
HdmiLogger.error("Service died cookie : " + cookie + "; reconnecting");
connectToHal();
+ // Reconnect the callback
+ if (mCallback != null) {
+ setCallback(mCallback);
+ }
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index 68473c1..29bdd6c 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -379,7 +379,8 @@
assertRunOnServiceThread();
if (reason == mService.INITIATED_BY_ENABLE_CEC) {
mService.setAndBroadcastActiveSource(mService.getPhysicalAddress(),
- getDeviceInfo().getDeviceType(), Constants.ADDR_BROADCAST);
+ getDeviceInfo().getDeviceType(), Constants.ADDR_BROADCAST,
+ "HdmiCecLocalDeviceAudioSystem#onAddressAllocated()");
}
mService.sendCecCommand(
HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
@@ -1324,7 +1325,8 @@
if (getRoutingPort() == Constants.CEC_SWITCH_HOME && mService.isPlaybackDevice()) {
routeToInputFromPortId(Constants.CEC_SWITCH_HOME);
mService.setAndBroadcastActiveSourceFromOneDeviceType(
- message.getSource(), mService.getPhysicalAddress());
+ message.getSource(), mService.getPhysicalAddress(),
+ "HdmiCecLocalDeviceAudioSystem#handleRoutingChangeAndInformationForSwitch()");
return;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 6e6d848..6257032 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -16,6 +16,7 @@
package com.android.server.hdmi;
+import android.annotation.CallSuper;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.IHdmiControlCallback;
@@ -96,7 +97,8 @@
assertRunOnServiceThread();
if (reason == mService.INITIATED_BY_ENABLE_CEC) {
mService.setAndBroadcastActiveSource(mService.getPhysicalAddress(),
- getDeviceInfo().getDeviceType(), Constants.ADDR_BROADCAST);
+ getDeviceInfo().getDeviceType(), Constants.ADDR_BROADCAST,
+ "HdmiCecLocalDevicePlayback#onAddressAllocated()");
}
mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
mAddress, mService.getPhysicalAddress(), mDeviceType));
@@ -165,7 +167,7 @@
void onHotplug(int portId, boolean connected) {
assertRunOnServiceThread();
mCecMessageCache.flushAll();
- // We'll not clear mIsActiveSource on the hotplug event to pass CETC 11.2.2-2 ~ 3.
+ // We'll not invalidate the active source on the hotplug event to pass CETC 11.2.2-2 ~ 3.
if (!connected) {
getWakeLock().release();
}
@@ -178,13 +180,12 @@
if (!mService.isControlEnabled()) {
return;
}
- if (mIsActiveSource) {
+ if (isActiveSource()) {
mService.sendCecCommand(HdmiCecMessageBuilder.buildInactiveSource(
mAddress, mService.getPhysicalAddress()));
}
- boolean wasActiveSource = mIsActiveSource;
+ boolean wasActiveSource = isActiveSource();
// Invalidate the internal active source record when goes to standby
- // This set will also update mIsActiveSource
mService.setActiveSource(Constants.ADDR_INVALID, Constants.INVALID_PHYSICAL_ADDRESS,
"HdmiCecLocalDevicePlayback#onStandby()");
if (initiatedByCec || !mAutoTvOff || !wasActiveSource) {
@@ -229,12 +230,13 @@
}
@Override
+ @CallSuper
@ServiceThreadOnly
@VisibleForTesting
- void setIsActiveSource(boolean on) {
+ protected void setActiveSource(int logicalAddress, int physicalAddress, String caller) {
assertRunOnServiceThread();
- super.setIsActiveSource(on);
- if (on) {
+ super.setActiveSource(logicalAddress, physicalAddress, caller);
+ if (isActiveSource()) {
getWakeLock().acquire();
} else {
getWakeLock().release();
@@ -291,7 +293,7 @@
@Override
protected void wakeUpIfActiveSource() {
- if (!mIsActiveSource) {
+ if (!isActiveSource()) {
return;
}
// Wake up the device if the power is in standby mode, or its screen is off -
@@ -399,9 +401,16 @@
"HdmiCecLocalDevicePlayback#handleRoutingChangeAndInformation()");
return;
}
+ if (!isActiveSource()) {
+ // If routing is changed to the device while Active Source, don't invalidate the
+ // Active Source
+ setActiveSource(physicalAddress,
+ "HdmiCecLocalDevicePlayback#handleRoutingChangeAndInformation()");
+ }
switch (mPlaybackDeviceActionOnRoutingControl) {
case WAKE_UP_AND_SEND_ACTIVE_SOURCE:
- setAndBroadcastActiveSource(message, physicalAddress);
+ setAndBroadcastActiveSource(message, physicalAddress,
+ "HdmiCecLocalDevicePlayback#handleRoutingChangeAndInformation()");
break;
case WAKE_UP_ONLY:
mService.wakeUp();
@@ -436,7 +445,7 @@
@Override
protected void dump(final IndentingPrintWriter pw) {
super.dump(pw);
- pw.println("mIsActiveSource: " + mIsActiveSource);
+ pw.println("isActiveSource(): " + isActiveSource());
pw.println("mAutoTvOff:" + mAutoTvOff);
}
@@ -457,7 +466,7 @@
@Override
public void acquire() {
mWakeLock.acquire();
- HdmiLogger.debug("active source: %b. Wake lock acquired", mIsActiveSource);
+ HdmiLogger.debug("active source: %b. Wake lock acquired", isActiveSource());
}
@Override
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
index 4ff36c4..4325f79 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
@@ -16,6 +16,7 @@
package com.android.server.hdmi;
+import android.annotation.CallSuper;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.hdmi.IHdmiControlCallback;
@@ -36,10 +37,6 @@
private static final String TAG = "HdmiCecLocalDeviceSource";
- // Indicate if current device is Active Source or not
- @VisibleForTesting
- protected boolean mIsActiveSource = false;
-
// Device has cec switch functionality or not.
// Default is false.
protected boolean mIsSwitchDevice = HdmiProperties.is_switch().orElse(false);
@@ -78,7 +75,7 @@
if (mService.getPortInfo(portId).getType() == HdmiPortInfo.PORT_OUTPUT) {
mCecMessageCache.flushAll();
}
- // We'll not clear mIsActiveSource on the hotplug event to pass CETC 11.2.2-2 ~ 3.
+ // We'll not invalidate the active source on the hotplug event to pass CETC 11.2.2-2 ~ 3.
if (connected) {
mService.wakeUp();
}
@@ -118,10 +115,21 @@
// Nothing to do.
}
+ @Override
+ @CallSuper
+ @ServiceThreadOnly
+ void setActiveSource(int logicalAddress, int physicalAddress, String caller) {
+ boolean wasActiveSource = isActiveSource();
+ super.setActiveSource(logicalAddress, physicalAddress, caller);
+ if (wasActiveSource && !isActiveSource()) {
+ onActiveSourceLost();
+ }
+ }
+
@ServiceThreadOnly
protected void setActiveSource(int physicalAddress, String caller) {
assertRunOnServiceThread();
- // Invalidate the internal active source record. This will also update mIsActiveSource.
+ // Invalidate the internal active source record.
ActiveSource activeSource = ActiveSource.of(Constants.ADDR_INVALID, physicalAddress);
setActiveSource(activeSource, caller);
}
@@ -135,7 +143,6 @@
if (!getActiveSource().equals(activeSource)) {
setActiveSource(activeSource, "HdmiCecLocalDeviceSource#handleActiveSource()");
}
- setIsActiveSource(physicalAddress == mService.getPhysicalAddress());
updateDevicePowerStatus(logicalAddress, HdmiControlManager.POWER_STATUS_ON);
if (isRoutingControlFeatureEnabled()) {
switchInputOnReceivingNewActivePath(physicalAddress);
@@ -159,9 +166,11 @@
// If current device is the target path, set to Active Source.
// If the path is under the current device, should switch
if (physicalAddress == mService.getPhysicalAddress() && mService.isPlaybackDevice()) {
- setAndBroadcastActiveSource(message, physicalAddress);
- }
- if (physicalAddress != mService.getPhysicalAddress()) {
+ setAndBroadcastActiveSource(message, physicalAddress,
+ "HdmiCecLocalDeviceSource#handleSetStreamPath()");
+ } else if (physicalAddress != mService.getPhysicalAddress() || !isActiveSource()) {
+ // Invalidate the active source if stream path is set to other physical address or
+ // our physical address while not active source
setActiveSource(physicalAddress, "HdmiCecLocalDeviceSource#handleSetStreamPath()");
}
switchInputOnReceivingNewActivePath(physicalAddress);
@@ -173,19 +182,15 @@
protected boolean handleRoutingChange(HdmiCecMessage message) {
assertRunOnServiceThread();
int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams(), 2);
- if (physicalAddress != mService.getPhysicalAddress()) {
+ if (physicalAddress != mService.getPhysicalAddress() || !isActiveSource()) {
+ // Invalidate the active source if routing is changed to other physical address or
+ // our physical address while not active source
setActiveSource(physicalAddress, "HdmiCecLocalDeviceSource#handleRoutingChange()");
}
if (!isRoutingControlFeatureEnabled()) {
mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
return true;
}
- // if the current device is a pure playback device
- if (!mIsSwitchDevice
- && physicalAddress == mService.getPhysicalAddress()
- && mService.isPlaybackDevice()) {
- setAndBroadcastActiveSource(message, physicalAddress);
- }
handleRoutingChangeAndInformation(physicalAddress, message);
return true;
}
@@ -195,19 +200,15 @@
protected boolean handleRoutingInformation(HdmiCecMessage message) {
assertRunOnServiceThread();
int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
- if (physicalAddress != mService.getPhysicalAddress()) {
+ if (physicalAddress != mService.getPhysicalAddress() || !isActiveSource()) {
+ // Invalidate the active source if routing is changed to other physical address or
+ // our physical address while not active source
setActiveSource(physicalAddress, "HdmiCecLocalDeviceSource#handleRoutingInformation()");
}
if (!isRoutingControlFeatureEnabled()) {
mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
return true;
}
- // if the current device is a pure playback device
- if (!mIsSwitchDevice
- && physicalAddress == mService.getPhysicalAddress()
- && mService.isPlaybackDevice()) {
- setAndBroadcastActiveSource(message, physicalAddress);
- }
handleRoutingChangeAndInformation(physicalAddress, message);
return true;
}
@@ -236,23 +237,21 @@
// since service can decide who will be the active source when the device supports
// multiple device types in this method.
// This method should only be called when the device can be the active source.
- protected void setAndBroadcastActiveSource(HdmiCecMessage message, int physicalAddress) {
+ protected void setAndBroadcastActiveSource(HdmiCecMessage message, int physicalAddress,
+ String caller) {
mService.setAndBroadcastActiveSource(
- physicalAddress, getDeviceInfo().getDeviceType(), message.getSource());
+ physicalAddress, getDeviceInfo().getDeviceType(), message.getSource(), caller);
}
+ // Indicates if current device is the active source or not
@ServiceThreadOnly
- void setIsActiveSource(boolean on) {
- assertRunOnServiceThread();
- boolean wasActiveSource = mIsActiveSource;
- mIsActiveSource = on;
- if (wasActiveSource && !mIsActiveSource) {
- onActiveSourceLost();
- }
+ protected boolean isActiveSource() {
+ return getActiveSource().equals(getDeviceInfo().getLogicalAddress(),
+ getDeviceInfo().getPhysicalAddress());
}
protected void wakeUpIfActiveSource() {
- if (!mIsActiveSource) {
+ if (!isActiveSource()) {
return;
}
// Wake up the device
@@ -261,7 +260,7 @@
}
protected void maySendActiveSource(int dest) {
- if (!mIsActiveSource) {
+ if (!isActiveSource()) {
return;
}
addAndStartAction(new ActiveSourceAction(this, dest));
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index b407234..a60a676 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1600,7 +1600,7 @@
if (isPlaybackDevice()) {
// if playback device itself is the active source,
// return its own device info.
- if (playback() != null && playback().mIsActiveSource) {
+ if (playback() != null && playback().isActiveSource()) {
return playback().getDeviceInfo();
}
// Otherwise get the active source and look for it from the device list
@@ -3242,20 +3242,12 @@
HdmiUtils.pathRelationship(getPhysicalAddress(), physicalAddress));
// If the current device is a source device, check if the current Active Source matches
- // the local device info. Set mIsActiveSource of the local device accordingly.
+ // the local device info.
for (HdmiCecLocalDevice device : getAllLocalDevices()) {
- // mIsActiveSource only exists in source device, ignore this setting if the current
- // device is not an HdmiCecLocalDeviceSource.
- if (!(device instanceof HdmiCecLocalDeviceSource)) {
- device.addActiveSourceHistoryItem(new ActiveSource(logicalAddress, physicalAddress),
- false, caller);
- continue;
- }
boolean deviceIsActiveSource =
logicalAddress == device.getDeviceInfo().getLogicalAddress()
&& physicalAddress == getPhysicalAddress();
- ((HdmiCecLocalDeviceSource) device).setIsActiveSource(deviceIsActiveSource);
device.addActiveSourceHistoryItem(new ActiveSource(logicalAddress, physicalAddress),
deviceIsActiveSource, caller);
}
@@ -3266,22 +3258,22 @@
// For example, when receiving broadcast messages, all the device types will call this
// method but only one of them will be the Active Source.
protected void setAndBroadcastActiveSource(
- int physicalAddress, int deviceType, int source) {
+ int physicalAddress, int deviceType, int source, String caller) {
// If the device has both playback and audio system logical addresses,
// playback will claim active source. Otherwise audio system will.
if (deviceType == HdmiDeviceInfo.DEVICE_PLAYBACK) {
HdmiCecLocalDevicePlayback playback = playback();
- playback.setIsActiveSource(true);
+ playback.setActiveSource(playback.getDeviceInfo().getLogicalAddress(), physicalAddress,
+ caller);
playback.wakeUpIfActiveSource();
playback.maySendActiveSource(source);
}
if (deviceType == HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM) {
HdmiCecLocalDeviceAudioSystem audioSystem = audioSystem();
- if (playback() != null) {
- audioSystem.setIsActiveSource(false);
- } else {
- audioSystem.setIsActiveSource(true);
+ if (playback() == null) {
+ audioSystem.setActiveSource(audioSystem.getDeviceInfo().getLogicalAddress(),
+ physicalAddress, caller);
audioSystem.wakeUpIfActiveSource();
audioSystem.maySendActiveSource(source);
}
@@ -3294,24 +3286,21 @@
// and this method updates Active Source in all the device types sharing the same
// Physical Address.
protected void setAndBroadcastActiveSourceFromOneDeviceType(
- int sourceAddress, int physicalAddress) {
+ int sourceAddress, int physicalAddress, String caller) {
// If the device has both playback and audio system logical addresses,
// playback will claim active source. Otherwise audio system will.
HdmiCecLocalDevicePlayback playback = playback();
HdmiCecLocalDeviceAudioSystem audioSystem = audioSystem();
if (playback != null) {
- playback.setIsActiveSource(true);
+ playback.setActiveSource(playback.getDeviceInfo().getLogicalAddress(), physicalAddress,
+ caller);
playback.wakeUpIfActiveSource();
playback.maySendActiveSource(sourceAddress);
- if (audioSystem != null) {
- audioSystem.setIsActiveSource(false);
- }
- } else {
- if (audioSystem != null) {
- audioSystem.setIsActiveSource(true);
- audioSystem.wakeUpIfActiveSource();
- audioSystem.maySendActiveSource(sourceAddress);
- }
+ } else if (audioSystem != null) {
+ audioSystem.setActiveSource(audioSystem.getDeviceInfo().getLogicalAddress(),
+ physicalAddress, caller);
+ audioSystem.wakeUpIfActiveSource();
+ audioSystem.maySendActiveSource(sourceAddress);
}
}
diff --git a/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java b/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java
index 4962af1..e78a86c 100644
--- a/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java
+++ b/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java
@@ -85,7 +85,7 @@
// Because only source device can create this action, it's safe to cast.
HdmiCecLocalDeviceSource source = source();
source.mService.setAndBroadcastActiveSourceFromOneDeviceType(
- mTargetAddress, getSourcePath());
+ mTargetAddress, getSourcePath(), "OneTouchPlayAction#broadcastActiveSource()");
// When OneTouchPlay is called, client side should be responsible to send out the intent
// of which internal source, for example YouTube, it would like to switch to.
// Here we only update the active port and the active source records in the local
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioInitiationActionFromAvr.java b/services/core/java/com/android/server/hdmi/SystemAudioInitiationActionFromAvr.java
index 0907e5d..acafda6 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioInitiationActionFromAvr.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioInitiationActionFromAvr.java
@@ -119,7 +119,8 @@
// claim Active Source and start to query TV system audio mode support.
if (audioSystem().mService.isPlaybackDevice()) {
audioSystem().mService.setAndBroadcastActiveSourceFromOneDeviceType(
- Constants.ADDR_BROADCAST, getSourcePath());
+ Constants.ADDR_BROADCAST, getSourcePath(),
+ "SystemAudioInitiationActionFromAvr#handleActiveSourceTimeout()");
mState = STATE_WAITING_FOR_TV_SUPPORT;
queryTvSystemAudioModeSupport();
} else {
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 0329c3c..227cdee 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -83,8 +83,6 @@
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
-import com.android.server.location.LocationRequestStatistics.PackageStatistics;
import com.android.server.location.geofence.GeofenceManager;
import com.android.server.location.geofence.GeofenceProxy;
import com.android.server.location.gnss.GnssManagerService;
@@ -93,6 +91,7 @@
import com.android.server.location.util.AppOpsHelper;
import com.android.server.location.util.Injector;
import com.android.server.location.util.LocationAttributionHelper;
+import com.android.server.location.util.LocationEventLog;
import com.android.server.location.util.LocationPermissionsHelper;
import com.android.server.location.util.LocationPowerSaveModeHelper;
import com.android.server.location.util.LocationUsageLogger;
@@ -114,9 +113,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
-import java.util.TreeMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -419,6 +416,8 @@
Log.d(TAG, "[u" + userId + "] location enabled = " + enabled);
}
+ mInjector.getLocationEventLog().logLocationEnabled(userId, enabled);
+
Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION)
.putExtra(LocationManager.EXTRA_LOCATION_ENABLED, enabled)
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
@@ -1131,18 +1130,6 @@
mInjector.getSettingsHelper().dump(fd, ipw, args);
ipw.decreaseIndent();
- ipw.println("Historical Records by Provider:");
- ipw.increaseIndent();
- TreeMap<PackageProviderKey, PackageStatistics> sorted = new TreeMap<>(
- mInjector.getLocationRequestStatistics().statistics);
- for (Map.Entry<PackageProviderKey, PackageStatistics> entry
- : sorted.entrySet()) {
- ipw.println(entry.getKey() + ": " + entry.getValue());
- }
- ipw.decreaseIndent();
-
- mInjector.getLocationRequestStatistics().history.dump(ipw);
-
synchronized (mLock) {
if (mExtraLocationControllerPackage != null) {
ipw.println(
@@ -1170,6 +1157,13 @@
ipw.increaseIndent();
mGeofenceManager.dump(fd, ipw, args);
ipw.decreaseIndent();
+
+ ipw.println("Event Log:");
+ ipw.increaseIndent();
+ for (String log : mInjector.getLocationEventLog()) {
+ ipw.println(log);
+ }
+ ipw.decreaseIndent();
}
private class LocalService extends LocationManagerInternal {
@@ -1231,6 +1225,7 @@
private static class SystemInjector implements Injector {
+ private final LocationEventLog mLocationEventLog;
private final UserInfoHelper mUserInfoHelper;
private final AlarmHelper mAlarmHelper;
private final SystemAppOpsHelper mAppOpsHelper;
@@ -1241,9 +1236,9 @@
private final SystemScreenInteractiveHelper mScreenInteractiveHelper;
private final LocationAttributionHelper mLocationAttributionHelper;
private final LocationUsageLogger mLocationUsageLogger;
- private final LocationRequestStatistics mLocationRequestStatistics;
SystemInjector(Context context, UserInfoHelper userInfoHelper) {
+ mLocationEventLog = new LocationEventLog();
mUserInfoHelper = userInfoHelper;
mAlarmHelper = new SystemAlarmHelper(context);
mAppOpsHelper = new SystemAppOpsHelper(context);
@@ -1251,11 +1246,11 @@
mAppOpsHelper);
mSettingsHelper = new SystemSettingsHelper(context);
mAppForegroundHelper = new SystemAppForegroundHelper(context);
- mLocationPowerSaveModeHelper = new SystemLocationPowerSaveModeHelper(context);
+ mLocationPowerSaveModeHelper = new SystemLocationPowerSaveModeHelper(context,
+ mLocationEventLog);
mScreenInteractiveHelper = new SystemScreenInteractiveHelper(context);
mLocationAttributionHelper = new LocationAttributionHelper(mAppOpsHelper);
mLocationUsageLogger = new LocationUsageLogger();
- mLocationRequestStatistics = new LocationRequestStatistics();
}
void onSystemReady() {
@@ -1318,8 +1313,8 @@
}
@Override
- public LocationRequestStatistics getLocationRequestStatistics() {
- return mLocationRequestStatistics;
+ public LocationEventLog getLocationEventLog() {
+ return mLocationEventLog;
}
}
}
diff --git a/services/core/java/com/android/server/location/LocationProviderManager.java b/services/core/java/com/android/server/location/LocationProviderManager.java
index cd8bf4a..c6a9a1f 100644
--- a/services/core/java/com/android/server/location/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/LocationProviderManager.java
@@ -95,6 +95,7 @@
import com.android.server.location.util.AppOpsHelper;
import com.android.server.location.util.Injector;
import com.android.server.location.util.LocationAttributionHelper;
+import com.android.server.location.util.LocationEventLog;
import com.android.server.location.util.LocationPermissionsHelper;
import com.android.server.location.util.LocationPermissionsHelper.LocationPermissionsListener;
import com.android.server.location.util.LocationPowerSaveModeHelper;
@@ -276,6 +277,8 @@
+ getRequest());
}
+ mLocationEventLog.logProviderClientRegistered(mName, getIdentity(), super.getRequest());
+
// initialization order is important as there are ordering dependencies
mPermitted = mLocationPermissionsHelper.hasLocationPermissions(mPermissionLevel,
getIdentity());
@@ -295,6 +298,8 @@
onProviderListenerUnregister();
+ mLocationEventLog.logProviderClientUnregistered(mName, getIdentity());
+
if (D) {
Log.d(TAG, mName + " provider removed registration from " + getIdentity());
}
@@ -519,16 +524,18 @@
}
}
- if (baseRequest.isLocationSettingsIgnored()) {
+ boolean locationSettingsIgnored = baseRequest.isLocationSettingsIgnored();
+ if (locationSettingsIgnored) {
// if we are not currently allowed use location settings ignored, disable it
if (!mSettingsHelper.getIgnoreSettingsPackageWhitelist().contains(
getIdentity().getPackageName()) && !mLocationManagerInternal.isProvider(
null, getIdentity())) {
builder.setLocationSettingsIgnored(false);
+ locationSettingsIgnored = false;
}
}
- if (!baseRequest.isLocationSettingsIgnored() && !isThrottlingExempt()) {
+ if (!locationSettingsIgnored && !isThrottlingExempt()) {
// throttle in the background
if (!mForeground) {
builder.setIntervalMillis(max(baseRequest.getIntervalMillis(),
@@ -793,6 +800,7 @@
listener.deliverOnLocationChanged(deliveryLocation,
location.isFromMockProvider() ? null : mWakeLock::release);
+ mLocationEventLog.logProviderDeliveredLocation(mName, getIdentity());
}
@Override
@@ -1004,7 +1012,7 @@
// if the provider is currently disabled fail immediately
int userId = getIdentity().getUserId();
- if (!getRequest().isLocationSettingsIgnored() && !isEnabled(userId)) {
+ if (!isEnabled(userId)) {
deliverLocation(null);
}
}
@@ -1095,6 +1103,7 @@
// we currently don't hold a wakelock for getCurrentLocation deliveries
try {
listener.deliverOnLocationChanged(deliveryLocation, null);
+ mLocationEventLog.logProviderDeliveredLocation(mName, getIdentity());
} catch (Exception exception) {
if (exception instanceof RemoteException) {
Log.w(TAG, "registration " + this + " failed", exception);
@@ -1165,7 +1174,7 @@
protected final LocationManagerInternal mLocationManagerInternal;
protected final SettingsHelper mSettingsHelper;
- protected final UserInfoHelper mUserInfoHelper;
+ protected final UserInfoHelper mUserHelper;
protected final AlarmHelper mAlarmHelper;
protected final AppOpsHelper mAppOpsHelper;
protected final LocationPermissionsHelper mLocationPermissionsHelper;
@@ -1175,7 +1184,7 @@
protected final LocationAttributionHelper mLocationAttributionHelper;
protected final LocationUsageLogger mLocationUsageLogger;
protected final LocationFudger mLocationFudger;
- protected final LocationRequestStatistics mLocationRequestStatistics;
+ protected final LocationEventLog mLocationEventLog;
private final UserListener mUserChangedListener = this::onUserChanged;
private final UserSettingChangedListener mLocationEnabledChangedListener =
@@ -1227,7 +1236,7 @@
mLocationManagerInternal = Objects.requireNonNull(
LocalServices.getService(LocationManagerInternal.class));
mSettingsHelper = injector.getSettingsHelper();
- mUserInfoHelper = injector.getUserInfoHelper();
+ mUserHelper = injector.getUserInfoHelper();
mAlarmHelper = injector.getAlarmHelper();
mAppOpsHelper = injector.getAppOpsHelper();
mLocationPermissionsHelper = injector.getLocationPermissionsHelper();
@@ -1236,7 +1245,7 @@
mScreenInteractiveHelper = injector.getScreenInteractiveHelper();
mLocationAttributionHelper = injector.getLocationAttributionHelper();
mLocationUsageLogger = injector.getLocationUsageLogger();
- mLocationRequestStatistics = injector.getLocationRequestStatistics();
+ mLocationEventLog = injector.getLocationEventLog();
mLocationFudger = new LocationFudger(mSettingsHelper.getCoarseLocationAccuracyM());
// initialize last since this lets our reference escape
@@ -1252,7 +1261,7 @@
synchronized (mLock) {
mStarted = true;
- mUserInfoHelper.addListener(mUserChangedListener);
+ mUserHelper.addListener(mUserChangedListener);
mSettingsHelper.addOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
long identity = Binder.clearCallingIdentity();
@@ -1267,20 +1276,19 @@
public void stopManager() {
synchronized (mLock) {
- mUserInfoHelper.removeListener(mUserChangedListener);
+ mUserHelper.removeListener(mUserChangedListener);
mSettingsHelper.removeOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
- // notify and remove all listeners
+ mStarted = false;
+
long identity = Binder.clearCallingIdentity();
try {
- onUserStopped(UserHandle.USER_ALL);
+ onEnabledChanged(UserHandle.USER_ALL);
removeRegistrationIf(key -> true);
+ mEnabledListeners.clear();
} finally {
Binder.restoreCallingIdentity(identity);
}
-
- mEnabledListeners.clear();
- mStarted = false;
}
}
@@ -1354,6 +1362,8 @@
synchronized (mLock) {
Preconditions.checkState(mStarted);
+ mLocationEventLog.logProviderMocked(mName, provider != null);
+
long identity = Binder.clearCallingIdentity();
try {
mProvider.setMockProvider(provider);
@@ -1430,11 +1440,13 @@
identity.getPackageName())) {
return null;
}
- if (!mUserInfoHelper.isCurrentUserId(identity.getUserId())) {
- return null;
- }
- if (!ignoreLocationSettings && !isEnabled(identity.getUserId())) {
- return null;
+ if (!ignoreLocationSettings) {
+ if (!isEnabled(identity.getUserId())) {
+ return null;
+ }
+ if (!identity.isSystem() && !mUserHelper.isCurrentUserId(identity.getUserId())) {
+ return null;
+ }
}
Location location = getLastLocationUnsafe(identity.getUserId(), permissionLevel,
@@ -1462,7 +1474,7 @@
if (userId == UserHandle.USER_ALL) {
// find the most recent location across all users
Location lastLocation = null;
- final int[] runningUserIds = mUserInfoHelper.getRunningUserIds();
+ final int[] runningUserIds = mUserHelper.getRunningUserIds();
for (int i = 0; i < runningUserIds.length; i++) {
Location next = getLastLocationUnsafe(runningUserIds[i], permissionLevel,
ignoreLocationSettings, maximumAgeMs);
@@ -1507,7 +1519,7 @@
private void setLastLocation(Location location, int userId) {
if (userId == UserHandle.USER_ALL) {
- final int[] runningUserIds = mUserInfoHelper.getRunningUserIds();
+ final int[] runningUserIds = mUserHelper.getRunningUserIds();
for (int i = 0; i < runningUserIds.length; i++) {
setLastLocation(location, runningUserIds[i]);
}
@@ -1533,7 +1545,7 @@
@Nullable
public ICancellationSignal getCurrentLocation(LocationRequest request,
- CallerIdentity callerIdentity, int permissionLevel, ILocationCallback callback) {
+ CallerIdentity identity, int permissionLevel, ILocationCallback callback) {
if (request.getDurationMillis() > GET_CURRENT_LOCATION_MAX_TIMEOUT_MS) {
request = new LocationRequest.Builder(request)
.setDurationMillis(GET_CURRENT_LOCATION_MAX_TIMEOUT_MS)
@@ -1543,27 +1555,31 @@
GetCurrentLocationListenerRegistration registration =
new GetCurrentLocationListenerRegistration(
request,
- callerIdentity,
+ identity,
new GetCurrentLocationTransport(callback),
permissionLevel);
synchronized (mLock) {
- if (mSettingsHelper.isLocationPackageBlacklisted(callerIdentity.getUserId(),
- callerIdentity.getPackageName())) {
+ // shortcut various failure conditions so that we can return immediately rather than
+ // waiting for location to timeout
+ if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
+ identity.getPackageName())) {
registration.deliverLocation(null);
return null;
}
- if (!mUserInfoHelper.isCurrentUserId(callerIdentity.getUserId())) {
- registration.deliverLocation(null);
- return null;
- }
- if (!request.isLocationSettingsIgnored() && !isEnabled(callerIdentity.getUserId())) {
- registration.deliverLocation(null);
- return null;
+ if (!request.isLocationSettingsIgnored()) {
+ if (!isEnabled(identity.getUserId())) {
+ registration.deliverLocation(null);
+ return null;
+ }
+ if (!identity.isSystem() && !mUserHelper.isCurrentUserId(identity.getUserId())) {
+ registration.deliverLocation(null);
+ return null;
+ }
}
Location lastLocation = getLastLocationUnsafe(
- callerIdentity.getUserId(),
+ identity.getUserId(),
permissionLevel,
request.isLocationSettingsIgnored(),
MAX_CURRENT_LOCATION_AGE_MS);
@@ -1573,11 +1589,11 @@
}
// if last location isn't good enough then we add a location request
- long identity = Binder.clearCallingIdentity();
+ long ident = Binder.clearCallingIdentity();
try {
addRegistration(callback.asBinder(), registration);
} finally {
- Binder.restoreCallingIdentity(identity);
+ Binder.restoreCallingIdentity(ident);
}
}
@@ -1601,20 +1617,20 @@
}
}
- public void registerLocationRequest(LocationRequest request, CallerIdentity callerIdentity,
+ public void registerLocationRequest(LocationRequest request, CallerIdentity identity,
@PermissionLevel int permissionLevel, ILocationListener listener) {
synchronized (mLock) {
- long identity = Binder.clearCallingIdentity();
+ long ident = Binder.clearCallingIdentity();
try {
addRegistration(
listener.asBinder(),
new LocationListenerRegistration(
request,
- callerIdentity,
+ identity,
new LocationListenerTransport(listener),
permissionLevel));
} finally {
- Binder.restoreCallingIdentity(identity);
+ Binder.restoreCallingIdentity(ident);
}
}
}
@@ -1717,13 +1733,6 @@
key instanceof PendingIntent,
/* geofence= */ key instanceof IBinder,
null, registration.isForeground());
-
- mLocationRequestStatistics.startRequesting(
- registration.getIdentity().getPackageName(),
- registration.getIdentity().getAttributionTag(),
- mName,
- registration.getRequest().getIntervalMillis(),
- registration.isForeground());
}
@GuardedBy("mLock")
@@ -1743,11 +1752,6 @@
Preconditions.checkState(Thread.holdsLock(mLock));
}
- mLocationRequestStatistics.stopRequesting(
- registration.getIdentity().getPackageName(),
- registration.getIdentity().getAttributionTag(),
- mName);
-
mLocationUsageLogger.logLocationApiUsage(
LocationStatsEnums.USAGE_ENDED,
LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
@@ -1799,13 +1803,20 @@
Preconditions.checkState(delayMs >= 0 && delayMs <= newRequest.getIntervalMillis());
if (delayMs < MIN_REQUEST_DELAY_MS) {
+ mLocationEventLog.logProviderUpdateRequest(mName, newRequest);
mProvider.setRequest(newRequest);
} else {
+ if (D) {
+ Log.d(TAG, mName + " provider delaying request update " + newRequest + " by "
+ + TimeUtils.formatDuration(delayMs));
+ }
+
mDelayedRegister = new OnAlarmListener() {
@Override
public void onAlarm() {
synchronized (mLock) {
if (mDelayedRegister == this) {
+ mLocationEventLog.logProviderUpdateRequest(mName, newRequest);
mProvider.setRequest(newRequest);
mDelayedRegister = null;
}
@@ -1825,6 +1836,7 @@
Preconditions.checkState(Thread.holdsLock(mLock));
}
+ mLocationEventLog.logProviderUpdateRequest(mName, EMPTY_REQUEST);
mProvider.setRequest(EMPTY_REQUEST);
}
@@ -1845,6 +1857,9 @@
if (!isEnabled(identity.getUserId())) {
return false;
}
+ if (!identity.isSystem() && !mUserHelper.isCurrentUserId(identity.getUserId())) {
+ return false;
+ }
switch (mLocationPowerSaveModeHelper.getLocationPowerSaveMode()) {
case LOCATION_MODE_FOREGROUND_ONLY:
@@ -1973,7 +1988,8 @@
synchronized (mLock) {
switch (change) {
case UserListener.CURRENT_USER_CHANGED:
- onEnabledChanged(userId);
+ updateRegistrations(
+ registration -> registration.getIdentity().getUserId() == userId);
break;
case UserListener.USER_STARTED:
onUserStarted(userId);
@@ -2093,16 +2109,21 @@
return;
}
+ if (mPassiveManager != null) {
+ // don't log location received for passive provider because it's spammy
+ mLocationEventLog.logProviderReceivedLocation(mName);
+ }
+
// update last location
setLastLocation(location, UserHandle.USER_ALL);
+ // attempt listener delivery
+ deliverToListeners(registration -> registration.acceptLocationChange(location));
+
// notify passive provider
if (mPassiveManager != null) {
mPassiveManager.updateLocation(location);
}
-
- // attempt listener delivery
- deliverToListeners(registration -> registration.acceptLocationChange(location));
}
@GuardedBy("mLock")
@@ -2149,13 +2170,10 @@
}
if (userId == UserHandle.USER_ALL) {
- onEnabledChanged(UserHandle.USER_ALL);
mEnabled.clear();
mLastLocations.clear();
} else {
Preconditions.checkArgument(userId >= 0);
-
- onEnabledChanged(userId);
mEnabled.delete(userId);
mLastLocations.remove(userId);
}
@@ -2172,7 +2190,7 @@
// settings for instance) do not support the null user
return;
} else if (userId == UserHandle.USER_ALL) {
- final int[] runningUserIds = mUserInfoHelper.getRunningUserIds();
+ final int[] runningUserIds = mUserHelper.getRunningUserIds();
for (int i = 0; i < runningUserIds.length; i++) {
onEnabledChanged(runningUserIds[i]);
}
@@ -2183,7 +2201,6 @@
boolean enabled = mStarted
&& mProvider.getState().allowed
- && mUserInfoHelper.isCurrentUserId(userId)
&& mSettingsHelper.isLocationEnabled(userId);
int index = mEnabled.indexOfKey(userId);
@@ -2194,8 +2211,12 @@
mEnabled.put(userId, enabled);
- if (D) {
- Log.d(TAG, "[u" + userId + "] " + mName + " provider enabled = " + enabled);
+ // don't log unknown -> false transitions for brevity
+ if (wasEnabled != null || enabled) {
+ if (D) {
+ Log.d(TAG, "[u" + userId + "] " + mName + " provider enabled = " + enabled);
+ }
+ mLocationEventLog.logProviderEnabled(mName, userId, enabled);
}
// clear last locations if we become disabled
@@ -2247,7 +2268,7 @@
super.dump(fd, ipw, args);
- int[] userIds = mUserInfoHelper.getRunningUserIds();
+ int[] userIds = mUserHelper.getRunningUserIds();
for (int userId : userIds) {
if (userIds.length != 1) {
ipw.print("user ");
@@ -2270,6 +2291,11 @@
ipw.decreaseIndent();
}
+ @Override
+ protected String getServiceState() {
+ return mProvider.getCurrentRequest().toString();
+ }
+
private static class LastLocation {
@Nullable private Location mFineLocation;
diff --git a/services/core/java/com/android/server/location/LocationRequestStatistics.java b/services/core/java/com/android/server/location/LocationRequestStatistics.java
deleted file mode 100644
index 4984e63..0000000
--- a/services/core/java/com/android/server/location/LocationRequestStatistics.java
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.location;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.SystemClock;
-import android.util.IndentingPrintWriter;
-import android.util.Log;
-import android.util.TimeUtils;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Objects;
-
-/**
- * Holds statistics for location requests (active requests by provider).
- *
- * <p>Must be externally synchronized.
- */
-public class LocationRequestStatistics {
- private static final String TAG = "LocationStats";
-
- // Maps package name and provider to location request statistics.
- public final HashMap<PackageProviderKey, PackageStatistics> statistics
- = new HashMap<PackageProviderKey, PackageStatistics>();
-
- public final RequestSummaryLimitedHistory history = new RequestSummaryLimitedHistory();
-
- /**
- * Signals that a package has started requesting locations.
- *
- * @param packageName Name of package that has requested locations.
- * @param featureId Feature id associated with the request.
- * @param providerName Name of provider that is requested (e.g. "gps").
- * @param intervalMs The interval that is requested in ms.
- */
- public void startRequesting(String packageName, @Nullable String featureId, String providerName,
- long intervalMs, boolean isForeground) {
- PackageProviderKey key = new PackageProviderKey(packageName, featureId, providerName);
- PackageStatistics stats = statistics.get(key);
- if (stats == null) {
- stats = new PackageStatistics();
- statistics.put(key, stats);
- }
- stats.startRequesting(intervalMs);
- stats.updateForeground(isForeground);
- history.addRequest(packageName, featureId, providerName, intervalMs);
- }
-
- /**
- * Signals that a package has stopped requesting locations.
- *
- * @param packageName Name of package that has stopped requesting locations.
- * @param featureId Feature id associated with the request.
- * @param providerName Provider that is no longer being requested.
- */
- public void stopRequesting(String packageName, @Nullable String featureId,
- String providerName) {
- PackageProviderKey key = new PackageProviderKey(packageName, featureId, providerName);
- PackageStatistics stats = statistics.get(key);
- if (stats != null) {
- stats.stopRequesting();
- }
- history.removeRequest(packageName, featureId, providerName);
- }
-
- /**
- * Signals that a package possibly switched background/foreground.
- *
- * @param packageName Name of package that has stopped requesting locations.
- * @param featureId Feature id associated with the request.
- * @param providerName Provider that is no longer being requested.
- */
- public void updateForeground(String packageName, @Nullable String featureId,
- String providerName, boolean isForeground) {
- PackageProviderKey key = new PackageProviderKey(packageName, featureId, providerName);
- PackageStatistics stats = statistics.get(key);
- if (stats != null) {
- stats.updateForeground(isForeground);
- }
- }
-
- /**
- * A key that holds package, feature id, and provider names.
- */
- public static class PackageProviderKey implements Comparable<PackageProviderKey> {
- /**
- * Name of package requesting location.
- */
- public final String mPackageName;
- /**
- * Feature id associated with the request, which can be used to attribute location access to
- * different parts of the application.
- */
- @Nullable
- public final String mFeatureId;
- /**
- * Name of provider being requested (e.g. "gps").
- */
- public final String mProviderName;
-
- PackageProviderKey(String packageName, @Nullable String featureId, String providerName) {
- this.mPackageName = packageName;
- this.mFeatureId = featureId;
- this.mProviderName = providerName;
- }
-
- @NonNull
- @Override
- public String toString() {
- return mProviderName + ": " + mPackageName
- + (mFeatureId == null ? "" : ": " + mFeatureId);
- }
-
- /**
- * Sort by provider, then package, then feature
- */
- @Override
- public int compareTo(PackageProviderKey other) {
- final int providerCompare = mProviderName.compareTo(other.mProviderName);
- if (providerCompare != 0) {
- return providerCompare;
- }
-
- final int packageCompare = mPackageName.compareTo(other.mPackageName);
- if (packageCompare != 0) {
- return packageCompare;
- }
-
- return Objects.compare(mFeatureId, other.mFeatureId, Comparator
- .nullsFirst(String::compareTo));
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof PackageProviderKey)) {
- return false;
- }
-
- PackageProviderKey otherKey = (PackageProviderKey) other;
- return mPackageName.equals(otherKey.mPackageName)
- && mProviderName.equals(otherKey.mProviderName)
- && Objects.equals(mFeatureId, otherKey.mFeatureId);
- }
-
- @Override
- public int hashCode() {
- int hash = mPackageName.hashCode() + 31 * mProviderName.hashCode();
- if (mFeatureId != null) {
- hash += mFeatureId.hashCode() + 31 * hash;
- }
- return hash;
- }
- }
-
- /**
- * A data structure to hold past requests
- */
- public static class RequestSummaryLimitedHistory {
- @VisibleForTesting
- static final int MAX_SIZE = 100;
-
- final ArrayList<RequestSummary> mList = new ArrayList<>(MAX_SIZE);
-
- /**
- * Append an added location request to the history
- */
- @VisibleForTesting
- void addRequest(String packageName, @Nullable String featureId, String providerName,
- long intervalMs) {
- addRequestSummary(new RequestSummary(packageName, featureId, providerName, intervalMs));
- }
-
- /**
- * Append a removed location request to the history
- */
- @VisibleForTesting
- void removeRequest(String packageName, @Nullable String featureId, String providerName) {
- addRequestSummary(new RequestSummary(
- packageName, featureId, providerName, RequestSummary.REQUEST_ENDED_INTERVAL));
- }
-
- private void addRequestSummary(RequestSummary summary) {
- while (mList.size() >= MAX_SIZE) {
- mList.remove(0);
- }
- mList.add(summary);
- }
-
- /**
- * Dump history to a printwriter (for dumpsys location)
- */
- public void dump(IndentingPrintWriter ipw) {
- long systemElapsedOffsetMillis = System.currentTimeMillis()
- - SystemClock.elapsedRealtime();
-
- ipw.println("Last Several Location Requests:");
- ipw.increaseIndent();
-
- for (RequestSummary requestSummary : mList) {
- requestSummary.dump(ipw, systemElapsedOffsetMillis);
- }
-
- ipw.decreaseIndent();
- }
- }
-
- /**
- * A data structure to hold a single request
- */
- static class RequestSummary {
- /**
- * Name of package requesting location.
- */
- private final String mPackageName;
-
- /**
- * Feature id associated with the request for identifying subsystem of an application.
- */
- @Nullable
- private final String mFeatureId;
- /**
- * Name of provider being requested (e.g. "gps").
- */
- private final String mProviderName;
- /**
- * Interval Requested, or REQUEST_ENDED_INTERVAL indicating request has ended
- */
- private final long mIntervalMillis;
- /**
- * Elapsed time of request
- */
- private final long mElapsedRealtimeMillis;
-
- /**
- * Placeholder for requested ending (other values indicate request started/changed)
- */
- static final long REQUEST_ENDED_INTERVAL = -1;
-
- RequestSummary(String packageName, @Nullable String featureId, String providerName,
- long intervalMillis) {
- this.mPackageName = packageName;
- this.mFeatureId = featureId;
- this.mProviderName = providerName;
- this.mIntervalMillis = intervalMillis;
- this.mElapsedRealtimeMillis = SystemClock.elapsedRealtime();
- }
-
- void dump(IndentingPrintWriter ipw, long systemElapsedOffsetMillis) {
- StringBuilder s = new StringBuilder();
- long systemTimeMillis = systemElapsedOffsetMillis + mElapsedRealtimeMillis;
- s.append("At ").append(TimeUtils.logTimeOfDay(systemTimeMillis)).append(": ")
- .append(mIntervalMillis == REQUEST_ENDED_INTERVAL ? "- " : "+ ")
- .append(String.format("%7s", mProviderName)).append(" request from ")
- .append(mPackageName);
- if (mFeatureId != null) {
- s.append(" with feature ").append(mFeatureId);
- }
- if (mIntervalMillis != REQUEST_ENDED_INTERVAL) {
- s.append(" at interval ").append(mIntervalMillis / 1000).append(" seconds");
- }
- ipw.println(s);
- }
- }
-
- /**
- * Usage statistics for a package/provider pair.
- */
- public static class PackageStatistics {
- // Time when this package first requested location.
- private final long mInitialElapsedTimeMs;
- // Number of active location requests this package currently has.
- private int mNumActiveRequests;
- // Time when this package most recently went from not requesting location to requesting.
- private long mLastActivitationElapsedTimeMs;
- // The fastest interval this package has ever requested.
- private long mFastestIntervalMs;
- // The slowest interval this package has ever requested.
- private long mSlowestIntervalMs;
- // The total time this app has requested location (not including currently running
- // requests).
- private long mTotalDurationMs;
-
- // Time when this package most recently went to foreground, requesting location. 0 means
- // not currently in foreground.
- private long mLastForegroundElapsedTimeMs;
- // The time this app has requested location (not including currently running requests),
- // while in foreground.
- private long mForegroundDurationMs;
-
- // Time when package last went dormant (stopped requesting location)
- private long mLastStopElapsedTimeMs;
-
- private PackageStatistics() {
- mInitialElapsedTimeMs = SystemClock.elapsedRealtime();
- mNumActiveRequests = 0;
- mTotalDurationMs = 0;
- mFastestIntervalMs = Long.MAX_VALUE;
- mSlowestIntervalMs = 0;
- mForegroundDurationMs = 0;
- mLastForegroundElapsedTimeMs = 0;
- mLastStopElapsedTimeMs = 0;
- }
-
- private void startRequesting(long intervalMs) {
- if (mNumActiveRequests == 0) {
- mLastActivitationElapsedTimeMs = SystemClock.elapsedRealtime();
- }
-
- if (intervalMs < mFastestIntervalMs) {
- mFastestIntervalMs = intervalMs;
- }
-
- if (intervalMs > mSlowestIntervalMs) {
- mSlowestIntervalMs = intervalMs;
- }
-
- mNumActiveRequests++;
- }
-
- private void updateForeground(boolean isForeground) {
- long nowElapsedTimeMs = SystemClock.elapsedRealtime();
- // if previous interval was foreground, accumulate before resetting start
- if (mLastForegroundElapsedTimeMs != 0) {
- mForegroundDurationMs += (nowElapsedTimeMs - mLastForegroundElapsedTimeMs);
- }
- mLastForegroundElapsedTimeMs = isForeground ? nowElapsedTimeMs : 0;
- }
-
- private void stopRequesting() {
- if (mNumActiveRequests <= 0) {
- // Shouldn't be a possible code path
- Log.e(TAG, "Reference counting corrupted in usage statistics.");
- return;
- }
-
- mNumActiveRequests--;
- if (mNumActiveRequests == 0) {
- mLastStopElapsedTimeMs = SystemClock.elapsedRealtime();
- long lastDurationMs = mLastStopElapsedTimeMs - mLastActivitationElapsedTimeMs;
- mTotalDurationMs += lastDurationMs;
- updateForeground(false);
- }
- }
-
- /**
- * Returns the duration that this request has been active.
- */
- public long getDurationMs() {
- long currentDurationMs = mTotalDurationMs;
- if (mNumActiveRequests > 0) {
- currentDurationMs
- += SystemClock.elapsedRealtime() - mLastActivitationElapsedTimeMs;
- }
- return currentDurationMs;
- }
-
- /**
- * Returns the duration that this request has been active.
- */
- public long getForegroundDurationMs() {
- long currentDurationMs = mForegroundDurationMs;
- if (mLastForegroundElapsedTimeMs != 0) {
- currentDurationMs
- += SystemClock.elapsedRealtime() - mLastForegroundElapsedTimeMs;
- }
- return currentDurationMs;
- }
-
- /**
- * Returns the time since the initial request in ms.
- */
- public long getTimeSinceFirstRequestMs() {
- return SystemClock.elapsedRealtime() - mInitialElapsedTimeMs;
- }
-
- /**
- * Returns the time since the last request stopped in ms.
- */
- public long getTimeSinceLastRequestStoppedMs() {
- return SystemClock.elapsedRealtime() - mLastStopElapsedTimeMs;
- }
-
- /**
- * Returns the fastest interval that has been tracked.
- */
- public long getFastestIntervalMs() {
- return mFastestIntervalMs;
- }
-
- /**
- * Returns the slowest interval that has been tracked.
- */
- public long getSlowestIntervalMs() {
- return mSlowestIntervalMs;
- }
-
- /**
- * Returns true if a request is active for these tracked statistics.
- */
- public boolean isActive() {
- return mNumActiveRequests > 0;
- }
-
- @Override
- public String toString() {
- StringBuilder s = new StringBuilder();
- if (mFastestIntervalMs == mSlowestIntervalMs) {
- s.append("Interval ").append(mFastestIntervalMs / 1000).append(" seconds");
- } else {
- s.append("Min interval ").append(mFastestIntervalMs / 1000).append(" seconds");
- s.append(": Max interval ").append(mSlowestIntervalMs / 1000).append(" seconds");
- }
- s.append(": Duration requested ")
- .append((getDurationMs() / 1000) / 60)
- .append(" total, ")
- .append((getForegroundDurationMs() / 1000) / 60)
- .append(" foreground, out of the last ")
- .append((getTimeSinceFirstRequestMs() / 1000) / 60)
- .append(" minutes");
- if (isActive()) {
- s.append(": Currently active");
- } else {
- s.append(": Last active ")
- .append((getTimeSinceLastRequestStoppedMs() / 1000) / 60)
- .append(" minutes ago");
- }
- return s.toString();
- }
- }
-}
diff --git a/services/core/java/com/android/server/location/geofence/GeofenceManager.java b/services/core/java/com/android/server/location/geofence/GeofenceManager.java
index 58e6d59..baa01b1 100644
--- a/services/core/java/com/android/server/location/geofence/GeofenceManager.java
+++ b/services/core/java/com/android/server/location/geofence/GeofenceManager.java
@@ -327,7 +327,7 @@
protected boolean isActive(GeofenceRegistration registration) {
CallerIdentity identity = registration.getIdentity();
return registration.isPermitted()
- && mUserInfoHelper.isCurrentUserId(identity.getUserId())
+ && (identity.isSystem() || mUserInfoHelper.isCurrentUserId(identity.getUserId()))
&& mSettingsHelper.isLocationEnabled(identity.getUserId())
&& !mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
identity.getPackageName());
diff --git a/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java b/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
index a830e2f..1cdb118 100644
--- a/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
+++ b/services/core/java/com/android/server/location/gnss/GnssListenerMultiplexer.java
@@ -44,7 +44,6 @@
import com.android.server.location.util.UserInfoHelper;
import com.android.server.location.util.UserInfoHelper.UserListener;
-import java.io.PrintWriter;
import java.util.Collection;
import java.util.Objects;
@@ -260,7 +259,7 @@
CallerIdentity identity = registration.getIdentity();
return registration.isPermitted()
&& (registration.isForeground() || isBackgroundRestrictionExempt(identity))
- && mUserInfoHelper.isCurrentUserId(identity.getUserId())
+ && (identity.isSystem() || mUserInfoHelper.isCurrentUserId(identity.getUserId()))
&& mLocationManagerInternal.isProviderEnabledForUser(GPS_PROVIDER,
identity.getUserId())
&& !mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(),
@@ -361,11 +360,11 @@
}
@Override
- protected void dumpServiceState(PrintWriter pw) {
+ protected String getServiceState() {
if (!isServiceSupported()) {
- pw.print("unsupported");
+ return "unsupported";
} else {
- super.dumpServiceState(pw);
+ return super.getServiceState();
}
}
}
diff --git a/services/core/java/com/android/server/location/listeners/ListenerMultiplexer.java b/services/core/java/com/android/server/location/listeners/ListenerMultiplexer.java
index 0cda57c..0318ffb 100644
--- a/services/core/java/com/android/server/location/listeners/ListenerMultiplexer.java
+++ b/services/core/java/com/android/server/location/listeners/ListenerMultiplexer.java
@@ -555,7 +555,7 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
synchronized (mRegistrations) {
pw.print("service: ");
- dumpServiceState(pw);
+ pw.print(getServiceState());
pw.println();
if (!mRegistrations.isEmpty()) {
@@ -578,18 +578,17 @@
/**
* May be overridden to provide additional details on service state when dumping the manager
- * state.
+ * state. Invoked while holding the multiplexer's internal lock.
*/
- protected void dumpServiceState(PrintWriter pw) {
+ protected String getServiceState() {
if (mServiceRegistered) {
- pw.print("registered");
if (mMerged != null) {
- pw.print(" [");
- pw.print(mMerged);
- pw.print("]");
+ return mMerged.toString();
+ } else {
+ return "registered";
}
} else {
- pw.print("unregistered");
+ return "unregistered";
}
}
diff --git a/services/core/java/com/android/server/location/timezone/ControllerImpl.java b/services/core/java/com/android/server/location/timezone/ControllerImpl.java
index 179ce75..d482637 100644
--- a/services/core/java/com/android/server/location/timezone/ControllerImpl.java
+++ b/services/core/java/com/android/server/location/timezone/ControllerImpl.java
@@ -44,16 +44,22 @@
import java.util.Objects;
/**
- * A real implementation of {@link LocationTimeZoneProviderController} that supports a single
- * {@link LocationTimeZoneProvider}.
+ * A real implementation of {@link LocationTimeZoneProviderController} that supports a primary and a
+ * secondary {@link LocationTimeZoneProvider}.
*
- * TODO(b/152744911): This implementation currently only supports a single ("primary") provider.
- * Support for a secondary provider will be added in a later commit.
+ * <p>The primary is used until it fails or becomes uncertain. The secondary will then be enabled.
+ * The controller will immediately make suggestions based on "certain" {@link
+ * LocationTimeZoneEvent}s, i.e. events that demonstrate the provider is certain what the time zone
+ * is. The controller will not make immediate suggestions based on "uncertain" events, giving
+ * providers time to change their mind. This also gives the secondary provider time to initialize
+ * when the primary becomes uncertain.
*/
class ControllerImpl extends LocationTimeZoneProviderController {
@NonNull private final LocationTimeZoneProvider mPrimaryProvider;
+ @NonNull private final LocationTimeZoneProvider mSecondaryProvider;
+
@GuardedBy("mSharedLock")
// Non-null after initialize()
private ConfigurationInternal mCurrentUserConfiguration;
@@ -67,7 +73,9 @@
private Callback mCallback;
/**
- * Used for scheduling uncertainty timeouts, i.e after the provider has reported uncertainty.
+ * Used for scheduling uncertainty timeouts, i.e after a provider has reported uncertainty.
+ * This timeout is not provider-specific: it is started when the controller becomes uncertain
+ * due to events it has received from one or other provider.
*/
@NonNull private final SingleRunnableQueue mUncertaintyTimeoutQueue;
@@ -77,10 +85,12 @@
private GeolocationTimeZoneSuggestion mLastSuggestion;
ControllerImpl(@NonNull ThreadingDomain threadingDomain,
- @NonNull LocationTimeZoneProvider primaryProvider) {
+ @NonNull LocationTimeZoneProvider primaryProvider,
+ @NonNull LocationTimeZoneProvider secondaryProvider) {
super(threadingDomain);
mUncertaintyTimeoutQueue = threadingDomain.createSingleRunnableQueue();
mPrimaryProvider = Objects.requireNonNull(primaryProvider);
+ mSecondaryProvider = Objects.requireNonNull(secondaryProvider);
}
@Override
@@ -96,8 +106,9 @@
LocationTimeZoneProvider.ProviderListener providerListener =
ControllerImpl.this::onProviderStateChange;
mPrimaryProvider.initialize(providerListener);
+ mSecondaryProvider.initialize(providerListener);
- alterProviderEnabledStateIfRequired(
+ alterProvidersEnabledStateIfRequired(
null /* oldConfiguration */, mCurrentUserConfiguration);
}
}
@@ -115,15 +126,15 @@
if (!newConfig.equals(oldConfig)) {
if (newConfig.getUserId() != oldConfig.getUserId()) {
- // If the user changed, disable the provider if needed. It may be re-enabled for
- // the new user below if their settings allow.
+ // If the user changed, disable the providers if needed. They may be re-enabled
+ // for the new user immediately afterwards if their settings allow.
debugLog("User changed. old=" + oldConfig.getUserId()
- + ", new=" + newConfig.getUserId() + ": Disabling provider");
- disableProvider();
+ + ", new=" + newConfig.getUserId() + ": Disabling providers");
+ disableProviders();
- alterProviderEnabledStateIfRequired(null /* oldConfiguration */, newConfig);
+ alterProvidersEnabledStateIfRequired(null /* oldConfiguration */, newConfig);
} else {
- alterProviderEnabledStateIfRequired(oldConfig, newConfig);
+ alterProvidersEnabledStateIfRequired(oldConfig, newConfig);
}
}
}
@@ -140,22 +151,23 @@
}
@GuardedBy("mSharedLock")
- private void disableProvider() {
+ private void disableProviders() {
disableProviderIfEnabled(mPrimaryProvider);
+ disableProviderIfEnabled(mSecondaryProvider);
- // By definition, if the provider is disabled, the controller is uncertain.
+ // By definition, if both providers are disabled, the controller is uncertain.
cancelUncertaintyTimeout();
}
@GuardedBy("mSharedLock")
- private void disableProviderIfEnabled(LocationTimeZoneProvider provider) {
+ private void disableProviderIfEnabled(@NonNull LocationTimeZoneProvider provider) {
if (provider.getCurrentState().isEnabled()) {
disableProvider(provider);
}
}
@GuardedBy("mSharedLock")
- private void disableProvider(LocationTimeZoneProvider provider) {
+ private void disableProvider(@NonNull LocationTimeZoneProvider provider) {
ProviderState providerState = provider.getCurrentState();
switch (providerState.stateEnum) {
case PROVIDER_STATE_DISABLED: {
@@ -181,7 +193,7 @@
}
/**
- * Sets the provider into the correct enabled/disabled state for the {@code newConfiguration}
+ * Sets the providers into the correct enabled/disabled state for the {@code newConfiguration}
* and, if there is a provider state change, makes any suggestions required to inform the
* downstream time zone detection code.
*
@@ -190,7 +202,7 @@
* or when a new configuration has been received.
*/
@GuardedBy("mSharedLock")
- private void alterProviderEnabledStateIfRequired(
+ private void alterProvidersEnabledStateIfRequired(
@Nullable ConfigurationInternal oldConfiguration,
@NonNull ConfigurationInternal newConfiguration) {
@@ -203,21 +215,40 @@
return;
}
+ // The check above ensures that the logic below only executes if providers are going from
+ // {enabled *} -> {disabled}, or {disabled} -> {enabled initializing}. If this changes in
+ // future and there could be {enabled *} -> {enabled *} cases, or cases where the provider
+ // can't be assumed to go straight to the {enabled initializing} state, then the logic below
+ // would need to cover extra conditions, for example:
+ // 1) If the primary is in {enabled uncertain}, the secondary should be enabled.
+ // 2) If (1), and the secondary instantly enters the {perm failed} state, the uncertainty
+ // timeout started when the primary entered {enabled uncertain} should be cancelled.
+
if (newGeoDetectionEnabled) {
// Try to enable the primary provider.
tryEnableProvider(mPrimaryProvider, newConfiguration);
+ // The secondary should only ever be enabled if the primary now isn't enabled (i.e. it
+ // couldn't become {enabled initializing} because it is {perm failed}).
ProviderState newPrimaryState = mPrimaryProvider.getCurrentState();
if (!newPrimaryState.isEnabled()) {
- // If the provider is perm failed then the controller is immediately considered
- // uncertain.
- GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
- "Provider is failed:"
- + " primary=" + mPrimaryProvider.getCurrentState());
- makeSuggestion(suggestion);
+ // If the primary provider is {perm failed} then the controller must try to enable
+ // the secondary.
+ tryEnableProvider(mSecondaryProvider, newConfiguration);
+
+ ProviderState newSecondaryState = mSecondaryProvider.getCurrentState();
+ if (!newSecondaryState.isEnabled()) {
+ // If both providers are {perm failed} then the controller immediately
+ // becomes uncertain.
+ GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
+ "Providers are failed:"
+ + " primary=" + mPrimaryProvider.getCurrentState()
+ + " secondary=" + mPrimaryProvider.getCurrentState());
+ makeSuggestion(suggestion);
+ }
}
} else {
- disableProvider();
+ disableProviders();
// There can be an uncertainty timeout set if the controller most recently received
// an uncertain event. This is a no-op if there isn't a timeout set.
@@ -258,78 +289,108 @@
}
default: {
throw new IllegalStateException("Unknown provider state:"
- + " provider=" + provider
- + ", state=" + providerState.stateEnum);
+ + " provider=" + provider);
}
}
}
void onProviderStateChange(@NonNull ProviderState providerState) {
mThreadingDomain.assertCurrentThread();
- assertProviderKnown(providerState.provider);
+ LocationTimeZoneProvider provider = providerState.provider;
+ assertProviderKnown(provider);
synchronized (mSharedLock) {
switch (providerState.stateEnum) {
case PROVIDER_STATE_DISABLED: {
- // This should never happen: entering disabled does not trigger an event.
+ // This should never happen: entering disabled does not trigger a state change.
warnLog("onProviderStateChange: Unexpected state change for disabled provider,"
- + " providerState=" + providerState);
+ + " provider=" + provider);
break;
}
case PROVIDER_STATE_ENABLED_INITIALIZING:
case PROVIDER_STATE_ENABLED_CERTAIN:
case PROVIDER_STATE_ENABLED_UNCERTAIN: {
- // Entering enabled does not trigger an event, so this only happens if an event
- // is received while the provider is enabled.
- debugLog("onProviderStateChange: Received notification of an event while"
- + " enabled, providerState=" + providerState);
- providerEnabledProcessEvent(providerState);
+ // Entering enabled does not trigger a state change, so this only happens if an
+ // event is received while the provider is enabled.
+ debugLog("onProviderStateChange: Received notification of a state change while"
+ + " enabled, provider=" + provider);
+ handleProviderEnabledStateChange(providerState);
break;
}
case PROVIDER_STATE_PERM_FAILED: {
debugLog("Received notification of permanent failure for"
- + " provider=" + providerState);
- providerFailedProcessEvent();
+ + " provider=" + provider);
+ handleProviderFailedStateChange(providerState);
break;
}
default: {
- warnLog("onProviderStateChange: Unexpected providerState=" + providerState);
+ warnLog("onProviderStateChange: Unexpected provider=" + provider);
}
}
}
}
- private void assertProviderKnown(LocationTimeZoneProvider provider) {
- if (provider != mPrimaryProvider) {
+ private void assertProviderKnown(@NonNull LocationTimeZoneProvider provider) {
+ if (provider != mPrimaryProvider && provider != mSecondaryProvider) {
throw new IllegalArgumentException("Unknown provider: " + provider);
}
}
/**
- * Called when the provider has reported that it has failed permanently.
+ * Called when a provider has reported that it has failed permanently.
*/
@GuardedBy("mSharedLock")
- private void providerFailedProcessEvent() {
- // If the provider is newly perm failed then the controller is uncertain by
- // definition.
- cancelUncertaintyTimeout();
+ private void handleProviderFailedStateChange(@NonNull ProviderState providerState) {
+ LocationTimeZoneProvider failedProvider = providerState.provider;
+ ProviderState primaryCurrentState = mPrimaryProvider.getCurrentState();
+ ProviderState secondaryCurrentState = mSecondaryProvider.getCurrentState();
- // If the provider is now failed, then we must send a suggestion informing the time
- // zone detector that there are no further updates coming in future.
+ // If a provider has failed, the other may need to be enabled.
+ if (failedProvider == mPrimaryProvider) {
+ if (secondaryCurrentState.stateEnum != PROVIDER_STATE_PERM_FAILED) {
+ // The primary must have failed. Try to enable the secondary. This does nothing if
+ // the provider is already enabled, and will leave the provider in
+ // {enabled initializing} if the provider is disabled.
+ tryEnableProvider(mSecondaryProvider, mCurrentUserConfiguration);
+ }
+ } else if (failedProvider == mSecondaryProvider) {
+ // No-op: The secondary will only be active if the primary is uncertain or is failed.
+ // So, there the primary should not need to be enabled when the secondary fails.
+ if (primaryCurrentState.stateEnum != PROVIDER_STATE_ENABLED_UNCERTAIN
+ && primaryCurrentState.stateEnum != PROVIDER_STATE_PERM_FAILED) {
+ warnLog("Secondary provider unexpected reported a failure:"
+ + " failed provider=" + failedProvider.getName()
+ + ", primary provider=" + mPrimaryProvider
+ + ", secondary provider=" + mSecondaryProvider);
+ }
+ }
- GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
- "The provider is permanently failed:"
- + " primary=" + mPrimaryProvider.getCurrentState());
- makeSuggestion(suggestion);
+ // If both providers are now failed, the controller needs to tell the next component in the
+ // time zone detection process.
+ if (primaryCurrentState.stateEnum == PROVIDER_STATE_PERM_FAILED
+ && secondaryCurrentState.stateEnum == PROVIDER_STATE_PERM_FAILED) {
+
+ // If both providers are newly failed then the controller is uncertain by definition
+ // and it will never recover so it can send a suggestion immediately.
+ cancelUncertaintyTimeout();
+
+ // If both providers are now failed, then a suggestion must be sent informing the time
+ // zone detector that there are no further updates coming in future.
+ GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
+ "Both providers are permanently failed:"
+ + " primary=" + primaryCurrentState.provider
+ + ", secondary=" + secondaryCurrentState.provider);
+ makeSuggestion(suggestion);
+ }
}
/**
* Called when a provider has changed state but just moved from one enabled state to another
* enabled state, usually as a result of a new {@link LocationTimeZoneEvent} being received.
- * However, there are rare cases where the event can be null.
+ * However, there are rare cases where the event can also be null.
*/
@GuardedBy("mSharedLock")
- private void providerEnabledProcessEvent(@NonNull ProviderState providerState) {
+ private void handleProviderEnabledStateChange(@NonNull ProviderState providerState) {
LocationTimeZoneProvider provider = providerState.provider;
LocationTimeZoneEvent event = providerState.event;
if (event == null) {
@@ -353,14 +414,15 @@
if (!mCurrentUserConfiguration.getGeoDetectionEnabledBehavior()) {
// This should not happen: the provider should not be in an enabled state if the user
// does not have geodetection enabled.
- warnLog("Provider=" + providerState + " is enabled, but currentUserConfiguration="
- + mCurrentUserConfiguration + " suggests it shouldn't be.");
+ warnLog("Provider=" + provider + " is enabled, but"
+ + " currentUserConfiguration=" + mCurrentUserConfiguration
+ + " suggests it shouldn't be.");
}
switch (event.getEventType()) {
case EVENT_TYPE_PERMANENT_FAILURE: {
- // This shouldn't happen. A provider cannot be enabled and have this event.
- warnLog("Provider=" + providerState
+ // This shouldn't happen. A provider cannot be enabled and have this event type.
+ warnLog("Provider=" + provider
+ " is enabled, but event suggests it shouldn't be");
break;
}
@@ -371,7 +433,7 @@
}
case EVENT_TYPE_SUCCESS: {
handleProviderCertainty(provider, event.getTimeZoneIds(),
- "Event received provider=" + provider.getName() + ", event=" + event);
+ "Event received provider=" + provider + ", event=" + event);
break;
}
default: {
@@ -381,6 +443,9 @@
}
}
+ /**
+ * Called when a provider has become "certain" about the time zone(s).
+ */
@GuardedBy("mSharedLock")
private void handleProviderCertainty(
@NonNull LocationTimeZoneProvider provider,
@@ -389,10 +454,14 @@
// By definition, the controller is now certain.
cancelUncertaintyTimeout();
+ if (provider == mPrimaryProvider) {
+ disableProviderIfEnabled(mSecondaryProvider);
+ }
+
GeolocationTimeZoneSuggestion suggestion =
new GeolocationTimeZoneSuggestion(timeZoneIds);
suggestion.addDebugInfo(reason);
- // Rely on the receiver to dedupe events. It is better to over-communicate.
+ // Rely on the receiver to dedupe suggestions. It is better to over-communicate.
makeSuggestion(suggestion);
}
@@ -415,6 +484,11 @@
mPrimaryProvider.dump(ipw, args);
ipw.decreaseIndent(); // level 2
+ ipw.println("Secondary Provider:");
+ ipw.increaseIndent(); // level 2
+ mSecondaryProvider.dump(ipw, args);
+ ipw.decreaseIndent(); // level 2
+
ipw.decreaseIndent(); // level 1
}
}
@@ -434,48 +508,59 @@
}
/**
- * Indicates a provider has become uncertain with the event (if any) received that indicates
- * that.
+ * Called when a provider has become "uncertain" about the time zone.
*
* <p>A provider is expected to report its uncertainty as soon as it becomes uncertain, as
* this enables the most flexibility for the controller to enable other providers when there are
* multiple ones available. The controller is therefore responsible for deciding when to make a
- * "uncertain" suggestion.
+ * "uncertain" suggestion to the downstream time zone detector.
*
- * <p>This method schedules an "uncertain" suggestion (if one isn't already scheduled) to be
- * made later if nothing else preempts it. It can be preempted if the provider becomes certain
- * (or does anything else that calls {@link #makeSuggestion(GeolocationTimeZoneSuggestion)})
- * within {@link Environment#getUncertaintyDelay()}. Preemption causes the scheduled
- * "uncertain" event to be cancelled. If the provider repeatedly sends uncertainty events within
- * the uncertainty delay period, those events are effectively ignored (i.e. the timer is not
- * reset each time).
+ * <p>This method schedules an "uncertainty" timeout (if one isn't already scheduled) to be
+ * triggered later if nothing else preempts it. It can be preempted if the provider becomes
+ * certain (or does anything else that calls {@link
+ * #makeSuggestion(GeolocationTimeZoneSuggestion)}) within {@link
+ * Environment#getUncertaintyDelay()}. Preemption causes the scheduled
+ * "uncertainty" timeout to be cancelled. If the provider repeatedly sends uncertainty events
+ * within the uncertainty delay period, those events are effectively ignored (i.e. the timeout
+ * is not reset each time).
*/
@GuardedBy("mSharedLock")
- void handleProviderUncertainty(@NonNull LocationTimeZoneProvider provider, String reason) {
+ void handleProviderUncertainty(
+ @NonNull LocationTimeZoneProvider provider, @NonNull String reason) {
Objects.requireNonNull(provider);
- // Start the uncertainty timeout if needed.
+ // Start the uncertainty timeout if needed to ensure the controller will eventually make an
+ // uncertain suggestion if no success event arrives in time to counteract it.
if (!mUncertaintyTimeoutQueue.hasQueued()) {
debugLog("Starting uncertainty timeout: reason=" + reason);
Duration delay = mEnvironment.getUncertaintyDelay();
- mUncertaintyTimeoutQueue.runDelayed(
- this::onProviderUncertaintyTimeout, delay.toMillis());
+ mUncertaintyTimeoutQueue.runDelayed(() -> onProviderUncertaintyTimeout(provider),
+ delay.toMillis());
+ }
+
+ if (provider == mPrimaryProvider) {
+ // (Try to) enable the secondary. It could already be enabled, or enabling might not
+ // succeed if the provider has previously reported it is perm failed. The uncertainty
+ // timeout (set above) is used to ensure that an uncertain suggestion will be made if
+ // the secondary cannot generate a success event in time.
+ tryEnableProvider(mSecondaryProvider, mCurrentUserConfiguration);
}
}
- private void onProviderUncertaintyTimeout() {
+ private void onProviderUncertaintyTimeout(@NonNull LocationTimeZoneProvider provider) {
mThreadingDomain.assertCurrentThread();
synchronized (mSharedLock) {
GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
- "Uncertainty timeout triggered:"
- + " primary=" + mPrimaryProvider.getCurrentState());
+ "Uncertainty timeout triggered for " + provider.getName() + ":"
+ + " primary=" + mPrimaryProvider
+ + ", secondary=" + mSecondaryProvider);
makeSuggestion(suggestion);
}
}
- private static GeolocationTimeZoneSuggestion createUncertainSuggestion(String reason) {
+ private static GeolocationTimeZoneSuggestion createUncertainSuggestion(@NonNull String reason) {
GeolocationTimeZoneSuggestion suggestion = new GeolocationTimeZoneSuggestion(null);
suggestion.addDebugInfo(reason);
return suggestion;
@@ -485,11 +570,13 @@
* Asynchronously passes a {@link SimulatedBinderProviderEvent] to the appropriate provider.
* If the provider name does not match a known provider, then the event is logged and discarded.
*/
- void simulateBinderProviderEvent(SimulatedBinderProviderEvent event) {
+ void simulateBinderProviderEvent(@NonNull SimulatedBinderProviderEvent event) {
String targetProviderName = event.getProviderName();
LocationTimeZoneProvider targetProvider;
if (Objects.equals(mPrimaryProvider.getName(), targetProviderName)) {
targetProvider = mPrimaryProvider;
+ } else if (Objects.equals(mSecondaryProvider.getName(), targetProviderName)) {
+ targetProvider = mSecondaryProvider;
} else {
warnLog("Unable to process simulated binder provider event,"
+ " unknown providerName in event=" + event);
diff --git a/services/core/java/com/android/server/location/timezone/LocationTimeZoneManagerService.java b/services/core/java/com/android/server/location/timezone/LocationTimeZoneManagerService.java
index c9a211d..a8589d4 100644
--- a/services/core/java/com/android/server/location/timezone/LocationTimeZoneManagerService.java
+++ b/services/core/java/com/android/server/location/timezone/LocationTimeZoneManagerService.java
@@ -44,8 +44,8 @@
* are made to the {@link TimeZoneDetectorInternal}, and the {@link LocationTimeZoneProvider}s that
* offer {@link android.location.timezone.LocationTimeZoneEvent}s.
*
- * TODO(b/152744911): This implementation currently only supports a primary provider. Support for a
- * secondary provider must be added in a later commit.
+ * <p>For details of the time zone suggestion behavior, see {@link
+ * LocationTimeZoneProviderController}.
*
* <p>Implementation details:
*
@@ -109,6 +109,7 @@
static final String TAG = "LocationTZDetector";
static final String PRIMARY_PROVIDER_NAME = "primary";
+ static final String SECONDARY_PROVIDER_NAME = "secondary";
private static final String SIMULATION_MODE_SYSTEM_PROPERTY_PREFIX =
"persist.sys.location_tz_simulation_mode.";
@@ -117,6 +118,8 @@
private static final String PRIMARY_LOCATION_TIME_ZONE_SERVICE_ACTION =
"com.android.location.timezone.service.v1.PrimaryLocationTimeZoneProvider";
+ private static final String SECONDARY_LOCATION_TIME_ZONE_SERVICE_ACTION =
+ "com.android.location.timezone.service.v1.SecondaryLocationTimeZoneProvider";
@NonNull private final Context mContext;
@@ -160,8 +163,9 @@
// Called on an arbitrary thread during initialization.
synchronized (mSharedLock) {
LocationTimeZoneProvider primary = createPrimaryProvider();
+ LocationTimeZoneProvider secondary = createSecondaryProvider();
mLocationTimeZoneDetectorController =
- new ControllerImpl(mThreadingDomain, primary);
+ new ControllerImpl(mThreadingDomain, primary, secondary);
ControllerCallbackImpl callback = new ControllerCallbackImpl(mThreadingDomain);
ControllerEnvironmentImpl environment = new ControllerEnvironmentImpl(
mThreadingDomain, mLocationTimeZoneDetectorController);
@@ -178,9 +182,6 @@
if (isInSimulationMode(PRIMARY_PROVIDER_NAME)) {
proxy = new SimulatedLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
} else {
- // TODO Uncomment this code in a later commit.
- throw new UnsupportedOperationException("Not implemented");
- /*
proxy = RealLocationTimeZoneProviderProxy.createAndRegister(
mContext,
mThreadingDomain,
@@ -188,11 +189,31 @@
com.android.internal.R.bool.config_enablePrimaryLocationTimeZoneOverlay,
com.android.internal.R.string.config_primaryLocationTimeZoneProviderPackageName
);
- */
}
return createLocationTimeZoneProvider(PRIMARY_PROVIDER_NAME, proxy);
}
+ private LocationTimeZoneProvider createSecondaryProvider() {
+ LocationTimeZoneProviderProxy proxy;
+ if (isInSimulationMode(SECONDARY_PROVIDER_NAME)) {
+ proxy = new SimulatedLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
+ } else {
+ // TODO Uncomment this code in a later commit.
+ throw new UnsupportedOperationException("Not implemented");
+ /*
+ proxy = RealLocationTimeZoneProviderProxy.createAndRegister(
+ mContext,
+ mThreadingDomain,
+ SECONDARY_LOCATION_TIME_ZONE_SERVICE_ACTION,
+ com.android.internal.R.bool.config_enableSecondaryLocationTimeZoneOverlay,
+ com.android.internal.R.string
+ .config_secondaryLocationTimeZoneProviderPackageName
+ );
+ */
+ }
+ return createLocationTimeZoneProvider(SECONDARY_PROVIDER_NAME, proxy);
+ }
+
private boolean isInSimulationMode(String providerName) {
return SystemProperties.getBoolean(
SIMULATION_MODE_SYSTEM_PROPERTY_PREFIX + providerName, false);
diff --git a/services/core/java/com/android/server/location/timezone/LocationTimeZoneProvider.java b/services/core/java/com/android/server/location/timezone/LocationTimeZoneProvider.java
index 4b0b5a2..4bbda43 100644
--- a/services/core/java/com/android/server/location/timezone/LocationTimeZoneProvider.java
+++ b/services/core/java/com/android/server/location/timezone/LocationTimeZoneProvider.java
@@ -255,7 +255,9 @@
@Override
public String toString() {
- return "State{"
+ // this.provider is omitted deliberately to avoid recursion, since the provider holds
+ // a reference to its state.
+ return "ProviderState{"
+ "stateEnum=" + prettyPrintStateEnum(stateEnum)
+ ", event=" + event
+ ", currentUserConfiguration=" + currentUserConfiguration
diff --git a/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java b/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java
index ef2e349..f1d3723 100644
--- a/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java
+++ b/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java
@@ -21,6 +21,7 @@
import static android.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_UNCERTAIN;
import static com.android.server.location.timezone.LocationTimeZoneManagerService.PRIMARY_PROVIDER_NAME;
+import static com.android.server.location.timezone.LocationTimeZoneManagerService.SECONDARY_PROVIDER_NAME;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -42,7 +43,8 @@
*/
final class SimulatedBinderProviderEvent {
- private static final List<String> VALID_PROVIDER_NAMES = Arrays.asList(PRIMARY_PROVIDER_NAME);
+ private static final List<String> VALID_PROVIDER_NAMES =
+ Arrays.asList(PRIMARY_PROVIDER_NAME, SECONDARY_PROVIDER_NAME);
static final int INJECTED_EVENT_TYPE_ON_BIND = 1;
static final int INJECTED_EVENT_TYPE_ON_UNBIND = 2;
diff --git a/services/core/java/com/android/server/location/util/Injector.java b/services/core/java/com/android/server/location/util/Injector.java
index d9c73ba..6ebce91 100644
--- a/services/core/java/com/android/server/location/util/Injector.java
+++ b/services/core/java/com/android/server/location/util/Injector.java
@@ -17,7 +17,6 @@
package com.android.server.location.util;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.location.LocationRequestStatistics;
/**
* Injects various location dependencies so that they may be controlled by tests.
@@ -55,6 +54,6 @@
/** Returns a LocationUsageLogger. */
LocationUsageLogger getLocationUsageLogger();
- /** Returns a LocationRequestStatistics. */
- LocationRequestStatistics getLocationRequestStatistics();
+ /** Returns a LocationEventLog. */
+ LocationEventLog getLocationEventLog();
}
diff --git a/services/core/java/com/android/server/location/util/LocationEventLog.java b/services/core/java/com/android/server/location/util/LocationEventLog.java
new file mode 100644
index 0000000..e4c354b
--- /dev/null
+++ b/services/core/java/com/android/server/location/util/LocationEventLog.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.location.util;
+
+import static android.os.PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF;
+import static android.os.PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
+import static android.os.PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF;
+import static android.os.PowerManager.LOCATION_MODE_NO_CHANGE;
+import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
+
+import android.annotation.Nullable;
+import android.location.LocationRequest;
+import android.location.util.identity.CallerIdentity;
+import android.os.Build;
+import android.os.PowerManager.LocationPowerSaveMode;
+
+import com.android.internal.location.ProviderRequest;
+import com.android.server.location.LocationManagerService;
+import com.android.server.utils.eventlog.LocalEventLog;
+
+/** In memory event log for location events. */
+public class LocationEventLog extends LocalEventLog {
+
+ private static int getLogSize() {
+ if (Build.IS_DEBUGGABLE || LocationManagerService.D) {
+ return 500;
+ } else {
+ return 200;
+ }
+ }
+
+ private static final int EVENT_LOCATION_ENABLED = 1;
+ private static final int EVENT_PROVIDER_ENABLED = 2;
+ private static final int EVENT_PROVIDER_MOCKED = 3;
+ private static final int EVENT_PROVIDER_REGISTER_CLIENT = 4;
+ private static final int EVENT_PROVIDER_UNREGISTER_CLIENT = 5;
+ private static final int EVENT_PROVIDER_UPDATE_REQUEST = 6;
+ private static final int EVENT_PROVIDER_RECEIVE_LOCATION = 7;
+ private static final int EVENT_PROVIDER_DELIVER_LOCATION = 8;
+ private static final int EVENT_LOCATION_POWER_SAVE_MODE_CHANGE = 9;
+
+ public LocationEventLog() {
+ super(getLogSize());
+ }
+
+ /** Logs a location enabled/disabled event. */
+ public synchronized void logLocationEnabled(int userId, boolean enabled) {
+ addLogEvent(EVENT_LOCATION_POWER_SAVE_MODE_CHANGE, userId, enabled);
+ }
+
+ /** Logs a location provider enabled/disabled event. */
+ public synchronized void logProviderEnabled(String provider, int userId, boolean enabled) {
+ addLogEvent(EVENT_PROVIDER_ENABLED, provider, userId, enabled);
+ }
+
+ /** Logs a location provider being replaced/unreplaced by a mock provider. */
+ public synchronized void logProviderMocked(String provider, boolean mocked) {
+ addLogEvent(EVENT_PROVIDER_MOCKED, provider, mocked);
+ }
+
+ /** Logs a new client registration for a location provider. */
+ public synchronized void logProviderClientRegistered(String provider, CallerIdentity identity,
+ LocationRequest request) {
+ addLogEvent(EVENT_PROVIDER_REGISTER_CLIENT, provider, identity, request);
+ }
+
+ /** Logs a client unregistration for a location provider. */
+ public synchronized void logProviderClientUnregistered(String provider,
+ CallerIdentity identity) {
+ addLogEvent(EVENT_PROVIDER_UNREGISTER_CLIENT, provider, identity);
+ }
+
+ /** Logs a change to the provider request for a location provider. */
+ public synchronized void logProviderUpdateRequest(String provider, ProviderRequest request) {
+ addLogEvent(EVENT_PROVIDER_UPDATE_REQUEST, provider, request);
+ }
+
+ /** Logs a new incoming location for a location provider. */
+ public synchronized void logProviderReceivedLocation(String provider) {
+ addLogEvent(EVENT_PROVIDER_RECEIVE_LOCATION, provider);
+ }
+
+ /** Logs a location deliver for a client of a location provider. */
+ public synchronized void logProviderDeliveredLocation(String provider,
+ CallerIdentity identity) {
+ addLogEvent(EVENT_PROVIDER_DELIVER_LOCATION, provider, identity);
+ }
+
+ /** Logs that the location power save mode has changed. */
+ public synchronized void logLocationPowerSaveMode(
+ @LocationPowerSaveMode int locationPowerSaveMode) {
+ addLogEvent(EVENT_LOCATION_POWER_SAVE_MODE_CHANGE, locationPowerSaveMode);
+ }
+
+ @Override
+ protected LogEvent createLogEvent(long timeDelta, int event, Object... args) {
+ switch (event) {
+ case EVENT_LOCATION_ENABLED:
+ return new LocationEnabledEvent(timeDelta, (Integer) args[1], (Boolean) args[2]);
+ case EVENT_PROVIDER_ENABLED:
+ return new ProviderEnabledEvent(timeDelta, (String) args[0], (Integer) args[1],
+ (Boolean) args[2]);
+ case EVENT_PROVIDER_MOCKED:
+ return new ProviderMockedEvent(timeDelta, (String) args[0], (Boolean) args[1]);
+ case EVENT_PROVIDER_REGISTER_CLIENT:
+ return new ProviderRegisterEvent(timeDelta, (String) args[0], true,
+ (CallerIdentity) args[1], (LocationRequest) args[2]);
+ case EVENT_PROVIDER_UNREGISTER_CLIENT:
+ return new ProviderRegisterEvent(timeDelta, (String) args[0], false,
+ (CallerIdentity) args[1], null);
+ case EVENT_PROVIDER_UPDATE_REQUEST:
+ return new ProviderUpdateEvent(timeDelta, (String) args[0],
+ (ProviderRequest) args[1]);
+ case EVENT_PROVIDER_RECEIVE_LOCATION:
+ return new ProviderReceiveLocationEvent(timeDelta, (String) args[0]);
+ case EVENT_PROVIDER_DELIVER_LOCATION:
+ return new ProviderDeliverLocationEvent(timeDelta, (String) args[0],
+ (CallerIdentity) args[1]);
+ case EVENT_LOCATION_POWER_SAVE_MODE_CHANGE:
+ return new LocationPowerSaveModeEvent(timeDelta, (Integer) args[0]);
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ private static class ProviderEnabledEvent extends LogEvent {
+
+ private final String mProvider;
+ private final int mUserId;
+ private final boolean mEnabled;
+
+ protected ProviderEnabledEvent(long timeDelta, String provider, int userId,
+ boolean enabled) {
+ super(timeDelta);
+ mProvider = provider;
+ mUserId = userId;
+ mEnabled = enabled;
+ }
+
+ @Override
+ public String getLogString() {
+ return mProvider + " provider [u" + mUserId + "] " + (mEnabled ? "enabled"
+ : "disabled");
+ }
+ }
+
+ private static class ProviderMockedEvent extends LogEvent {
+
+ private final String mProvider;
+ private final boolean mMocked;
+
+ protected ProviderMockedEvent(long timeDelta, String provider, boolean mocked) {
+ super(timeDelta);
+ mProvider = provider;
+ mMocked = mocked;
+ }
+
+ @Override
+ public String getLogString() {
+ if (mMocked) {
+ return mProvider + " provider added mock provider override";
+ } else {
+ return mProvider + " provider removed mock provider override";
+ }
+ }
+ }
+
+ private static class ProviderRegisterEvent extends LogEvent {
+
+ private final String mProvider;
+ private final boolean mRegistered;
+ private final CallerIdentity mIdentity;
+ @Nullable private final LocationRequest mLocationRequest;
+
+ private ProviderRegisterEvent(long timeDelta, String provider, boolean registered,
+ CallerIdentity identity, @Nullable LocationRequest locationRequest) {
+ super(timeDelta);
+ mProvider = provider;
+ mRegistered = registered;
+ mIdentity = identity;
+ mLocationRequest = locationRequest;
+ }
+
+ @Override
+ public String getLogString() {
+ if (mRegistered) {
+ return mProvider + " provider " + "+registration " + mIdentity + " -> "
+ + mLocationRequest;
+ } else {
+ return mProvider + " provider " + "-registration " + mIdentity;
+ }
+ }
+ }
+
+ private static class ProviderUpdateEvent extends LogEvent {
+
+ private final String mProvider;
+ private final ProviderRequest mRequest;
+
+ private ProviderUpdateEvent(long timeDelta, String provider, ProviderRequest request) {
+ super(timeDelta);
+ mProvider = provider;
+ mRequest = request;
+ }
+
+ @Override
+ public String getLogString() {
+ return mProvider + " provider request = " + mRequest;
+ }
+ }
+
+ private static class ProviderReceiveLocationEvent extends LogEvent {
+
+ private final String mProvider;
+
+ private ProviderReceiveLocationEvent(long timeDelta, String provider) {
+ super(timeDelta);
+ mProvider = provider;
+ }
+
+ @Override
+ public String getLogString() {
+ return mProvider + " provider received location";
+ }
+ }
+
+ private static class ProviderDeliverLocationEvent extends LogEvent {
+
+ private final String mProvider;
+ @Nullable private final CallerIdentity mIdentity;
+
+ private ProviderDeliverLocationEvent(long timeDelta, String provider,
+ @Nullable CallerIdentity identity) {
+ super(timeDelta);
+ mProvider = provider;
+ mIdentity = identity;
+ }
+
+ @Override
+ public String getLogString() {
+ return mProvider + " provider delivered location to " + mIdentity;
+ }
+ }
+
+ private static class LocationPowerSaveModeEvent extends LogEvent {
+
+ @LocationPowerSaveMode
+ private final int mLocationPowerSaveMode;
+
+ private LocationPowerSaveModeEvent(long timeDelta,
+ @LocationPowerSaveMode int locationPowerSaveMode) {
+ super(timeDelta);
+ mLocationPowerSaveMode = locationPowerSaveMode;
+ }
+
+ @Override
+ public String getLogString() {
+ String mode;
+ switch (mLocationPowerSaveMode) {
+ case LOCATION_MODE_NO_CHANGE:
+ mode = "NO_CHANGE";
+ break;
+ case LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
+ mode = "GPS_DISABLED_WHEN_SCREEN_OFF";
+ break;
+ case LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
+ mode = "ALL_DISABLED_WHEN_SCREEN_OFF";
+ break;
+ case LOCATION_MODE_FOREGROUND_ONLY:
+ mode = "FOREGROUND_ONLY";
+ break;
+ case LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF:
+ mode = "THROTTLE_REQUESTS_WHEN_SCREEN_OFF";
+ break;
+ default:
+ mode = "UNKNOWN";
+ break;
+ }
+ return "location power save mode changed to " + mode;
+ }
+ }
+
+ private static class LocationEnabledEvent extends LogEvent {
+
+ private final int mUserId;
+ private final boolean mEnabled;
+
+ private LocationEnabledEvent(long timeDelta, int userId, boolean enabled) {
+ super(timeDelta);
+ mUserId = userId;
+ mEnabled = enabled;
+ }
+
+ @Override
+ public String getLogString() {
+ return "[u" + mUserId + "] location setting " + (mEnabled ? "enabled" : "disabled");
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/location/util/LocationPowerSaveModeHelper.java b/services/core/java/com/android/server/location/util/LocationPowerSaveModeHelper.java
index a9a8c50..6e4cf06 100644
--- a/services/core/java/com/android/server/location/util/LocationPowerSaveModeHelper.java
+++ b/services/core/java/com/android/server/location/util/LocationPowerSaveModeHelper.java
@@ -16,7 +16,13 @@
package com.android.server.location.util;
+import static android.os.PowerManager.locationPowerSaveModeToString;
+
+import static com.android.server.location.LocationManagerService.D;
+import static com.android.server.location.LocationManagerService.TAG;
+
import android.os.PowerManager.LocationPowerSaveMode;
+import android.util.Log;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -35,9 +41,11 @@
void onLocationPowerSaveModeChanged(@LocationPowerSaveMode int locationPowerSaveMode);
}
+ private final LocationEventLog mLocationEventLog;
private final CopyOnWriteArrayList<LocationPowerSaveModeChangedListener> mListeners;
- public LocationPowerSaveModeHelper() {
+ public LocationPowerSaveModeHelper(LocationEventLog locationEventLog) {
+ mLocationEventLog = locationEventLog;
mListeners = new CopyOnWriteArrayList<>();
}
@@ -58,6 +66,12 @@
protected final void notifyLocationPowerSaveModeChanged(
@LocationPowerSaveMode int locationPowerSaveMode) {
+ if (D) {
+ Log.d(TAG, "location power save mode is now " + locationPowerSaveModeToString(
+ locationPowerSaveMode));
+ }
+ mLocationEventLog.logLocationPowerSaveMode(locationPowerSaveMode);
+
for (LocationPowerSaveModeChangedListener listener : mListeners) {
listener.onLocationPowerSaveModeChanged(locationPowerSaveMode);
}
diff --git a/services/core/java/com/android/server/location/util/ScreenInteractiveHelper.java b/services/core/java/com/android/server/location/util/ScreenInteractiveHelper.java
index d47bce3..ecd6966 100644
--- a/services/core/java/com/android/server/location/util/ScreenInteractiveHelper.java
+++ b/services/core/java/com/android/server/location/util/ScreenInteractiveHelper.java
@@ -16,6 +16,11 @@
package com.android.server.location.util;
+import static com.android.server.location.LocationManagerService.D;
+import static com.android.server.location.LocationManagerService.TAG;
+
+import android.util.Log;
+
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -55,6 +60,10 @@
}
protected final void notifyScreenInteractiveChanged(boolean interactive) {
+ if (D) {
+ Log.d(TAG, "screen interactive is now " + interactive);
+ }
+
for (ScreenInteractiveChangedListener listener : mListeners) {
listener.onScreenInteractiveChanged(interactive);
}
diff --git a/services/core/java/com/android/server/location/util/SystemLocationPowerSaveModeHelper.java b/services/core/java/com/android/server/location/util/SystemLocationPowerSaveModeHelper.java
index c8d8202..3129eba 100644
--- a/services/core/java/com/android/server/location/util/SystemLocationPowerSaveModeHelper.java
+++ b/services/core/java/com/android/server/location/util/SystemLocationPowerSaveModeHelper.java
@@ -41,7 +41,8 @@
@LocationPowerSaveMode
private volatile int mLocationPowerSaveMode;
- public SystemLocationPowerSaveModeHelper(Context context) {
+ public SystemLocationPowerSaveModeHelper(Context context, LocationEventLog locationEventLog) {
+ super(locationEventLog);
mContext = context;
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 0450e5b..2992877 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -587,7 +587,7 @@
private final NetworkPolicyLogger mLogger = new NetworkPolicyLogger();
- /** List of apps indexed by appId and whether they have the internet permission */
+ /** List of apps indexed by uid and whether they have the internet permission */
@GuardedBy("mUidRulesFirstLock")
private final SparseBooleanArray mInternetPermissionMap = new SparseBooleanArray();
@@ -973,7 +973,7 @@
if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
// Clear the cache for the app
synchronized (mUidRulesFirstLock) {
- mInternetPermissionMap.delete(UserHandle.getAppId(uid));
+ mInternetPermissionMap.delete(uid);
updateRestrictionRulesForUidUL(uid);
}
}
@@ -4203,16 +4203,14 @@
@GuardedBy("mUidRulesFirstLock")
private boolean hasInternetPermissionUL(int uid) {
try {
- final int appId = UserHandle.getAppId(uid);
- final boolean hasPermission;
- if (mInternetPermissionMap.indexOfKey(appId) < 0) {
- hasPermission =
- mIPm.checkUidPermission(Manifest.permission.INTERNET, uid)
- == PackageManager.PERMISSION_GRANTED;
- mInternetPermissionMap.put(appId, hasPermission);
- } else {
- hasPermission = mInternetPermissionMap.get(appId);
+ if (mInternetPermissionMap.get(uid)) {
+ return true;
}
+ // If the cache shows that uid doesn't have internet permission,
+ // then always re-check with PackageManager just to be safe.
+ final boolean hasPermission = mIPm.checkUidPermission(Manifest.permission.INTERNET,
+ uid) == PackageManager.PERMISSION_GRANTED;
+ mInternetPermissionMap.put(uid, hasPermission);
return hasPermission;
} catch (RemoteException e) {
}
diff --git a/services/core/java/com/android/server/notification/EventConditionProvider.java b/services/core/java/com/android/server/notification/EventConditionProvider.java
index a4a94c2..25ad9280 100644
--- a/services/core/java/com/android/server/notification/EventConditionProvider.java
+++ b/services/core/java/com/android/server/notification/EventConditionProvider.java
@@ -271,7 +271,7 @@
new Intent(ACTION_EVALUATE)
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
.putExtra(EXTRA_TIME, time),
- PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
alarms.cancel(pendingIntent);
if (time == 0 || time < now) {
if (DEBUG) Slog.d(TAG, "Not scheduling evaluate: " + (time == 0 ? "no time specified"
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b4c98e0..4da5fad2 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3084,6 +3084,8 @@
UserHandle.getUserId(uid), REASON_PACKAGE_BANNED, null);
}
+ mAppOps.setMode(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg,
+ enabled ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
try {
getContext().sendBroadcastAsUser(
new Intent(ACTION_APP_BLOCK_STATE_CHANGED)
@@ -5247,7 +5249,8 @@
Intent appIntent = getContext().getPackageManager().getLaunchIntentForPackage(pkg);
if (appIntent != null) {
summaryNotification.contentIntent = PendingIntent.getActivityAsUser(
- getContext(), 0, appIntent, 0, null, UserHandle.of(userId));
+ getContext(), 0, appIntent, PendingIntent.FLAG_IMMUTABLE, null,
+ UserHandle.of(userId));
}
final StatusBarNotification summarySbn =
new StatusBarNotification(adjustedSbn.getPackageName(),
@@ -6830,7 +6833,7 @@
.appendPath(record.getKey()).build())
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
.putExtra(EXTRA_KEY, record.getKey()),
- PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + record.getNotification().getTimeoutAfter(), pi);
}
diff --git a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
index 961d3db..3517033 100644
--- a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
+++ b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
@@ -223,7 +223,7 @@
new Intent(ACTION_EVALUATE)
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
.putExtra(EXTRA_TIME, time),
- PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
alarms.cancel(pendingIntent);
if (time > now) {
if (DEBUG) Slog.d(TAG, String.format("Scheduling evaluate for %s, in %s, now=%s",
diff --git a/services/core/java/com/android/server/pm/IncrementalStates.java b/services/core/java/com/android/server/pm/IncrementalStates.java
new file mode 100644
index 0000000..dda5faf
--- /dev/null
+++ b/services/core/java/com/android/server/pm/IncrementalStates.java
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.content.pm.IDataLoaderStatusListener;
+import android.content.pm.IncrementalStatesInfo;
+import android.content.pm.PackageManager;
+import android.os.Handler;
+import android.os.incremental.IStorageHealthListener;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.function.pooled.PooledLambda;
+
+import java.util.function.BiConsumer;
+
+/**
+ * Manages state transitions of a package installed on Incremental File System. Currently manages:
+ * 1. startable state (whether a package is allowed to be launched), and
+ * 2. loading state (whether a package is still loading or has been fully loaded).
+ *
+ * The following events might change the states of a package:
+ * 1. Installation commit
+ * 2. Incremental storage health
+ * 3. Data loader stream health
+ * 4. Loading progress changes
+ *
+ * @hide
+ */
+public final class IncrementalStates {
+ private static final String TAG = "IncrementalStates";
+ private static final boolean DEBUG = false;
+ private final Handler mHandler = BackgroundThread.getHandler();
+ private final Object mLock = new Object();
+ @GuardedBy("mLock")
+ private int mStreamStatus = IDataLoaderStatusListener.STREAM_HEALTHY;
+ @GuardedBy("mLock")
+ private int mStorageHealthStatus = IStorageHealthListener.HEALTH_STATUS_OK;
+ @GuardedBy("mLock")
+ private final LoadingState mLoadingState;
+ @GuardedBy("mLock")
+ private StartableState mStartableState;
+ @GuardedBy("mLock")
+ private Callback mCallback = null;
+ private final BiConsumer<Integer, Integer> mStatusConsumer;
+
+ public IncrementalStates() {
+ // By default the package is not startable and not fully loaded (i.e., is loading)
+ this(false, true);
+ }
+
+ public IncrementalStates(boolean isStartable, boolean isLoading) {
+ mStartableState = new StartableState(isStartable);
+ mLoadingState = new LoadingState(isLoading);
+ mStatusConsumer = new StatusConsumer();
+ }
+
+ /**
+ * Callback interface to report that the startable state of this package has changed.
+ */
+ public interface Callback {
+ /**
+ * Reports that the package is now unstartable and the unstartable reason.
+ */
+ void onPackageUnstartable(int reason);
+
+ /**
+ * Reports that the package is now startable.
+ */
+ void onPackageStartable();
+
+ /**
+ * Reports that package is fully loaded.
+ */
+ void onPackageFullyLoaded();
+ }
+
+ /**
+ * By calling this method, the caller indicates that package installation has just been
+ * committed. The package becomes startable. Set the initial loading state after the package
+ * is committed. Incremental packages are by-default loading; non-Incremental packages are not.
+ *
+ * @param isIncremental whether a package is installed on Incremental or not.
+ */
+ public void onCommit(boolean isIncremental) {
+ if (DEBUG) {
+ Slog.i(TAG, "received package commit event");
+ }
+ synchronized (mLock) {
+ if (!mStartableState.isStartable()) {
+ mStartableState.adoptNewStartableStateLocked(true);
+ }
+ if (mLoadingState.isLoading() != isIncremental) {
+ mLoadingState.adoptNewLoadingStateLocked(isIncremental);
+ }
+ }
+ mHandler.post(PooledLambda.obtainRunnable(
+ IncrementalStates::reportStartableState,
+ IncrementalStates.this).recycleOnUse());
+ if (!isIncremental) {
+ mHandler.post(PooledLambda.obtainRunnable(
+ IncrementalStates::reportFullyLoaded,
+ IncrementalStates.this).recycleOnUse());
+ }
+ }
+
+ private void reportStartableState() {
+ final Callback callback;
+ final boolean startable;
+ final int reason;
+ synchronized (mLock) {
+ callback = mCallback;
+ startable = mStartableState.isStartable();
+ reason = mStartableState.getUnstartableReason();
+ }
+ if (callback == null) {
+ return;
+ }
+ if (startable) {
+ callback.onPackageStartable();
+ } else {
+ callback.onPackageUnstartable(reason);
+ }
+ }
+
+ private void reportFullyLoaded() {
+ final Callback callback;
+ synchronized (mLock) {
+ callback = mCallback;
+ }
+ if (callback != null) {
+ callback.onPackageFullyLoaded();
+ }
+ }
+
+ private class StatusConsumer implements BiConsumer<Integer, Integer> {
+ @Override
+ public void accept(Integer streamStatus, Integer storageStatus) {
+ if (streamStatus == null && storageStatus == null) {
+ return;
+ }
+ final boolean oldState, newState;
+ synchronized (mLock) {
+ if (!mLoadingState.isLoading()) {
+ // Do nothing if the package is already fully loaded
+ return;
+ }
+ oldState = mStartableState.isStartable();
+ if (streamStatus != null) {
+ mStreamStatus = (Integer) streamStatus;
+ }
+ if (storageStatus != null) {
+ mStorageHealthStatus = (Integer) storageStatus;
+ }
+ updateStartableStateLocked();
+ newState = mStartableState.isStartable();
+ }
+ if (oldState != newState) {
+ mHandler.post(PooledLambda.obtainRunnable(IncrementalStates::reportStartableState,
+ IncrementalStates.this).recycleOnUse());
+ }
+ }
+ };
+
+ /**
+ * By calling this method, the caller indicates that there issues with the Incremental
+ * Storage,
+ * on which the package is installed. The state will change according to the status
+ * code defined in {@code IStorageHealthListener}.
+ */
+ public void onStorageHealthStatusChanged(int storageHealthStatus) {
+ if (DEBUG) {
+ Slog.i(TAG, "received storage health status changed event : storageHealthStatus="
+ + storageHealthStatus);
+ }
+ mStatusConsumer.accept(null, storageHealthStatus);
+ }
+
+ /**
+ * By calling this method, the caller indicates that the stream status of the package has
+ * been
+ * changed. This could indicate a streaming error. The state will change according to the
+ * status
+ * code defined in {@code IDataLoaderStatusListener}.
+ */
+ public void onStreamStatusChanged(int streamState) {
+ if (DEBUG) {
+ Slog.i(TAG, "received stream status changed event : streamState=" + streamState);
+ }
+ mStatusConsumer.accept(streamState, null);
+ }
+
+ /**
+ * Use the specified callback to report state changing events.
+ *
+ * @param callback Object to report new state.
+ */
+ public void setCallback(Callback callback) {
+ if (DEBUG) {
+ Slog.i(TAG, "registered callback");
+ }
+ synchronized (mLock) {
+ mCallback = callback;
+ }
+ }
+
+ /**
+ * Update the package loading progress to specified value. This might change startable state.
+ *
+ * @param progress Value between [0, 1].
+ */
+ public void setProgress(float progress) {
+ final boolean newLoadingState;
+ final boolean oldStartableState, newStartableState;
+ synchronized (mLock) {
+ oldStartableState = mStartableState.isStartable();
+ updateProgressLocked(progress);
+ newLoadingState = mLoadingState.isLoading();
+ newStartableState = mStartableState.isStartable();
+ }
+ if (!newLoadingState) {
+ mHandler.post(PooledLambda.obtainRunnable(
+ IncrementalStates::reportFullyLoaded,
+ IncrementalStates.this).recycleOnUse());
+ }
+ if (newStartableState != oldStartableState) {
+ mHandler.post(PooledLambda.obtainRunnable(
+ IncrementalStates::reportStartableState,
+ IncrementalStates.this).recycleOnUse());
+ }
+ }
+
+ /**
+ * @return the current startable state.
+ */
+ public boolean isStartable() {
+ synchronized (mLock) {
+ return mStartableState.isStartable();
+ }
+ }
+
+ /**
+ * @return Whether the package is still being loaded or has been fully loaded.
+ */
+ public boolean isLoading() {
+ synchronized (mLock) {
+ return mLoadingState.isLoading();
+ }
+ }
+
+ /**
+ * @return all current states in a Parcelable.
+ */
+ public IncrementalStatesInfo getIncrementalStatesInfo() {
+ synchronized (mLock) {
+ return new IncrementalStatesInfo(mStartableState.isStartable(),
+ mLoadingState.isLoading(),
+ mLoadingState.getProgress());
+ }
+ }
+
+ /**
+ * Determine the next state based on the current state, current stream status and storage
+ * health
+ * status. If the next state is different from the current state, proceed with state
+ * change.
+ */
+ private void updateStartableStateLocked() {
+ final boolean currentState = mStartableState.isStartable();
+ boolean nextState = currentState;
+ if (!currentState) {
+ if (mStorageHealthStatus == IStorageHealthListener.HEALTH_STATUS_OK
+ && mStreamStatus == IDataLoaderStatusListener.STREAM_HEALTHY) {
+ // change from unstartable -> startable when both stream and storage are healthy
+ nextState = true;
+ }
+ } else {
+ if (mStorageHealthStatus == IStorageHealthListener.HEALTH_STATUS_UNHEALTHY) {
+ // unrecoverable if storage is unhealthy
+ nextState = false;
+ } else {
+ switch (mStreamStatus) {
+ case IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR:
+ // unrecoverable, fall through
+ case IDataLoaderStatusListener.STREAM_SOURCE_ERROR: {
+ // unrecoverable
+ nextState = false;
+ break;
+ }
+ case IDataLoaderStatusListener.STREAM_STORAGE_ERROR: {
+ if (mStorageHealthStatus != IStorageHealthListener.HEALTH_STATUS_OK) {
+ // unrecoverable if there is a pending read AND storage is limited
+ nextState = false;
+ }
+ break;
+ }
+ default:
+ // anything else, remain startable
+ break;
+ }
+ }
+ }
+ if (nextState == currentState) {
+ return;
+ }
+ mStartableState.adoptNewStartableStateLocked(nextState);
+ }
+
+ private void updateProgressLocked(float progress) {
+ if (DEBUG) {
+ Slog.i(TAG, "received progress update: " + progress);
+ }
+ mLoadingState.setProgress(progress);
+ if (1 - progress < 0.001) {
+ if (DEBUG) {
+ Slog.i(TAG, "package is fully loaded");
+ }
+ mLoadingState.setProgress(1);
+ if (mLoadingState.isLoading()) {
+ mLoadingState.adoptNewLoadingStateLocked(false);
+ }
+ // Also updates startable state if necessary
+ if (!mStartableState.isStartable()) {
+ mStartableState.adoptNewStartableStateLocked(true);
+ }
+ }
+ }
+
+ private class StartableState {
+ private boolean mIsStartable;
+ private int mUnstartableReason = PackageManager.UNSTARTABLE_REASON_UNKNOWN;
+
+ StartableState(boolean isStartable) {
+ mIsStartable = isStartable;
+ }
+
+ public boolean isStartable() {
+ return mIsStartable;
+ }
+
+ public int getUnstartableReason() {
+ return mUnstartableReason;
+ }
+
+ public void adoptNewStartableStateLocked(boolean nextState) {
+ if (DEBUG) {
+ Slog.i(TAG, "startable state changed from " + mIsStartable + " to " + nextState);
+ }
+ mIsStartable = nextState;
+ mUnstartableReason = getUnstartableReasonLocked();
+ }
+
+ private int getUnstartableReasonLocked() {
+ if (mIsStartable) {
+ return PackageManager.UNSTARTABLE_REASON_UNKNOWN;
+ }
+ // Translate stream status to reason for unstartable state
+ switch (mStreamStatus) {
+ case IDataLoaderStatusListener.STREAM_TRANSPORT_ERROR:
+ // fall through
+ case IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR:
+ // fall through
+ case IDataLoaderStatusListener.STREAM_SOURCE_ERROR: {
+ return PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT;
+ }
+ case IDataLoaderStatusListener.STREAM_STORAGE_ERROR: {
+ return PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE;
+ }
+ default:
+ return PackageManager.UNSTARTABLE_REASON_UNKNOWN;
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof StartableState)) {
+ return false;
+ }
+ StartableState l = (StartableState) o;
+ return l.mIsStartable == mIsStartable;
+ }
+
+ @Override
+ public int hashCode() {
+ return Boolean.hashCode(mIsStartable);
+ }
+ }
+
+ private class LoadingState {
+ private boolean mIsLoading;
+ private float mProgress;
+
+ LoadingState(boolean isLoading) {
+ mIsLoading = isLoading;
+ mProgress = isLoading ? 0 : 1;
+ }
+
+ public boolean isLoading() {
+ return mIsLoading;
+ }
+
+ public float getProgress() {
+ return mProgress;
+ }
+
+ public void setProgress(float progress) {
+ mProgress = progress;
+ }
+
+ public void adoptNewLoadingStateLocked(boolean nextState) {
+ if (DEBUG) {
+ Slog.i(TAG, "Loading state changed from " + mIsLoading + " to " + nextState);
+ }
+ mIsLoading = nextState;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof LoadingState)) {
+ return false;
+ }
+ LoadingState l = (LoadingState) o;
+ return l.mIsLoading == mIsLoading && l.mProgress == mProgress;
+ }
+
+ @Override
+ public int hashCode() {
+ int hashCode = Boolean.hashCode(mIsLoading);
+ hashCode = 31 * hashCode + Float.hashCode(mProgress);
+ return hashCode;
+ }
+ }
+
+
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof IncrementalStates)) {
+ return false;
+ }
+ IncrementalStates l = (IncrementalStates) o;
+ return l.mStorageHealthStatus == mStorageHealthStatus
+ && l.mStreamStatus == mStreamStatus
+ && l.mStartableState.equals(mStartableState)
+ && l.mLoadingState.equals(mLoadingState);
+ }
+
+ @Override
+ public int hashCode() {
+ int hashCode = mStartableState.hashCode();
+ hashCode = 31 * hashCode + mLoadingState.hashCode();
+ hashCode = 31 * hashCode + mStorageHealthStatus;
+ hashCode = 31 * hashCode + mStreamStatus;
+ return hashCode;
+ }
+}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 949dcb25..2aafe9a 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -141,6 +141,7 @@
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.dex.DexManager;
@@ -1086,6 +1087,23 @@
}
}
+ private ParcelFileDescriptor openTargetInternal(String path, int flags, int mode)
+ throws IOException, ErrnoException {
+ // TODO: this should delegate to DCS so the system process avoids
+ // holding open FDs into containers.
+ final FileDescriptor fd = Os.open(path, flags, mode);
+ return new ParcelFileDescriptor(fd);
+ }
+
+ private ParcelFileDescriptor createRevocableFdInternal(RevocableFileDescriptor fd,
+ ParcelFileDescriptor pfd) throws IOException {
+ int releasedFdInt = pfd.detachFd();
+ FileDescriptor releasedFd = new FileDescriptor();
+ releasedFd.setInt$(releasedFdInt);
+ fd.init(mContext, releasedFd);
+ return fd.getRevocableFileDescriptor();
+ }
+
private ParcelFileDescriptor doWriteInternal(String name, long offsetBytes, long lengthBytes,
ParcelFileDescriptor incomingFd) throws IOException {
// Quick validity check of state, and allocate a pipe for ourselves. We
@@ -1118,21 +1136,20 @@
Binder.restoreCallingIdentity(identity);
}
- // TODO: this should delegate to DCS so the system process avoids
- // holding open FDs into containers.
- final FileDescriptor targetFd = Os.open(target.getAbsolutePath(),
+ ParcelFileDescriptor targetPfd = openTargetInternal(target.getAbsolutePath(),
O_CREAT | O_WRONLY, 0644);
Os.chmod(target.getAbsolutePath(), 0644);
// If caller specified a total length, allocate it for them. Free up
// cache space to grow, if needed.
if (stageDir != null && lengthBytes > 0) {
- mContext.getSystemService(StorageManager.class).allocateBytes(targetFd, lengthBytes,
+ mContext.getSystemService(StorageManager.class).allocateBytes(
+ targetPfd.getFileDescriptor(), lengthBytes,
PackageHelper.translateAllocateFlags(params.installFlags));
}
if (offsetBytes > 0) {
- Os.lseek(targetFd, offsetBytes, OsConstants.SEEK_SET);
+ Os.lseek(targetPfd.getFileDescriptor(), offsetBytes, OsConstants.SEEK_SET);
}
if (incomingFd != null) {
@@ -1142,8 +1159,9 @@
// inserted above to hold the session active.
try {
final Int64Ref last = new Int64Ref(0);
- FileUtils.copy(incomingFd.getFileDescriptor(), targetFd, lengthBytes, null,
- Runnable::run, (long progress) -> {
+ FileUtils.copy(incomingFd.getFileDescriptor(), targetPfd.getFileDescriptor(),
+ lengthBytes, null, Runnable::run,
+ (long progress) -> {
if (params.sizeBytes > 0) {
final long delta = progress - last.value;
last.value = progress;
@@ -1154,7 +1172,7 @@
}
});
} finally {
- IoUtils.closeQuietly(targetFd);
+ IoUtils.closeQuietly(targetPfd);
IoUtils.closeQuietly(incomingFd);
// We're done here, so remove the "bridge" that was holding
@@ -1170,12 +1188,11 @@
}
return null;
} else if (PackageInstaller.ENABLE_REVOCABLE_FD) {
- fd.init(mContext, targetFd);
- return fd.getRevocableFileDescriptor();
+ return createRevocableFdInternal(fd, targetPfd);
} else {
- bridge.setTargetFile(targetFd);
+ bridge.setTargetFile(targetPfd);
bridge.start();
- return new ParcelFileDescriptor(bridge.getClientSocket());
+ return bridge.getClientSocket();
}
} catch (ErrnoException e) {
@@ -1684,20 +1701,26 @@
}
}
- private void onStorageUnhealthy() {
+ private void onStorageHealthStatusChanged(int status) {
final String packageName = getPackageName();
if (TextUtils.isEmpty(packageName)) {
// The package has not been installed.
return;
}
- final PackageManagerService packageManagerService = mPm;
- mHandler.post(() -> {
- if (packageManagerService.deletePackageX(packageName,
- PackageManager.VERSION_CODE_HIGHEST, UserHandle.USER_SYSTEM,
- PackageManager.DELETE_ALL_USERS) != PackageManager.DELETE_SUCCEEDED) {
- Slog.e(TAG, "Failed to uninstall package with failed dataloader: " + packageName);
- }
- });
+ mHandler.post(PooledLambda.obtainRunnable(
+ PackageManagerService::onStorageHealthStatusChanged,
+ mPm, packageName, status, userId).recycleOnUse());
+ }
+
+ private void onStreamHealthStatusChanged(int status) {
+ final String packageName = getPackageName();
+ if (TextUtils.isEmpty(packageName)) {
+ // The package has not been installed.
+ return;
+ }
+ mHandler.post(PooledLambda.obtainRunnable(
+ PackageManagerService::onStreamStatusChanged,
+ mPm, packageName, status, userId).recycleOnUse());
}
/**
@@ -3245,7 +3268,9 @@
if (isDestroyedOrDataLoaderFinished) {
switch (status) {
case IDataLoaderStatusListener.DATA_LOADER_UNRECOVERABLE:
- onStorageUnhealthy();
+ // treat as unhealthy storage
+ onStorageHealthStatusChanged(
+ IStorageHealthListener.HEALTH_STATUS_UNHEALTHY);
return;
}
return;
@@ -3342,6 +3367,16 @@
sendPendingStreaming(mContext, statusReceiver, sessionId, e.getMessage());
}
}
+ @Override
+ public void reportStreamHealth(int dataLoaderId, int streamStatus) {
+ synchronized (mLock) {
+ if (!mDestroyed && !mDataLoaderFinished) {
+ // ignore streaming status if package isn't installed
+ return;
+ }
+ }
+ onStreamHealthStatusChanged(streamStatus);
+ }
};
if (!manualStartAndDestroy) {
@@ -3361,11 +3396,7 @@
}
if (isDestroyedOrDataLoaderFinished) {
// App's installed.
- switch (status) {
- case IStorageHealthListener.HEALTH_STATUS_UNHEALTHY:
- onStorageUnhealthy();
- return;
- }
+ onStorageHealthStatusChanged(status);
return;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 67f218e..cc1ef86 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -20,10 +20,8 @@
import static android.Manifest.permission.INSTALL_PACKAGES;
import static android.Manifest.permission.MANAGE_DEVICE_ADMINS;
import static android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS;
-import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.REQUEST_DELETE_PACKAGES;
import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS;
-import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.MODE_IGNORED;
@@ -92,7 +90,6 @@
import static android.content.pm.PackageManager.MOVE_FAILED_LOCKED_USER;
import static android.content.pm.PackageManager.MOVE_FAILED_OPERATION_PENDING;
import static android.content.pm.PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
-import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.pm.PackageManager.RESTRICTION_NONE;
import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
@@ -3779,6 +3776,8 @@
PackageParser.readConfigUseRoundIcon(mContext.getResources());
mServiceStartWithDelay = SystemClock.uptimeMillis() + (60 * 1000L);
+
+ Slog.i(TAG, "Fix for b/169414761 is applied");
}
/**
@@ -16390,12 +16389,24 @@
} else if (!previousUserIds.contains(userId)) {
ps.setInstallReason(installReason, userId);
}
+
+ // TODO(b/169721400): generalize Incremental States and create a Callback object
+ // that can be used for all the packages.
+ final IncrementalStatesCallback incrementalStatesCallback =
+ new IncrementalStatesCallback(ps, userId);
+ final String codePath = ps.getPathString();
+ if (IncrementalManager.isIncrementalPath(codePath) && mIncrementalManager != null) {
+ mIncrementalManager.registerCallback(codePath, incrementalStatesCallback);
+ ps.setIncrementalStatesCallback(incrementalStatesCallback);
+ }
+
// Ensure that the uninstall reason is UNKNOWN for users with the package installed.
for (int currentUserId : allUsersList) {
if (ps.getInstalled(currentUserId)) {
ps.setUninstallReason(UNINSTALL_REASON_UNKNOWN, currentUserId);
}
}
+
mSettings.writeKernelMappingLPr(ps);
}
res.name = pkgName;
@@ -17192,6 +17203,7 @@
mDexManager.notifyPackageUpdated(pkg.getPackageName(),
pkg.getBaseApkPath(), pkg.getSplitCodePaths());
}
+ reconciledPkg.pkgSetting.setStatesOnCommit();
// Prepare the application profiles for the new code paths.
// This needs to be done before invoking dexopt so that any install-time profile
@@ -17288,6 +17300,155 @@
NativeLibraryHelper.waitForNativeBinariesExtraction(incrementalStorages);
}
+ private class IncrementalStatesCallback extends IPackageLoadingProgressCallback.Stub
+ implements IncrementalStates.Callback {
+ @GuardedBy("mPackageSetting")
+ private final PackageSetting mPackageSetting;
+ private final String mPackageName;
+ private final String mPathString;
+ private final int mUserId;
+ private final int[] mInstalledUserIds;
+
+ IncrementalStatesCallback(PackageSetting packageSetting, int userId) {
+ mPackageSetting = packageSetting;
+ mPackageName = packageSetting.name;
+ mUserId = userId;
+ mPathString = packageSetting.getPathString();
+ final int[] allUserIds = resolveUserIds(userId);
+ final ArrayList<Integer> installedUserIds = new ArrayList<>();
+ for (int i = 0; i < allUserIds.length; i++) {
+ if (packageSetting.getInstalled(allUserIds[i])) {
+ installedUserIds.add(allUserIds[i]);
+ }
+ }
+ final int numInstalledUserId = installedUserIds.size();
+ mInstalledUserIds = new int[numInstalledUserId];
+ for (int i = 0; i < numInstalledUserId; i++) {
+ mInstalledUserIds[i] = installedUserIds.get(i);
+ }
+ }
+
+ @Override
+ public void onPackageLoadingProgressChanged(float progress) {
+ synchronized (mPackageSetting) {
+ mPackageSetting.setLoadingProgress(progress);
+ }
+ }
+
+ @Override
+ public void onPackageFullyLoaded() {
+ mIncrementalManager.unregisterCallback(mPathString, this);
+ final SparseArray<int[]> newBroadcastAllowList;
+ synchronized (mLock) {
+ newBroadcastAllowList = mAppsFilter.getVisibilityAllowList(
+ getPackageSettingInternal(mPackageName, Process.SYSTEM_UID),
+ mInstalledUserIds, mSettings.mPackages);
+ }
+ Bundle extras = new Bundle(1);
+ extras.putInt(Intent.EXTRA_UID, mUserId);
+ extras.putString(Intent.EXTRA_PACKAGE_NAME, mPackageName);
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_LOADED, mPackageName,
+ extras, 0 /*flags*/,
+ null /*targetPackage*/, null /*finishedReceiver*/,
+ mInstalledUserIds, null /* instantUserIds */, newBroadcastAllowList);
+ }
+
+ @Override
+ public void onPackageUnstartable(int reason) {
+ final SparseArray<int[]> newBroadcastAllowList;
+ synchronized (mLock) {
+ newBroadcastAllowList = mAppsFilter.getVisibilityAllowList(
+ getPackageSettingInternal(mPackageName, Process.SYSTEM_UID),
+ mInstalledUserIds, mSettings.mPackages);
+ }
+ Bundle extras = new Bundle(1);
+ extras.putInt(Intent.EXTRA_UID, mUserId);
+ extras.putString(Intent.EXTRA_PACKAGE_NAME, mPackageName);
+ extras.putInt(Intent.EXTRA_REASON, reason);
+ // send broadcast to users with this app installed
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_UNSTARTABLE, mPackageName,
+ extras, 0 /*flags*/,
+ null /*targetPackage*/, null /*finishedReceiver*/,
+ mInstalledUserIds, null /* instantUserIds */, newBroadcastAllowList);
+ }
+
+ @Override
+ public void onPackageStartable() {
+ final SparseArray<int[]> newBroadcastAllowList;
+ synchronized (mLock) {
+ newBroadcastAllowList = mAppsFilter.getVisibilityAllowList(
+ getPackageSettingInternal(mPackageName, Process.SYSTEM_UID),
+ mInstalledUserIds, mSettings.mPackages);
+ }
+ Bundle extras = new Bundle(1);
+ extras.putInt(Intent.EXTRA_UID, mUserId);
+ extras.putString(Intent.EXTRA_PACKAGE_NAME, mPackageName);
+ // send broadcast to users with this app installed
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_STARTABLE, mPackageName,
+ extras, 0 /*flags*/,
+ null /*targetPackage*/, null /*finishedReceiver*/,
+ mInstalledUserIds, null /* instantUserIds */, newBroadcastAllowList);
+ }
+ }
+
+ /**
+ * This is an internal method that is used to indicate changes on the health status of the
+ * Incremental Storage used by an installed package with an associated user id. This might
+ * result in a change in the loading state of the package.
+ */
+ public void onStorageHealthStatusChanged(String packageName, int status, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ mPermissionManager.enforceCrossUserPermission(
+ callingUid, userId, true, false,
+ "onStorageHealthStatusChanged");
+ final PackageSetting ps = getPackageSettingForUser(packageName, callingUid, userId);
+ if (ps == null) {
+ return;
+ }
+ ps.setStorageHealthStatus(status);
+ }
+
+ /**
+ * This is an internal method that is used to indicate changes on the stream status of the
+ * data loader used by an installed package with an associated user id. This might
+ * result in a change in the loading state of the package.
+ */
+ public void onStreamStatusChanged(String packageName, int status, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ mPermissionManager.enforceCrossUserPermission(
+ callingUid, userId, true, false,
+ "onStreamStatusChanged");
+ final PackageSetting ps = getPackageSettingForUser(packageName, callingUid, userId);
+ if (ps == null) {
+ return;
+ }
+ ps.setStreamStatus(status);
+ }
+
+ @Nullable PackageSetting getPackageSettingForUser(String packageName, int callingUid,
+ int userId) {
+ final PackageSetting ps;
+ synchronized (mLock) {
+ ps = mSettings.mPackages.get(packageName);
+ if (ps == null) {
+ Slog.w(TAG, "Failed to get package setting. Package " + packageName
+ + " is not installed");
+ return null;
+ }
+ if (!ps.getInstalled(userId)) {
+ Slog.w(TAG, "Failed to get package setting. Package " + packageName
+ + " is not installed for user " + userId);
+ return null;
+ }
+ if (shouldFilterApplicationLocked(ps, callingUid, userId)) {
+ Slog.w(TAG, "Failed to get package setting. Package " + packageName
+ + " is not visible to the calling app");
+ return null;
+ }
+ }
+ return ps;
+ }
+
private void notifyPackageChangeObserversOnUpdate(ReconciledPackage reconciledPkg) {
final PackageSetting pkgSetting = reconciledPkg.pkgSetting;
final PackageInstalledInfo pkgInstalledInfo = reconciledPkg.installResult;
@@ -21756,24 +21917,18 @@
mInjector.getStorageManagerInternal().addExternalStoragePolicy(
new StorageManagerInternal.ExternalStorageMountPolicy() {
- @Override
- public int getMountMode(int uid, String packageName) {
- if (Process.isIsolated(uid)) {
- return Zygote.MOUNT_EXTERNAL_NONE;
- }
- if (checkUidPermission(READ_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {
- return Zygote.MOUNT_EXTERNAL_DEFAULT;
- }
- if (checkUidPermission(WRITE_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {
- return Zygote.MOUNT_EXTERNAL_READ;
- }
- return Zygote.MOUNT_EXTERNAL_WRITE;
- }
+ @Override
+ public int getMountMode(int uid, String packageName) {
+ if (Process.isIsolated(uid)) {
+ return Zygote.MOUNT_EXTERNAL_NONE;
+ }
+ return Zygote.MOUNT_EXTERNAL_DEFAULT;
+ }
- @Override
- public boolean hasExternalStorage(int uid, String packageName) {
- return true;
- }
+ @Override
+ public boolean hasExternalStorage(int uid, String packageName) {
+ return true;
+ }
});
// Now that we're mostly running, clean up stale users and apps
@@ -25407,24 +25562,15 @@
@Override
public boolean registerInstalledLoadingProgressCallback(String packageName,
PackageManagerInternal.InstalledLoadingProgressCallback callback, int userId) {
- final int callingUid = Binder.getCallingUid();
- mPermissionManager.enforceCrossUserPermission(
- callingUid, userId, true, false,
- "registerLoadingProgressCallback");
- final PackageSetting ps;
- synchronized (mLock) {
- ps = mSettings.mPackages.get(packageName);
- if (ps == null) {
- Slog.w(TAG, "Failed registering loading progress callback. Package "
- + packageName + " is not installed");
- return false;
- }
- if (shouldFilterApplicationLocked(ps, callingUid, userId)) {
- Slog.w(TAG, "Failed registering loading progress callback. Package "
- + packageName + " is not visible to the calling app");
- return false;
- }
- // TODO(b/165841827): return false if package is fully loaded
+ final PackageSetting ps = getPackageSettingForUser(packageName, Binder.getCallingUid(),
+ userId);
+ if (ps == null) {
+ return false;
+ }
+ if (!ps.isPackageLoading()) {
+ Slog.w(TAG,
+ "Failed registering loading progress callback. Package is fully loaded.");
+ return false;
}
if (mIncrementalManager == null) {
Slog.w(TAG,
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 855a5ff5..de9d3a0 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -28,7 +28,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.pm.parsing.pkg.AndroidPackage;
-import com.android.server.pm.permission.AppIdPermissionState;
+import com.android.server.pm.permission.LegacyPermissionState;
import com.android.server.pm.pkg.PackageStateUnserialized;
import java.io.File;
@@ -214,11 +214,12 @@
mimeGroups = updatedMimeGroups;
}
+ @Deprecated
@Override
- public AppIdPermissionState getPermissionsState() {
+ public LegacyPermissionState getLegacyPermissionState() {
return (sharedUser != null)
- ? sharedUser.getPermissionsState()
- : super.getPermissionsState();
+ ? sharedUser.getLegacyPermissionState()
+ : super.getLegacyPermissionState();
}
public int getAppId() {
@@ -333,6 +334,8 @@
installSource.originatingPackageName);
proto.end(sourceToken);
}
+ proto.write(PackageProto.StatesProto.IS_STARTABLE, incrementalStates.isStartable());
+ proto.write(PackageProto.StatesProto.IS_LOADING, incrementalStates.isLoading());
writeUsersInfoToProto(proto, PackageProto.USERS);
proto.end(packageToken);
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index a7bbf8d..d52ad46 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -25,6 +25,7 @@
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IncrementalStatesInfo;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.UninstallReason;
@@ -33,6 +34,7 @@
import android.content.pm.Signature;
import android.content.pm.SuspendDialogInfo;
import android.os.PersistableBundle;
+import android.os.incremental.IncrementalManager;
import android.service.pm.PackageProto;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -133,6 +135,9 @@
boolean forceQueryableOverride;
+ @NonNull
+ public IncrementalStates incrementalStates;
+
PackageSettingBase(String name, String realName, @NonNull File path,
String legacyNativeLibraryPathString, String primaryCpuAbiString,
String secondaryCpuAbiString, String cpuAbiOverrideString,
@@ -151,6 +156,7 @@
this.versionCode = pVersionCode;
this.signatures = new PackageSignatures();
this.installSource = InstallSource.EMPTY;
+ this.incrementalStates = new IncrementalStates();
}
/**
@@ -257,6 +263,7 @@
orig.usesStaticLibrariesVersions.length) : null;
updateAvailable = orig.updateAvailable;
forceQueryableOverride = orig.forceQueryableOverride;
+ incrementalStates = orig.incrementalStates;
}
@VisibleForTesting
@@ -733,6 +740,66 @@
modifyUserState(userId).resetOverrideComponentLabelIcon();
}
+ /**
+ * @return True if package is startable, false otherwise.
+ */
+ public boolean isPackageStartable() {
+ return incrementalStates.isStartable();
+ }
+
+ /**
+ * @return True if package is still being loaded, false if the package is fully loaded.
+ */
+ public boolean isPackageLoading() {
+ return incrementalStates.isLoading();
+ }
+
+ /**
+ * @return all current states in a Parcelable.
+ */
+ public IncrementalStatesInfo getIncrementalStates() {
+ return incrementalStates.getIncrementalStatesInfo();
+ }
+
+ /**
+ * Called to indicate that the package installation has been committed. This will create a
+ * new startable state and a new loading state with default values. By default, the package is
+ * startable after commit. For a package installed on Incremental, the loading state is true.
+ * For non-Incremental packages, the loading state is false.
+ */
+ public void setStatesOnCommit() {
+ incrementalStates.onCommit(IncrementalManager.isIncrementalPath(getPathString()));
+ }
+
+ /**
+ * Called to set the callback to listen for startable state changes.
+ */
+ public void setIncrementalStatesCallback(IncrementalStates.Callback callback) {
+ incrementalStates.setCallback(callback);
+ }
+
+ /**
+ * Called to report progress changes. This might trigger loading state change.
+ * @see IncrementalStates#setProgress(float)
+ */
+ public void setLoadingProgress(float progress) {
+ incrementalStates.setProgress(progress);
+ }
+
+ /**
+ * @see IncrementalStates#onStorageHealthStatusChanged(int)
+ */
+ public void setStorageHealthStatus(int status) {
+ incrementalStates.onStorageHealthStatusChanged(status);
+ }
+
+ /**
+ * @see IncrementalStates#onStreamStatusChanged(int)
+ */
+ public void setStreamStatus(int status) {
+ incrementalStates.onStreamStatusChanged(status);
+ }
+
protected PackageSettingBase updateFrom(PackageSettingBase other) {
super.copyFrom(other);
setPath(other.getPath());
@@ -756,6 +823,7 @@
this.updateAvailable = other.updateAvailable;
this.verificationInfo = other.verificationInfo;
this.forceQueryableOverride = other.forceQueryableOverride;
+ this.incrementalStates = other.incrementalStates;
if (mOldCodePaths != null) {
if (other.mOldCodePaths != null) {
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index c1258b1..968c4b5 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -19,23 +19,29 @@
import android.content.pm.ApplicationInfo;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.pm.permission.AppIdPermissionState;
+import com.android.server.pm.permission.LegacyPermissionState;
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public abstract class SettingBase {
int pkgFlags;
int pkgPrivateFlags;
- protected final AppIdPermissionState mPermissionsState;
+ /**
+ * The legacy permission state that is read from package settings persistence for migration.
+ * This state here can not reflect the current permission state and should not be used for
+ * purposes other than migration.
+ */
+ @Deprecated
+ protected final LegacyPermissionState mLegacyPermissionsState;
SettingBase(int pkgFlags, int pkgPrivateFlags) {
setFlags(pkgFlags);
setPrivateFlags(pkgPrivateFlags);
- mPermissionsState = new AppIdPermissionState();
+ mLegacyPermissionsState = new LegacyPermissionState();
}
SettingBase(SettingBase orig) {
- mPermissionsState = new AppIdPermissionState();
+ mLegacyPermissionsState = new LegacyPermissionState();
doCopy(orig);
}
@@ -46,11 +52,12 @@
private void doCopy(SettingBase orig) {
pkgFlags = orig.pkgFlags;
pkgPrivateFlags = orig.pkgPrivateFlags;
- mPermissionsState.copyFrom(orig.mPermissionsState);
+ mLegacyPermissionsState.copyFrom(orig.mLegacyPermissionsState);
}
- public AppIdPermissionState getPermissionsState() {
- return mPermissionsState;
+ @Deprecated
+ public LegacyPermissionState getLegacyPermissionState() {
+ return mLegacyPermissionsState;
}
void setFlags(int pkgFlags) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index a922d76..1dc035f 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -107,10 +107,10 @@
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
-import com.android.server.pm.permission.AppIdPermissionState;
-import com.android.server.pm.permission.AppIdPermissionState.PermissionState;
import com.android.server.pm.permission.BasePermission;
import com.android.server.pm.permission.LegacyPermissionDataProvider;
+import com.android.server.pm.permission.LegacyPermissionState;
+import com.android.server.pm.permission.LegacyPermissionState.PermissionState;
import com.android.server.pm.permission.PermissionSettings;
import com.android.server.utils.TimingsTraceAndSlog;
@@ -733,7 +733,8 @@
pkgSetting.signatures = new PackageSignatures(disabledPkg.signatures);
pkgSetting.appId = disabledPkg.appId;
// Clone permissions
- pkgSetting.getPermissionsState().copyFrom(disabledPkg.getPermissionsState());
+ pkgSetting.getLegacyPermissionState()
+ .copyFrom(disabledPkg.getLegacyPermissionState());
// Clone component info
List<UserInfo> users = getAllUsers(userManager);
if (users != null) {
@@ -2114,7 +2115,7 @@
}
void readInstallPermissionsLPr(XmlPullParser parser,
- AppIdPermissionState permissionsState) throws IOException, XmlPullParserException {
+ LegacyPermissionState permissionsState) throws IOException, XmlPullParserException {
int outerDepth = parser.getDepth();
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
@@ -2406,7 +2407,7 @@
serializer.attribute(null, "userId",
Integer.toString(usr.userId));
usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
- writePermissionsLPr(serializer, usr.getPermissionsState()
+ writePermissionsLPr(serializer, usr.getLegacyPermissionState()
.getInstallPermissionStates());
serializer.endTag(null, "shared-user");
}
@@ -2734,7 +2735,7 @@
// If this is a shared user, the permissions will be written there.
if (pkg.sharedUser == null) {
- writePermissionsLPr(serializer, pkg.getPermissionsState()
+ writePermissionsLPr(serializer, pkg.getLegacyPermissionState()
.getInstallPermissionStates());
}
@@ -2809,6 +2810,12 @@
if (pkg.forceQueryableOverride) {
serializer.attribute(null, "forceQueryable", "true");
}
+ if (pkg.isPackageStartable()) {
+ serializer.attribute(null, "isStartable", "true");
+ }
+ if (pkg.isPackageLoading()) {
+ serializer.attribute(null, "isLoading", "true");
+ }
writeUsesStaticLibLPw(serializer, pkg.usesStaticLibraries, pkg.usesStaticLibrariesVersions);
@@ -2819,7 +2826,8 @@
serializer, "install-initiator-sigs", mPastSignatures);
}
- writePermissionsLPr(serializer, pkg.getPermissionsState().getInstallPermissionStates());
+ writePermissionsLPr(serializer,
+ pkg.getLegacyPermissionState().getInstallPermissionStates());
writeSigningKeySetLPr(serializer, pkg.keySetData);
writeUpgradeKeySetsLPr(serializer, pkg.keySetData);
@@ -3545,7 +3553,7 @@
}
if (parser.getName().equals(TAG_PERMISSIONS)) {
- readInstallPermissionsLPr(parser, ps.getPermissionsState());
+ readInstallPermissionsLPr(parser, ps.getLegacyPermissionState());
} else if (parser.getName().equals(TAG_USES_STATIC_LIB)) {
readUsesStaticLibLPw(parser, ps);
} else {
@@ -3594,6 +3602,8 @@
String version = null;
long versionCode = 0;
String installedForceQueryable = null;
+ String isStartable = null;
+ String isLoading = null;
try {
name = parser.getAttributeValue(null, ATTR_NAME);
realName = parser.getAttributeValue(null, "realName");
@@ -3610,6 +3620,8 @@
cpuAbiOverrideString = parser.getAttributeValue(null, "cpuAbiOverride");
updateAvailable = parser.getAttributeValue(null, "updateAvailable");
installedForceQueryable = parser.getAttributeValue(null, "forceQueryable");
+ isStartable = parser.getAttributeValue(null, "isStartable");
+ isLoading = parser.getAttributeValue(null, "isLoading");
if (primaryCpuAbiString == null && legacyCpuAbiString != null) {
primaryCpuAbiString = legacyCpuAbiString;
@@ -3793,6 +3805,8 @@
packageSetting.secondaryCpuAbiString = secondaryCpuAbiString;
packageSetting.updateAvailable = "true".equals(updateAvailable);
packageSetting.forceQueryableOverride = "true".equals(installedForceQueryable);
+ packageSetting.incrementalStates = new IncrementalStates("true".equals(isStartable),
+ "true".equals(isLoading));
// Handle legacy string here for single-user mode
final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
if (enabledStr != null) {
@@ -3836,7 +3850,7 @@
packageSetting.signatures.readXml(parser, mPastSignatures);
} else if (tagName.equals(TAG_PERMISSIONS)) {
readInstallPermissionsLPr(parser,
- packageSetting.getPermissionsState());
+ packageSetting.getLegacyPermissionState());
packageSetting.installPermissionsFixed = true;
} else if (tagName.equals("proper-signing-keyset")) {
long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
@@ -4062,7 +4076,7 @@
if (tagName.equals("sigs")) {
su.signatures.readXml(parser, mPastSignatures);
} else if (tagName.equals("perms")) {
- readInstallPermissionsLPr(parser, su.getPermissionsState());
+ readInstallPermissionsLPr(parser, su.getLegacyPermissionState());
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Unknown element under <shared-user>: " + parser.getName());
@@ -4482,7 +4496,7 @@
void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag,
ArraySet<String> permissionNames, PackageSetting ps,
- AppIdPermissionState permissionsState, SimpleDateFormat sdf, Date date,
+ LegacyPermissionState permissionsState, SimpleDateFormat sdf, Date date,
List<UserInfo> users, boolean dumpAll, boolean dumpAllComponents) {
AndroidPackage pkg = ps.pkg;
if (checkinTag != null) {
@@ -4932,8 +4946,8 @@
&& !packageName.equals(ps.name)) {
continue;
}
- final AppIdPermissionState permissionsState =
- mPermissionDataProvider.getAppIdPermissionState(ps.appId);
+ final LegacyPermissionState permissionsState =
+ mPermissionDataProvider.getLegacyPermissionState(ps.appId);
if (permissionNames != null
&& !permissionsState.hasPermissionState(permissionNames)) {
continue;
@@ -4990,8 +5004,8 @@
pw.println("Hidden system packages:");
printedSomething = true;
}
- final AppIdPermissionState permissionsState =
- mPermissionDataProvider.getAppIdPermissionState(ps.appId);
+ final LegacyPermissionState permissionsState =
+ mPermissionDataProvider.getLegacyPermissionState(ps.appId);
dumpPackageLPr(pw, " ", checkin ? "dis" : null, permissionNames, ps,
permissionsState, sdf, date, users, packageName != null, dumpAllComponents);
}
@@ -5021,8 +5035,8 @@
if (packageName != null && su != dumpState.getSharedUser()) {
continue;
}
- final AppIdPermissionState permissionsState =
- mPermissionDataProvider.getAppIdPermissionState(su.userId);
+ final LegacyPermissionState permissionsState =
+ mPermissionDataProvider.getLegacyPermissionState(su.userId);
if (permissionNames != null
&& !permissionsState.hasPermissionState(permissionNames)) {
continue;
@@ -5166,7 +5180,7 @@
}
void dumpInstallPermissionsLPr(PrintWriter pw, String prefix, ArraySet<String> permissionNames,
- AppIdPermissionState permissionsState) {
+ LegacyPermissionState permissionsState) {
Collection<PermissionState> permissionStates =
permissionsState.getInstallPermissionStates();
if (!permissionStates.isEmpty()) {
@@ -5412,7 +5426,7 @@
if (packageSetting.sharedUser == null) {
List<RuntimePermissionsState.PermissionState> permissions =
getPermissionsFromPermissionsState(
- packageSetting.getPermissionsState(), userId);
+ packageSetting.getLegacyPermissionState(), userId);
packagePermissions.put(packageName, permissions);
}
}
@@ -5425,7 +5439,7 @@
SharedUserSetting sharedUserSetting = mSharedUsers.valueAt(i);
List<RuntimePermissionsState.PermissionState> permissions =
getPermissionsFromPermissionsState(
- sharedUserSetting.getPermissionsState(), userId);
+ sharedUserSetting.getLegacyPermissionState(), userId);
sharedUserPermissions.put(sharedUserName, permissions);
}
@@ -5437,7 +5451,7 @@
@NonNull
private List<RuntimePermissionsState.PermissionState> getPermissionsFromPermissionsState(
- @NonNull AppIdPermissionState permissionsState, @UserIdInt int userId) {
+ @NonNull LegacyPermissionState permissionsState, @UserIdInt int userId) {
Collection<PermissionState> permissionStates =
permissionsState.getRuntimePermissionStates(userId);
List<RuntimePermissionsState.PermissionState> permissions = new ArrayList<>();
@@ -5497,11 +5511,11 @@
List<RuntimePermissionsState.PermissionState> permissions =
packagePermissions.get(packageName);
if (permissions != null) {
- readPermissionsStateLpr(permissions, packageSetting.getPermissionsState(),
+ readPermissionsStateLpr(permissions, packageSetting.getLegacyPermissionState(),
userId);
} else if (packageSetting.sharedUser == null && !isUpgradeToR) {
Slog.w(TAG, "Missing permission state for package: " + packageName);
- packageSetting.getPermissionsState().setMissing(true, userId);
+ packageSetting.getLegacyPermissionState().setMissing(true, userId);
}
}
@@ -5515,18 +5529,18 @@
List<RuntimePermissionsState.PermissionState> permissions =
sharedUserPermissions.get(sharedUserName);
if (permissions != null) {
- readPermissionsStateLpr(permissions, sharedUserSetting.getPermissionsState(),
- userId);
+ readPermissionsStateLpr(permissions,
+ sharedUserSetting.getLegacyPermissionState(), userId);
} else if (!isUpgradeToR) {
Slog.w(TAG, "Missing permission state for shared user: " + sharedUserName);
- sharedUserSetting.getPermissionsState().setMissing(true, userId);
+ sharedUserSetting.getLegacyPermissionState().setMissing(true, userId);
}
}
}
private void readPermissionsStateLpr(
@NonNull List<RuntimePermissionsState.PermissionState> permissions,
- @NonNull AppIdPermissionState permissionsState, @UserIdInt int userId) {
+ @NonNull LegacyPermissionState permissionsState, @UserIdInt int userId) {
int permissionsSize = permissions.size();
for (int i = 0; i < permissionsSize; i++) {
RuntimePermissionsState.PermissionState permission = permissions.get(i);
@@ -5605,7 +5619,7 @@
XmlUtils.skipCurrentTag(parser);
continue;
}
- parsePermissionsLPr(parser, ps.getPermissionsState(), userId);
+ parsePermissionsLPr(parser, ps.getLegacyPermissionState(), userId);
} break;
case TAG_SHARED_USER: {
@@ -5616,14 +5630,14 @@
XmlUtils.skipCurrentTag(parser);
continue;
}
- parsePermissionsLPr(parser, sus.getPermissionsState(), userId);
+ parsePermissionsLPr(parser, sus.getLegacyPermissionState(), userId);
} break;
}
}
}
private void parsePermissionsLPr(XmlPullParser parser,
- AppIdPermissionState permissionsState, int userId)
+ LegacyPermissionState permissionsState, int userId)
throws IOException, XmlPullParserException {
final int outerDepth = parser.getDepth();
int type;
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionDataProvider.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionDataProvider.java
index 7452b52..346a2c5 100644
--- a/services/core/java/com/android/server/pm/permission/LegacyPermissionDataProvider.java
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionDataProvider.java
@@ -31,7 +31,7 @@
* @return the legacy permission state
*/
@NonNull
- public abstract AppIdPermissionState getAppIdPermissionState(@AppIdInt int appId);
+ LegacyPermissionState getLegacyPermissionState(@AppIdInt int appId);
/**
* Get the GIDs computed from the permission state of a UID, either a package or a shared user.
@@ -40,5 +40,5 @@
* @return the GIDs for the UID
*/
@NonNull
- public abstract int[] getGidsForUid(int uid);
+ int[] getGidsForUid(int uid);
}
diff --git a/services/core/java/com/android/server/pm/permission/AppIdPermissionState.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionState.java
similarity index 97%
rename from services/core/java/com/android/server/pm/permission/AppIdPermissionState.java
rename to services/core/java/com/android/server/pm/permission/LegacyPermissionState.java
index aabdafd..63f69ce 100644
--- a/services/core/java/com/android/server/pm/permission/AppIdPermissionState.java
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionState.java
@@ -32,7 +32,7 @@
* Legacy permission state that was associated with packages or shared users.
*/
//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-public final class AppIdPermissionState {
+public final class LegacyPermissionState {
// Maps from user IDs to user states.
@NonNull
private final SparseArray<UserState> mUserStates = new SparseArray<>();
@@ -48,7 +48,7 @@
*
* @hide
*/
- public void copyFrom(@NonNull AppIdPermissionState other) {
+ public void copyFrom(@NonNull LegacyPermissionState other) {
if (other == this) {
return;
}
@@ -88,7 +88,7 @@
if (getClass() != object.getClass()) {
return false;
}
- final AppIdPermissionState other = (AppIdPermissionState) object;
+ final LegacyPermissionState other = (LegacyPermissionState) object;
return Objects.equals(mUserStates, other.mUserStates)
&& Objects.equals(mMissing, other.mMissing);
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index b293ba6..6a9503c7 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -104,7 +104,6 @@
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.os.storage.StorageManager;
-import android.os.storage.StorageManagerInternal;
import android.permission.IOnPermissionsChangeListener;
import android.permission.IPermissionManager;
import android.permission.PermissionControllerManager;
@@ -1554,24 +1553,6 @@
if (bp.isRuntime()) {
notifyRuntimePermissionStateChanged(packageName, userId);
}
-
- // Only need to do this if user is initialized. Otherwise it's a new user
- // and there are no processes running as the user yet and there's no need
- // to make an expensive call to remount processes for the changed permissions.
- if (READ_EXTERNAL_STORAGE.equals(permName)
- || WRITE_EXTERNAL_STORAGE.equals(permName)) {
- final long token = Binder.clearCallingIdentity();
- try {
- if (mUserManagerInt.isUserInitialized(userId)) {
- StorageManagerInternal storageManagerInternal = LocalServices.getService(
- StorageManagerInternal.class);
- storageManagerInternal.onExternalStoragePolicyChanged(uid, packageName);
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
}
@Override
@@ -4618,7 +4599,7 @@
final int[] userIds = getAllUserIds();
mPackageManagerInt.forEachPackageSetting(ps -> {
final int appId = ps.getAppId();
- final AppIdPermissionState appIdState = ps.getPermissionsState();
+ final LegacyPermissionState legacyState = ps.getLegacyPermissionState();
synchronized (mLock) {
for (final int userId : userIds) {
@@ -4627,19 +4608,19 @@
userState.setInstallPermissionsFixed(ps.name, ps.areInstallPermissionsFixed());
final UidPermissionState uidState = userState.getOrCreateUidState(appId);
uidState.reset();
- uidState.setMissing(appIdState.isMissing(userId));
+ uidState.setMissing(legacyState.isMissing(userId));
readStateFromPermissionStates(uidState,
- appIdState.getInstallPermissionStates());
+ legacyState.getInstallPermissionStates());
readStateFromPermissionStates(uidState,
- appIdState.getRuntimePermissionStates(userId));
+ legacyState.getRuntimePermissionStates(userId));
}
}
});
}
private void readStateFromPermissionStates(@NonNull UidPermissionState uidState,
- @NonNull Collection<AppIdPermissionState.PermissionState> permissionStates) {
- for (final AppIdPermissionState.PermissionState permissionState : permissionStates) {
+ @NonNull Collection<LegacyPermissionState.PermissionState> permissionStates) {
+ for (final LegacyPermissionState.PermissionState permissionState : permissionStates) {
uidState.putPermissionState(permissionState.getPermission(),
permissionState.isGranted(), permissionState.getFlags());
}
@@ -4649,8 +4630,8 @@
final int[] userIds = mState.getUserIds();
mPackageManagerInt.forEachPackageSetting(ps -> {
ps.setInstallPermissionsFixed(false);
- final AppIdPermissionState appIdState = ps.getPermissionsState();
- appIdState.reset();
+ final LegacyPermissionState legacyState = ps.getLegacyPermissionState();
+ legacyState.reset();
final int appId = ps.getAppId();
synchronized (mLock) {
@@ -4672,21 +4653,21 @@
continue;
}
- appIdState.setMissing(uidState.isMissing(), userId);
+ legacyState.setMissing(uidState.isMissing(), userId);
final List<PermissionState> permissionStates = uidState.getPermissionStates();
final int permissionStatesSize = permissionStates.size();
for (int i = 0; i < permissionStatesSize; i++) {
final PermissionState permissionState = permissionStates.get(i);
- final AppIdPermissionState.PermissionState legacyPermissionState =
- new AppIdPermissionState.PermissionState(
+ final LegacyPermissionState.PermissionState legacyPermissionState =
+ new LegacyPermissionState.PermissionState(
permissionState.getPermission(),
permissionState.isGranted(), permissionState.getFlags());
if (permissionState.isRuntime()) {
- appIdState.putRuntimePermissionState(legacyPermissionState,
+ legacyState.putRuntimePermissionState(legacyPermissionState,
userId);
} else {
- appIdState.putInstallPermissionState(legacyPermissionState);
+ legacyState.putInstallPermissionState(legacyPermissionState);
}
}
}
@@ -4695,8 +4676,8 @@
}
@NonNull
- private AppIdPermissionState getAppIdPermissionState(@AppIdInt int appId) {
- final AppIdPermissionState appIdState = new AppIdPermissionState();
+ private LegacyPermissionState getLegacyPermissionState(@AppIdInt int appId) {
+ final LegacyPermissionState legacyState = new LegacyPermissionState();
final int[] userIds = mState.getUserIds();
for (final int userId : userIds) {
final UidPermissionState uidState = getUidState(appId, userId);
@@ -4711,17 +4692,17 @@
for (int i = 0; i < permissionStatesSize; i++) {
final PermissionState permissionState = permissionStates.get(i);
- final AppIdPermissionState.PermissionState legacyPermissionState =
- new AppIdPermissionState.PermissionState(permissionState.getPermission(),
+ final LegacyPermissionState.PermissionState legacyPermissionState =
+ new LegacyPermissionState.PermissionState(permissionState.getPermission(),
permissionState.isGranted(), permissionState.getFlags());
if (permissionState.isRuntime()) {
- appIdState.putRuntimePermissionState(legacyPermissionState, userId);
+ legacyState.putRuntimePermissionState(legacyPermissionState, userId);
} else if (userId == UserHandle.USER_SYSTEM) {
- appIdState.putInstallPermissionState(legacyPermissionState);
+ legacyState.putInstallPermissionState(legacyPermissionState);
}
}
}
- return appIdState;
+ return legacyState;
}
@NonNull
@@ -5130,8 +5111,8 @@
}
@NonNull
- public AppIdPermissionState getAppIdPermissionState(@AppIdInt int appId) {
- return PermissionManagerService.this.getAppIdPermissionState(appId);
+ public LegacyPermissionState getLegacyPermissionState(@AppIdInt int appId) {
+ return PermissionManagerService.this.getLegacyPermissionState(appId);
}
@NonNull
diff --git a/services/core/java/com/android/server/pm/permission/UidPermissionState.java b/services/core/java/com/android/server/pm/permission/UidPermissionState.java
index c73e2f3..82ab954 100644
--- a/services/core/java/com/android/server/pm/permission/UidPermissionState.java
+++ b/services/core/java/com/android/server/pm/permission/UidPermissionState.java
@@ -338,6 +338,9 @@
public boolean isPermissionReviewRequired() {
synchronized (mLock) {
+ if (mPermissions == null) {
+ return false;
+ }
final int permissionsSize = mPermissions.size();
for (int i = 0; i < permissionsSize; i++) {
final PermissionState permission = mPermissions.valueAt(i);
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index cfceaabf..7b044ed 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -77,6 +77,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.view.InputChannel;
@@ -709,8 +710,7 @@
}
sessionState.isCurrent = false;
sessionState.currentChannel = null;
- notifyCurrentChannelInfosUpdatedLocked(
- userState, getCurrentTvChannelInfosInternalLocked(userState));
+ notifyCurrentChannelInfosUpdatedLocked(userState);
} catch (RemoteException | SessionNotFoundException e) {
Slog.e(TAG, "error in releaseSession", e);
} finally {
@@ -851,15 +851,18 @@
}
}
- private void notifyCurrentChannelInfosUpdatedLocked(
- UserState userState, List<TvChannelInfo> infos) {
+ private void notifyCurrentChannelInfosUpdatedLocked(UserState userState) {
if (DEBUG) {
Slog.d(TAG, "notifyCurrentChannelInfosUpdatedLocked");
}
int n = userState.mCallbacks.beginBroadcast();
for (int i = 0; i < n; ++i) {
try {
- userState.mCallbacks.getBroadcastItem(i).onCurrentTvChannelInfosUpdated(infos);
+ ITvInputManagerCallback callback = userState.mCallbacks.getBroadcastItem(i);
+ Pair<Integer, Integer> pidUid = userState.callbackPidUidMap.get(callback);
+ List<TvChannelInfo> infos = getCurrentTvChannelInfosInternalLocked(
+ userState, pidUid.first, pidUid.second);
+ callback.onCurrentTvChannelInfosUpdated(infos);
} catch (RemoteException e) {
Slog.e(TAG, "failed to report updated current channel infos to callback", e);
}
@@ -1063,14 +1066,19 @@
@Override
public void registerCallback(final ITvInputManagerCallback callback, int userId) {
- final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
- Binder.getCallingUid(), userId, "registerCallback");
+ int callingPid = Binder.getCallingPid();
+ int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
+ "registerCallback");
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
final UserState userState = getOrCreateUserStateLocked(resolvedUserId);
if (!userState.mCallbacks.register(callback)) {
Slog.e(TAG, "client process has already died");
+ } else {
+ userState.callbackPidUidMap.put(
+ callback, Pair.create(callingPid, callingUid));
}
}
} finally {
@@ -1087,6 +1095,7 @@
synchronized (mLock) {
UserState userState = getOrCreateUserStateLocked(resolvedUserId);
userState.mCallbacks.unregister(callback);
+ userState.callbackPidUidMap.remove(callback);
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -1419,8 +1428,8 @@
@Override
public void tune(IBinder sessionToken, final Uri channelUri, Bundle params, int userId) {
final int callingUid = Binder.getCallingUid();
- final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
- userId, "tune");
+ final int callingPid = Binder.getCallingPid();
+ final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId, "tune");
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -1432,8 +1441,7 @@
if (sessionState != null) {
sessionState.isCurrent = true;
sessionState.currentChannel = channelUri;
- notifyCurrentChannelInfosUpdatedLocked(
- userState, getCurrentTvChannelInfosInternalLocked(userState));
+ notifyCurrentChannelInfosUpdatedLocked(userState);
}
if (TvContract.isChannelUriForPassthroughInput(channelUri)) {
// Do not log the watch history for passthrough inputs.
@@ -2090,16 +2098,13 @@
@Override
public List<TvChannelInfo> getCurrentTvChannelInfos(@UserIdInt int userId) {
- final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
- Binder.getCallingUid(), userId, "getTvCurrentChannelInfos");
- final long identity = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
- UserState userState = getOrCreateUserStateLocked(resolvedUserId);
- return getCurrentTvChannelInfosInternalLocked(userState);
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
+ int callingPid = Binder.getCallingPid();
+ int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
+ "getTvCurrentChannelInfos");
+ synchronized (mLock) {
+ UserState userState = getOrCreateUserStateLocked(resolvedUserId);
+ return getCurrentTvChannelInfosInternalLocked(userState, callingPid, callingUid);
}
}
@@ -2273,14 +2278,15 @@
}
}
- private List<TvChannelInfo> getCurrentTvChannelInfosInternalLocked(UserState userState) {
+ private List<TvChannelInfo> getCurrentTvChannelInfosInternalLocked(
+ UserState userState, int callingPid, int callingUid) {
List<TvChannelInfo> channelInfos = new ArrayList<>();
- boolean watchedProgramsAccess = hasAccessWatchedProgramsPermission();
+ boolean watchedProgramsAccess = hasAccessWatchedProgramsPermission(callingPid, callingUid);
for (SessionState state : userState.sessionStateMap.values()) {
if (state.isCurrent) {
Integer appTag;
int appType;
- if (state.callingUid == Binder.getCallingUid()) {
+ if (state.callingUid == callingUid) {
appTag = APP_TAG_SELF;
appType = TvChannelInfo.APP_TYPE_SELF;
} else {
@@ -2322,8 +2328,8 @@
return false;
}
- private boolean hasAccessWatchedProgramsPermission() {
- return mContext.checkCallingPermission(PERMISSION_ACCESS_WATCHED_PROGRAMS)
+ private boolean hasAccessWatchedProgramsPermission(int callingPid, int callingUid) {
+ return mContext.checkPermission(PERMISSION_ACCESS_WATCHED_PROGRAMS, callingPid, callingUid)
== PackageManager.PERMISSION_GRANTED;
}
@@ -2360,6 +2366,9 @@
private final RemoteCallbackList<ITvInputManagerCallback> mCallbacks =
new RemoteCallbackList<ITvInputManagerCallback>();
+ private final Map<ITvInputManagerCallback, Pair<Integer, Integer>> callbackPidUidMap =
+ new HashMap<>();
+
// The token of a "main" TV input session.
private IBinder mainSessionToken = null;
@@ -2712,8 +2721,7 @@
mSessionState.isCurrent = true;
mSessionState.currentChannel = channelUri;
UserState userState = getOrCreateUserStateLocked(mSessionState.userId);
- notifyCurrentChannelInfosUpdatedLocked(
- userState, getCurrentTvChannelInfosInternalLocked(userState));
+ notifyCurrentChannelInfosUpdatedLocked(userState);
try {
// TODO: Consider adding this channel change in the watch log. When we do
// that, how we can protect the watch log from malicious tv inputs should
diff --git a/services/core/java/com/android/server/utils/eventlog/LocalEventLog.java b/services/core/java/com/android/server/utils/eventlog/LocalEventLog.java
new file mode 100644
index 0000000..c160647
--- /dev/null
+++ b/services/core/java/com/android/server/utils/eventlog/LocalEventLog.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.utils.eventlog;
+
+import android.os.SystemClock;
+import android.util.TimeUtils;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ConcurrentModificationException;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+/**
+ * An in-memory event log to support historical event information.
+ */
+public abstract class LocalEventLog implements Iterable<String> {
+
+ private interface Log {
+ // true if this is a filler element that should not be queried
+ boolean isFiller();
+ long getTimeDeltaMs();
+ String getLogString();
+ }
+
+ private static final class FillerEvent implements Log {
+
+ static final long MAX_TIME_DELTA = (1L << 32) - 1;
+
+ private final int mTimeDelta;
+
+ FillerEvent(long timeDelta) {
+ Preconditions.checkArgument(timeDelta >= 0);
+ mTimeDelta = (int) timeDelta;
+ }
+
+ @Override
+ public boolean isFiller() {
+ return true;
+ }
+
+ @Override
+ public long getTimeDeltaMs() {
+ return Integer.toUnsignedLong(mTimeDelta);
+ }
+
+ @Override
+ public String getLogString() {
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * An abstraction of a log event to be implemented by subclasses.
+ */
+ public abstract static class LogEvent implements Log {
+
+ static final long MAX_TIME_DELTA = (1L << 32) - 1;
+
+ private final int mTimeDelta;
+
+ protected LogEvent(long timeDelta) {
+ Preconditions.checkArgument(timeDelta >= 0);
+ mTimeDelta = (int) timeDelta;
+ }
+
+ @Override
+ public final boolean isFiller() {
+ return false;
+ }
+
+ @Override
+ public final long getTimeDeltaMs() {
+ return Integer.toUnsignedLong(mTimeDelta);
+ }
+ }
+
+ // circular buffer of log entries
+ private final Log[] mLog;
+ private int mLogSize;
+ private int mLogEndIndex;
+ private int mModificationCount;
+
+ // invalid if log is empty
+ private long mStartRealtimeMs;
+ private long mLastLogRealtimeMs;
+
+ public LocalEventLog(int size) {
+ mLog = new Log[size];
+ mLogSize = 0;
+ mLogEndIndex = 0;
+ mModificationCount = 0;
+
+ mStartRealtimeMs = -1;
+ mLastLogRealtimeMs = -1;
+ }
+
+ /**
+ * Should be overridden by subclasses to return a new immutable log event for the given
+ * arguments (as passed into {@link #addLogEvent(int, Object...)}.
+ */
+ protected abstract LogEvent createLogEvent(long timeDelta, int event, Object... args);
+
+ /**
+ * May be optionally overridden by subclasses if they wish to change how log event time is
+ * formatted.
+ */
+ protected String getTimePrefix(long timeMs) {
+ return TimeUtils.logTimeOfDay(timeMs) + ": ";
+ }
+
+ /**
+ * Call to add a new log event at the current time. The arguments provided here will be passed
+ * into {@link #createLogEvent(long, int, Object...)} in addition to a time delta, and should be
+ * used to construct an appropriate {@link LogEvent} object.
+ */
+ public void addLogEvent(int event, Object... args) {
+ long timeMs = SystemClock.elapsedRealtime();
+
+ // calculate delta
+ long delta = 0;
+ if (!isEmpty()) {
+ delta = timeMs - mLastLogRealtimeMs;
+
+ // if the delta is invalid, or if the delta is great enough using filler elements would
+ // result in an empty log anyways, just clear the log and continue, otherwise insert
+ // filler elements until we have a reasonable delta
+ if (delta < 0 || (delta / FillerEvent.MAX_TIME_DELTA) >= mLog.length - 1) {
+ clear();
+ delta = 0;
+ } else {
+ while (delta >= LogEvent.MAX_TIME_DELTA) {
+ long timeDelta = Math.min(FillerEvent.MAX_TIME_DELTA, delta);
+ addLogEventInternal(new FillerEvent(timeDelta));
+ delta -= timeDelta;
+ }
+ }
+ }
+
+ // for first log entry, set initial times
+ if (isEmpty()) {
+ mStartRealtimeMs = timeMs;
+ mLastLogRealtimeMs = mStartRealtimeMs;
+ }
+
+ addLogEventInternal(createLogEvent(delta, event, args));
+ }
+
+ private void addLogEventInternal(Log event) {
+ Preconditions.checkState(mStartRealtimeMs != -1 && mLastLogRealtimeMs != -1);
+
+ if (mLogSize == mLog.length) {
+ // if log is full, size will remain the same, but update the start time
+ mStartRealtimeMs += event.getTimeDeltaMs();
+ } else {
+ // otherwise add an item
+ mLogSize++;
+ }
+
+ // set log and increment end index
+ mLog[mLogEndIndex] = event;
+ mLogEndIndex = incrementIndex(mLogEndIndex);
+ mLastLogRealtimeMs = mLastLogRealtimeMs + event.getTimeDeltaMs();
+
+ mModificationCount++;
+ }
+
+ /** Clears the log of all entries. */
+ public void clear() {
+ mLogEndIndex = 0;
+ mLogSize = 0;
+ mModificationCount++;
+
+ mStartRealtimeMs = -1;
+ mLastLogRealtimeMs = -1;
+ }
+
+ // checks if the log is empty (if empty, times are invalid)
+ private boolean isEmpty() {
+ return mLogSize == 0;
+ }
+
+ @Override
+ public ListIterator<String> iterator() {
+ return new LogIterator();
+ }
+
+ // returns the index of the first element
+ private int startIndex() {
+ return wrapIndex(mLogEndIndex - mLogSize);
+ }
+
+ // returns the index after this one
+ private int incrementIndex(int index) {
+ return wrapIndex(index + 1);
+ }
+
+ // returns the index before this one
+ private int decrementIndex(int index) {
+ return wrapIndex(index - 1);
+ }
+
+ // rolls over the given index if necessary
+ private int wrapIndex(int index) {
+ // java modulo will keep negative sign, we need to rollover
+ return (index % mLog.length + mLog.length) % mLog.length;
+ }
+
+ private class LogIterator implements ListIterator<String> {
+
+ private final int mModificationGuard;
+
+ private final long mSystemTimeDeltaMs;
+
+ private long mCurrentRealtimeMs;
+ private int mIndex;
+ private int mCount;
+
+ LogIterator() {
+ mModificationGuard = mModificationCount;
+ mSystemTimeDeltaMs = System.currentTimeMillis() - SystemClock.elapsedRealtime();
+ mCurrentRealtimeMs = mStartRealtimeMs;
+ mIndex = startIndex();
+ mCount = 0;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return mCount < mLogSize;
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return mCount > 0;
+ }
+
+ @Override
+ // return then increment
+ public String next() {
+ checkModifications();
+
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+
+ Log log = mLog[mIndex];
+ long nextDeltaMs = log.getTimeDeltaMs();
+ long realtimeMs = mCurrentRealtimeMs + nextDeltaMs;
+
+ // calculate next index, skipping filler events
+ do {
+ mCurrentRealtimeMs += nextDeltaMs;
+ mIndex = incrementIndex(mIndex);
+ if (++mCount < mLogSize) {
+ nextDeltaMs = mLog[mIndex].getTimeDeltaMs();
+ }
+ } while (mCount < mLogSize && mLog[mIndex].isFiller());
+
+ return getTimePrefix(realtimeMs + mSystemTimeDeltaMs) + log.getLogString();
+ }
+
+ @Override
+ // decrement then return
+ public String previous() {
+ checkModifications();
+
+ Log log;
+ long currentDeltaMs;
+ long realtimeMs;
+
+ // calculate previous index, skipping filler events with MAX_TIME_DELTA
+ do {
+ if (!hasPrevious()) {
+ throw new NoSuchElementException();
+ }
+
+ mIndex = decrementIndex(mIndex);
+ mCount--;
+
+ log = mLog[mIndex];
+ realtimeMs = mCurrentRealtimeMs;
+
+ if (mCount > 0) {
+ currentDeltaMs = log.getTimeDeltaMs();
+ mCurrentRealtimeMs -= currentDeltaMs;
+ }
+ } while (mCount >= 0 && log.isFiller());
+
+ return getTimePrefix(realtimeMs + mSystemTimeDeltaMs) + log.getLogString();
+ }
+
+ private void checkModifications() {
+ if (mModificationGuard != mModificationCount) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ @Override
+ public int nextIndex() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int previousIndex() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void add(String s) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void set(String s) {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
+
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 2355ed3..9868fc1 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -116,6 +116,7 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SWITCH;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
@@ -150,10 +151,7 @@
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_APP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
@@ -1133,16 +1131,14 @@
boolean scheduleTopResumedActivityChanged(boolean onTop) {
if (!attachedToProcess()) {
- if (DEBUG_STATES) {
- Slog.w(TAG, "Can't report activity position update - client not running"
- + ", activityRecord=" + this);
- }
+ ProtoLog.w(WM_DEBUG_STATES,
+ "Can't report activity position update - client not running, "
+ + "activityRecord=%s", this);
return false;
}
try {
- if (DEBUG_STATES) {
- Slog.v(TAG, "Sending position change to " + this + ", onTop: " + onTop);
- }
+ ProtoLog.v(WM_DEBUG_STATES, "Sending position change to %s, onTop: %b",
+ this, onTop);
mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
TopResumedActivityChangeItem.obtain(onTop));
@@ -2518,10 +2514,8 @@
*/
@FinishRequest int finishIfPossible(int resultCode, Intent resultData,
NeededUriGrants resultGrants, String reason, boolean oomAdj) {
- if (DEBUG_RESULTS || DEBUG_STATES) {
- Slog.v(TAG_STATES, "Finishing activity r=" + this + ", result=" + resultCode
- + ", data=" + resultData + ", reason=" + reason);
- }
+ ProtoLog.v(WM_DEBUG_STATES, "Finishing activity r=%s, result=%d, data=%s, "
+ + "reason=%s", this, resultCode, resultData, reason);
if (finishing) {
Slog.w(TAG, "Duplicate finish request for r=" + this);
@@ -2603,7 +2597,7 @@
setVisibility(false);
if (stack.mPausingActivity == null) {
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + this);
+ ProtoLog.v(WM_DEBUG_STATES, "Finish needs to pause: %s", this);
if (DEBUG_USER_LEAVING) {
Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");
}
@@ -2650,7 +2644,7 @@
}
return removedActivity ? FINISH_RESULT_REMOVED : FINISH_RESULT_REQUESTED;
} else {
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + this);
+ ProtoLog.v(WM_DEBUG_STATES, "Finish waiting for pause of: %s", this);
}
return FINISH_RESULT_REQUESTED;
@@ -2807,7 +2801,7 @@
*/
@VisibleForTesting
boolean addToFinishingAndWaitForIdle() {
- if (DEBUG_STATES) Slog.v(TAG, "Enqueueing pending finish: " + this);
+ ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending finish: %s", this);
setState(FINISHING, "addToFinishingAndWaitForIdle");
if (!mStackSupervisor.mFinishingActivities.contains(this)) {
mStackSupervisor.mFinishingActivities.add(this);
@@ -2835,10 +2829,8 @@
}
if (isState(DESTROYING, DESTROYED)) {
- if (DEBUG_STATES) {
- Slog.v(TAG_STATES, "activity " + this + " already destroying."
- + "skipping request with reason:" + reason);
- }
+ ProtoLog.v(WM_DEBUG_STATES, "activity %s already destroying, skipping "
+ + "request with reason:%s", this, reason);
return false;
}
@@ -2879,16 +2871,13 @@
// the list yet. Otherwise, we can just immediately put it in the destroyed state since
// we are not removing it from the list.
if (finishing && !skipDestroy) {
- if (DEBUG_STATES) {
- Slog.v(TAG_STATES, "Moving to DESTROYING: " + this + " (destroy requested)");
- }
+ ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYING: %s (destroy requested)", this);
setState(DESTROYING,
"destroyActivityLocked. finishing and not skipping destroy");
mAtmService.mH.postDelayed(mDestroyTimeoutRunnable, DESTROY_TIMEOUT);
} else {
- if (DEBUG_STATES) {
- Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (destroy skipped)");
- }
+ ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s "
+ + "(destroy skipped)", this);
setState(DESTROYED,
"destroyActivityLocked. not finishing or skipping destroy");
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + this);
@@ -2900,7 +2889,7 @@
removeFromHistory(reason + " hadNoApp");
removedFromHistory = true;
} else {
- if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (no app)");
+ ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s (no app)", this);
setState(DESTROYED, "destroyActivityLocked. not finishing and had no app");
}
}
@@ -2935,9 +2924,8 @@
takeFromHistory();
removeTimeouts();
- if (DEBUG_STATES) {
- Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (removed from history)");
- }
+ ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s (removed from history)",
+ this);
setState(DESTROYED, "removeFromHistory");
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + this);
detachFromProcess();
@@ -4455,12 +4443,12 @@
}
void setState(ActivityState state, String reason) {
- if (DEBUG_STATES) Slog.v(TAG_STATES, "State movement: " + this + " from:" + getState()
- + " to:" + state + " reason:" + reason);
+ ProtoLog.v(WM_DEBUG_STATES, "State movement: %s from:%s to:%s reason:%s",
+ this, getState(), state, reason);
if (state == mState) {
// No need to do anything if state doesn't change.
- if (DEBUG_STATES) Slog.v(TAG_STATES, "State unchanged from:" + state);
+ ProtoLog.v(WM_DEBUG_STATES, "State unchanged from:%s", state);
return;
}
@@ -4943,7 +4931,7 @@
static void activityResumedLocked(IBinder token) {
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
- if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r);
+ ProtoLog.i(WM_DEBUG_STATES, "Resumed activity; dropping state of: %s", r);
if (r == null) {
// If an app reports resumed after a long delay, the record on server side might have
// been removed (e.g. destroy timeout), so the token could be null.
@@ -5014,8 +5002,8 @@
}
void activityPaused(boolean timeout) {
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
- "Activity paused: token=" + appToken + ", timeout=" + timeout);
+ ProtoLog.v(WM_DEBUG_STATES, "Activity paused: token=%s, timeout=%b", appToken,
+ timeout);
final Task stack = getStack();
@@ -5023,8 +5011,8 @@
removePauseTimeout();
if (stack.mPausingActivity == this) {
- if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + this
- + (timeout ? " (due to timeout)" : " (pause complete)"));
+ ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s %s", this,
+ (timeout ? "(due to timeout)" : " (pause complete)"));
mAtmService.deferWindowLayout();
try {
stack.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
@@ -5039,8 +5027,8 @@
if (isState(PAUSING)) {
setState(PAUSED, "activityPausedLocked");
if (finishing) {
- if (DEBUG_PAUSE) Slog.v(TAG,
- "Executing finish of failed to pause activity: " + this);
+ ProtoLog.v(WM_DEBUG_STATES,
+ "Executing finish of failed to pause activity: %s", this);
completeFinishing("activityPausedLocked");
}
}
@@ -5057,7 +5045,7 @@
void schedulePauseTimeout() {
pauseTime = SystemClock.uptimeMillis();
mAtmService.mH.postDelayed(mPauseTimeoutRunnable, PAUSE_TIMEOUT);
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
+ ProtoLog.v(WM_DEBUG_STATES, "Waiting for pause to complete...");
}
private void removePauseTimeout() {
@@ -5086,17 +5074,15 @@
if (isNoHistory()) {
if (!finishing) {
if (!stack.shouldSleepActivities()) {
- if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + this);
+ ProtoLog.d(WM_DEBUG_STATES, "no-history finish of %s", this);
if (finishIfPossible("stop-no-history", false /* oomAdj */)
!= FINISH_RESULT_CANCELLED) {
resumeKeyDispatchingLocked();
return;
}
} else {
- if (DEBUG_STATES) {
- Slog.d(TAG_STATES, "Not finishing noHistory " + this
- + " on stop because we're just sleeping");
- }
+ ProtoLog.d(WM_DEBUG_STATES, "Not finishing noHistory %s on stop "
+ + "because we're just sleeping", this);
}
}
}
@@ -5107,9 +5093,8 @@
resumeKeyDispatchingLocked();
try {
stopped = false;
- if (DEBUG_STATES) {
- Slog.v(TAG_STATES, "Moving to STOPPING: " + this + " (stop requested)");
- }
+ ProtoLog.v(WM_DEBUG_STATES, "Moving to STOPPING: %s (stop requested)", this);
+
setState(STOPPING, "stopIfPossible");
if (DEBUG_VISIBILITY) {
Slog.v(TAG_VISIBILITY, "Stopping:" + this);
@@ -5129,7 +5114,7 @@
Slog.w(TAG, "Exception thrown during pause", e);
// Just in case, assume it to be stopped.
stopped = true;
- if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + this);
+ ProtoLog.v(WM_DEBUG_STATES, "Stop failed; moving to STOPPED: %s", this);
setState(STOPPED, "stopIfPossible");
if (deferRelaunchUntilPaused) {
destroyImmediately("stop-except");
@@ -5158,9 +5143,9 @@
launchCount = 0;
updateTaskDescription(description);
}
- if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + mIcicle);
+ ProtoLog.i(WM_DEBUG_STATES, "Saving icicle of %s: %s", this, mIcicle);
if (!stopped) {
- if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
+ ProtoLog.v(WM_DEBUG_STATES, "Moving to STOPPED: %s (stop complete)", this);
removeStopTimeout();
stopped = true;
if (isStopping) {
@@ -5196,10 +5181,9 @@
boolean forceIdle = mStackSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE
|| (isRootOfTask() && stack.getChildCount() <= 1);
if (scheduleIdle || forceIdle) {
- if (DEBUG_PAUSE) {
- Slog.v(TAG_PAUSE, "Scheduling idle now: forceIdle=" + forceIdle
- + "immediate=" + !idleDelayed);
- }
+ ProtoLog.v(WM_DEBUG_STATES,
+ "Scheduling idle now: forceIdle=%b immediate=%b", forceIdle, !idleDelayed);
+
if (!idleDelayed) {
mStackSupervisor.scheduleIdle();
} else {
@@ -7126,9 +7110,9 @@
} else {
ProtoLog.v(WM_DEBUG_CONFIGURATION, "Config is relaunching %s",
this);
- if (DEBUG_STATES && !mVisibleRequested) {
- Slog.v(TAG_STATES, "Config is relaunching invisible activity " + this
- + " called by " + Debug.getCallers(4));
+ if (!mVisibleRequested) {
+ ProtoLog.v(WM_DEBUG_STATES, "Config is relaunching invisible "
+ + "activity %s called by %s", this, Debug.getCallers(4));
}
relaunchActivityLocked(preserveWindow);
}
@@ -7261,9 +7245,8 @@
startFreezingScreenLocked(0);
try {
- if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
- "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + this
- + " callers=" + Debug.getCallers(6));
+ ProtoLog.i(WM_DEBUG_STATES, "Moving to %s Relaunching %s callers=%s" ,
+ (andResume ? "RESUMED" : "PAUSED"), this, Debug.getCallers(6));
forceNewConfig = false;
startRelaunching();
final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
@@ -7286,13 +7269,11 @@
// request resume if this activity is currently resumed, which implies we aren't
// sleeping.
} catch (RemoteException e) {
- if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e);
+ ProtoLog.i(WM_DEBUG_STATES, "Relaunch failed %s", e);
}
if (andResume) {
- if (DEBUG_STATES) {
- Slog.d(TAG_STATES, "Resumed after relaunch " + this);
- }
+ ProtoLog.d(WM_DEBUG_STATES, "Resumed after relaunch %s", this);
results = null;
newIntents = null;
mAtmService.getAppWarningsLocked().onResumeActivity(this);
@@ -7864,6 +7845,7 @@
final Rect insets = new Rect();
mainWindow.getContentInsets(insets);
InsetUtils.addInsets(insets, getLetterboxInsets());
+
return new RemoteAnimationTarget(task.mTaskId, record.getMode(),
record.mAdapter.mCapturedLeash, !fillsParent(),
new Rect(), insets,
@@ -7871,7 +7853,7 @@
record.mAdapter.mStackBounds, task.getWindowConfiguration(),
false /*isNotInRecents*/,
record.mThumbnailAdapter != null ? record.mThumbnailAdapter.mCapturedLeash : null,
- record.mStartBounds);
+ record.mStartBounds, task.getPictureInPictureParams());
}
@Override
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 3ef383b..e2c1303 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -44,15 +44,14 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_IDLE;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_IDLE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
@@ -66,7 +65,6 @@
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
-import static com.android.server.wm.RootWindowContainer.TAG_STATES;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.Task.ActivityState.PAUSED;
@@ -135,6 +133,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.os.TransferPipe;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledLambda;
@@ -721,9 +720,9 @@
// While there are activities pausing we skipping starting any new activities until
// pauses are complete. NOTE: that we also do this for activities that are starting in
// the paused state because they will first be resumed then paused on the client side.
- if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
- "realStartActivityLocked: Skipping start of r=" + r
- + " some activities pausing...");
+ ProtoLog.v(WM_DEBUG_STATES,
+ "realStartActivityLocked: Skipping start of r=%s some activities pausing...",
+ r);
return false;
}
@@ -919,8 +918,8 @@
// This activity is not starting in the resumed state... which should look like we asked
// it to pause+stop (but remain visible), and it has done so and reported back the
// current icicle and other state.
- if (DEBUG_STATES) Slog.v(TAG_STATES,
- "Moving to PAUSED: " + r + " (starting in paused state)");
+ ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s "
+ + "(starting in paused state)", r);
r.setState(PAUSED, "realStartActivityLocked");
mRootWindowContainer.executeAppTransitionForAllDisplay();
}
@@ -1071,11 +1070,11 @@
/** Check if caller is allowed to launch activities on specified display. */
boolean isCallerAllowedToLaunchOnDisplay(int callingPid, int callingUid, int launchDisplayId,
ActivityInfo aInfo) {
- if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check: displayId=" + launchDisplayId
- + " callingPid=" + callingPid + " callingUid=" + callingUid);
+ ProtoLog.d(WM_DEBUG_TASKS, "Launch on display check: displayId=%d callingPid=%d "
+ + "callingUid=%d", launchDisplayId, callingPid, callingUid);
if (callingPid == -1 && callingUid == -1) {
- if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check: no caller info, skip check");
+ ProtoLog.d(WM_DEBUG_TASKS, "Launch on display check: no caller info, skip check");
return true;
}
@@ -1091,8 +1090,7 @@
final int startAnyPerm = mService.checkPermission(INTERNAL_SYSTEM_WINDOW, callingPid,
callingUid);
if (startAnyPerm == PERMISSION_GRANTED) {
- if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
- + " allow launch any on display");
+ ProtoLog.d(WM_DEBUG_TASKS, "Launch on display check: allow launch any on display");
return true;
}
@@ -1104,36 +1102,36 @@
// Limit launching on untrusted displays because their contents can be read from Surface
// by apps that created them.
if ((aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
- if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
- + " disallow launch on virtual display for not-embedded activity.");
+ ProtoLog.d(WM_DEBUG_TASKS, "Launch on display check: disallow launch on "
+ + "virtual display for not-embedded activity.");
return false;
}
// Check if the caller is allowed to embed activities from other apps.
if (mService.checkPermission(ACTIVITY_EMBEDDING, callingPid, callingUid)
== PERMISSION_DENIED && !uidPresentOnDisplay) {
- if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
- + " disallow activity embedding without permission.");
+ ProtoLog.d(WM_DEBUG_TASKS, "Launch on display check: disallow activity "
+ + "embedding without permission.");
return false;
}
}
if (!displayContent.isPrivate()) {
// Anyone can launch on a public display.
- if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
- + " allow launch on public display");
+ ProtoLog.d(WM_DEBUG_TASKS, "Launch on display check: allow launch on public "
+ + "display");
return true;
}
// Check if the caller is the owner of the display.
if (display.getOwnerUid() == callingUid) {
- if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
- + " allow launch for owner of the display");
+ ProtoLog.d(WM_DEBUG_TASKS, "Launch on display check: allow launch for owner of the"
+ + " display");
return true;
}
if (uidPresentOnDisplay) {
- if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
- + " allow launch for caller present on the display");
+ ProtoLog.d(WM_DEBUG_TASKS, "Launch on display check: allow launch for caller "
+ + "present on the display");
return true;
}
@@ -1832,8 +1830,8 @@
final boolean animating = s.isAnimating(TRANSITION | PARENTS,
ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS)
|| mService.getTransitionController().inTransition(s);
- if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + s.nowVisible
- + " animating=" + animating + " finishing=" + s.finishing);
+ ProtoLog.v(WM_DEBUG_STATES, "Stopping %s: nowVisible=%b animating=%b "
+ + "finishing=%s", s, s.nowVisible, animating, s.finishing);
if (!animating || mService.mShuttingDown) {
if (!processPausingActivities && s.isState(PAUSING)) {
// Defer processing pausing activities in this iteration and reschedule
@@ -1843,7 +1841,7 @@
continue;
}
- if (DEBUG_STATES) Slog.v(TAG, "Ready to stop: " + s);
+ ProtoLog.v(WM_DEBUG_STATES, "Ready to stop: %s", s);
if (readyToStopActivities == null) {
readyToStopActivities = new ArrayList<>();
}
@@ -2077,7 +2075,7 @@
msg.obj = r;
r.topResumedStateLossTime = SystemClock.uptimeMillis();
mHandler.sendMessageDelayed(msg, TOP_RESUMED_STATE_LOSS_TIMEOUT);
- if (DEBUG_STATES) Slog.v(TAG_STATES, "Waiting for top state to be released by " + r);
+ ProtoLog.v(WM_DEBUG_STATES, "Waiting for top state to be released by %s", r);
}
/**
@@ -2085,10 +2083,9 @@
* activity if needed.
*/
void handleTopResumedStateReleased(boolean timeout) {
- if (DEBUG_STATES) {
- Slog.v(TAG_STATES, "Top resumed state released "
- + (timeout ? " (due to timeout)" : " (transition complete)"));
- }
+ ProtoLog.v(WM_DEBUG_STATES, "Top resumed state released %s",
+ (timeout ? "(due to timeout)" : "(transition complete)"));
+
mHandler.removeMessages(TOP_RESUMED_STATE_LOSS_TIMEOUT_MSG);
if (!mTopResumedActivityWaitingForPrev) {
// Top resumed activity state loss already handled.
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index fa4373f..28e71fa 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -57,14 +57,13 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
-import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS;
@@ -1909,10 +1908,8 @@
// if that is the case, so this is it! And for paranoia, make sure we have
// correctly resumed the top activity.
if (!mMovedToFront && mDoResume) {
- if (DEBUG_TASKS) {
- Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
- + " from " + targetTaskTop);
- }
+ ProtoLog.d(WM_DEBUG_TASKS, "Bring to front target: %s from %s", mTargetStack,
+ targetTaskTop);
mTargetStack.moveToFront("intentActivityFound");
}
resumeTargetStackIfNeeded();
@@ -2564,10 +2561,8 @@
mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);
addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
- if (DEBUG_TASKS) {
- Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
- + " in new task " + mStartActivity.getTask());
- }
+ ProtoLog.v(WM_DEBUG_TASKS, "Starting new activity %s in new task %s",
+ mStartActivity, mStartActivity.getTask());
if (taskToAffiliate != null) {
mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerDebugConfig.java b/services/core/java/com/android/server/wm/ActivityTaskManagerDebugConfig.java
index 3c562a6..b5675a9 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerDebugConfig.java
@@ -43,14 +43,10 @@
// Enable all debug log categories for activities.
private static final boolean DEBUG_ALL_ACTIVITIES = DEBUG_ALL || false;
- static final boolean DEBUG_PAUSE = DEBUG_ALL || false;
static final boolean DEBUG_RECENTS = DEBUG_ALL || false;
static final boolean DEBUG_RECENTS_TRIM_TASKS = DEBUG_RECENTS || false;
- static final boolean DEBUG_SAVED_STATE = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_STACK = DEBUG_ALL || false;
- static final boolean DEBUG_STATES = DEBUG_ALL_ACTIVITIES || false;
public static final boolean DEBUG_SWITCH = DEBUG_ALL || false;
- static final boolean DEBUG_TASKS = DEBUG_ALL || false;
static final boolean DEBUG_TRANSITION = DEBUG_ALL || false;
static final boolean DEBUG_VISIBILITY = DEBUG_ALL || false;
static final boolean DEBUG_APP = DEBUG_ALL_ACTIVITIES || false;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index c0e31f9..0938d22 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -70,6 +70,7 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IMMERSIVE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
import static com.android.server.am.ActivityManagerService.ANR_TRACE_DIR;
import static com.android.server.am.ActivityManagerService.MY_PID;
import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
@@ -96,9 +97,7 @@
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS;
@@ -324,14 +323,14 @@
/** Hardware-reported OpenGLES version. */
final int GL_ES_VERSION;
- public static final String DUMP_ACTIVITIES_CMD = "activities" ;
- public static final String DUMP_ACTIVITIES_SHORT_CMD = "a" ;
- public static final String DUMP_LASTANR_CMD = "lastanr" ;
- public static final String DUMP_LASTANR_TRACES_CMD = "lastanr-traces" ;
- public static final String DUMP_STARTER_CMD = "starter" ;
- public static final String DUMP_CONTAINERS_CMD = "containers" ;
- public static final String DUMP_RECENTS_CMD = "recents" ;
- public static final String DUMP_RECENTS_SHORT_CMD = "r" ;
+ public static final String DUMP_ACTIVITIES_CMD = "activities";
+ public static final String DUMP_ACTIVITIES_SHORT_CMD = "a";
+ public static final String DUMP_LASTANR_CMD = "lastanr";
+ public static final String DUMP_LASTANR_TRACES_CMD = "lastanr-traces";
+ public static final String DUMP_STARTER_CMD = "starter";
+ public static final String DUMP_CONTAINERS_CMD = "containers";
+ public static final String DUMP_RECENTS_CMD = "recents";
+ public static final String DUMP_RECENTS_SHORT_CMD = "r";
/** This activity is not being relaunched, or being relaunched for a non-resize reason. */
public static final int RELAUNCH_REASON_NONE = 0;
@@ -614,7 +613,9 @@
LAYOUT_REASON_CONFIG_CHANGED,
LAYOUT_REASON_VISIBILITY_CHANGED,
})
- @interface LayoutReason {}
+ @interface LayoutReason {
+ }
+
static final int LAYOUT_REASON_CONFIG_CHANGED = 0x1;
static final int LAYOUT_REASON_VISIBILITY_CHANGED = 0x2;
@@ -653,7 +654,8 @@
*
* @see #updateResumedAppTrace
*/
- private @Nullable ActivityRecord mTracedResumedActivity;
+ @Nullable
+ private ActivityRecord mTracedResumedActivity;
/** If non-null, we are tracking the time the user spends in the currently focused app. */
AppTimeTracker mCurAppTimeTracker;
@@ -716,6 +718,7 @@
int OOM_ADJUSTMENT = 1;
int LRU_UPDATE = 2;
int PROCESS_CHANGE = 3;
+
int caller() default NONE;
}
@@ -873,7 +876,8 @@
}
protected ActivityStackSupervisor createStackSupervisor() {
- final ActivityStackSupervisor supervisor = new ActivityStackSupervisor(this, mH.getLooper());
+ final ActivityStackSupervisor supervisor = new ActivityStackSupervisor(this,
+ mH.getLooper());
supervisor.initialize();
return supervisor;
}
@@ -1128,7 +1132,7 @@
throw new IllegalArgumentException("Bad PendingIntent object");
}
- PendingIntentRecord pir = (PendingIntentRecord)target;
+ PendingIntentRecord pir = (PendingIntentRecord) target;
synchronized (mGlobalLock) {
// If this is coming from the currently resumed activity, it is
@@ -1181,14 +1185,14 @@
// Look for the original activity in the list...
final int N = resolves != null ? resolves.size() : 0;
- for (int i=0; i<N; i++) {
+ for (int i = 0; i < N; i++) {
ResolveInfo rInfo = resolves.get(i);
if (rInfo.activityInfo.packageName.equals(r.packageName)
&& rInfo.activityInfo.name.equals(r.info.name)) {
// We found the current one... the next matching is
// after it.
i++;
- if (i<N) {
+ if (i < N) {
aInfo = resolves.get(i).activityInfo;
}
if (debug) {
@@ -1212,11 +1216,10 @@
intent.setComponent(new ComponentName(
aInfo.applicationInfo.packageName, aInfo.name));
- intent.setFlags(intent.getFlags()&~(
- Intent.FLAG_ACTIVITY_FORWARD_RESULT|
- Intent.FLAG_ACTIVITY_CLEAR_TOP|
- Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
- FLAG_ACTIVITY_NEW_TASK));
+ intent.setFlags(intent.getFlags() & ~(Intent.FLAG_ACTIVITY_FORWARD_RESULT
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP
+ | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
+ | FLAG_ACTIVITY_NEW_TASK));
// Okay now we need to start the new activity, replacing the currently running activity.
// This is a little tricky because we want to start the new one as if the current one is
@@ -1581,11 +1584,12 @@
/**
* Start the recents activity to perform the recents animation.
*
- * @param intent The intent to start the recents activity.
+ * @param intent The intent to start the recents activity.
+ * @param eventTime When the (touch) event is triggered to start recents activity.
* @param recentsAnimationRunner Pass {@code null} to only preload the activity.
*/
@Override
- public void startRecentsActivity(Intent intent, @Deprecated IAssistDataReceiver unused,
+ public void startRecentsActivity(Intent intent, long eventTime,
@Nullable IRecentsAnimationRunner recentsAnimationRunner) {
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "startRecentsActivity()");
final int callingPid = Binder.getCallingPid();
@@ -1605,7 +1609,7 @@
if (recentsAnimationRunner == null) {
anim.preloadRecentsActivity();
} else {
- anim.startRecentsActivity(recentsAnimationRunner);
+ anim.startRecentsActivity(recentsAnimationRunner, eventTime);
}
}
} finally {
@@ -1637,12 +1641,12 @@
*
* If the target display is private or virtual, some restrictions will apply.
*
- * @param displayId Target display id.
- * @param intent Intent used to launch the activity.
+ * @param displayId Target display id.
+ * @param intent Intent used to launch the activity.
* @param resolvedType The MIME type of the intent.
- * @param userId The id of the user for whom the call is made.
+ * @param userId The id of the user for whom the call is made.
* @return {@code true} if a call to start an activity on the target display should succeed and
- * no {@link SecurityException} will be thrown, {@code false} otherwise.
+ * no {@link SecurityException} will be thrown, {@code false} otherwise.
*/
@Override
public final boolean isActivityStartAllowedOnDisplay(int displayId, Intent intent,
@@ -1671,11 +1675,10 @@
/**
* This is the internal entry point for handling Activity.finish().
*
- * @param token The Binder token referencing the Activity we want to finish.
+ * @param token The Binder token referencing the Activity we want to finish.
* @param resultCode Result code, if any, from this Activity.
* @param resultData Result data (Intent), if any, from this Activity.
* @param finishTask Whether to finish the task associated with this Activity.
- *
* @return Returns true if the activity successfully finished, or false if it is still running.
*/
@Override
@@ -2310,14 +2313,14 @@
* There are several possible results of this call:
* - if the task is locked, then we will show the lock toast
* - if there is a task behind the provided task, then that task is made visible and resumed as
- * this task is moved to the back
+ * this task is moved to the back
* - otherwise, if there are no other tasks in the stack:
- * - if this task is in the pinned stack, then we remove the stack completely, which will
- * have the effect of moving the task to the top or bottom of the fullscreen stack
- * (depending on whether it is visible)
- * - otherwise, we simply return home and hide this task
+ * - if this task is in the pinned stack, then we remove the stack completely, which will
+ * have the effect of moving the task to the top or bottom of the fullscreen stack
+ * (depending on whether it is visible)
+ * - otherwise, we simply return home and hide this task
*
- * @param token A reference to the activity we wish to move
+ * @param token A reference to the activity we wish to move
* @param nonRoot If false then this only works if the activity is the root
* of a task; if true it will work for any activity in a task.
* @return Returns true if the move completed, false if not.
@@ -2398,8 +2401,8 @@
return false;
}
- if (DEBUG_STACK) Slog.d(TAG_STACK, "setTaskWindowingMode: moving task=" + taskId
- + " to windowingMode=" + windowingMode + " toTop=" + toTop);
+ ProtoLog.d(WM_DEBUG_TASKS, "setTaskWindowingMode: moving task=%d "
+ + "to windowingMode=%d toTop=%b", taskId, windowingMode, toTop);
if (!task.isActivityTypeStandardOrUndefined()) {
throw new IllegalArgumentException("setTaskWindowingMode: Attempt to move"
@@ -2462,7 +2465,8 @@
@Override
public void unhandledBack() {
- mAmInternal.enforceCallingPermission(android.Manifest.permission.FORCE_BACK, "unhandledBack()");
+ mAmInternal.enforceCallingPermission(android.Manifest.permission.FORCE_BACK,
+ "unhandledBack()");
synchronized (mGlobalLock) {
final long origId = Binder.clearCallingIdentity();
@@ -2509,9 +2513,10 @@
@Override
public void moveTaskToFront(IApplicationThread appThread, String callingPackage, int taskId,
int flags, Bundle bOptions) {
- mAmInternal.enforceCallingPermission(android.Manifest.permission.REORDER_TASKS, "moveTaskToFront()");
+ mAmInternal.enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
+ "moveTaskToFront()");
- if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToFront: moving taskId=" + taskId);
+ ProtoLog.d(WM_DEBUG_TASKS, "moveTaskToFront: moving taskId=%d", taskId);
synchronized (mGlobalLock) {
moveTaskToFrontLocked(appThread, callingPackage, taskId, flags,
SafeActivityOptions.fromBundle(bOptions));
@@ -2543,7 +2548,7 @@
try {
final Task task = mRootWindowContainer.anyTaskForId(taskId);
if (task == null) {
- Slog.d(TAG, "Could not find task for id: "+ taskId);
+ ProtoLog.d(WM_DEBUG_TASKS, "Could not find task for id: %d", taskId);
SafeActivityOptions.abort(options);
return;
}
@@ -2756,8 +2761,8 @@
return;
}
- if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
- + " to stackId=" + stackId + " toTop=" + toTop);
+ ProtoLog.d(WM_DEBUG_TASKS, "moveTaskToStack: moving task=%d to "
+ + "stackId=%d toTop=%b", taskId, stackId, toTop);
final Task stack = mRootWindowContainer.getStack(stackId);
if (stack == null) {
@@ -2780,7 +2785,7 @@
* Moves the specified task to the primary-split-screen stack.
*
* @param taskId Id of task to move.
- * @param toTop If the task and stack should be moved to the top.
+ * @param toTop If the task and stack should be moved to the top.
* @return Whether the task was successfully put into splitscreen.
*/
@Override
@@ -3293,8 +3298,8 @@
if (intent.getSourceBounds() != null) {
intent.setSourceBounds(null);
}
- if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0) {
- if ((intent.getFlags()&Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS) == 0) {
+ if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0) {
+ if ((intent.getFlags() & Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS) == 0) {
// The caller has added this as an auto-remove task... that makes no
// sense, so turn off auto-remove.
intent.addFlags(Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
@@ -3492,8 +3497,8 @@
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
- if (DEBUG_STACK) Slog.d(TAG_STACK, "moveStackToDisplay: moving stackId=" + stackId
- + " to displayId=" + displayId);
+ ProtoLog.d(WM_DEBUG_TASKS, "moveStackToDisplay: moving stackId=%d to "
+ + "displayId=%d", stackId, displayId);
mRootWindowContainer.moveStackToDisplay(stackId, displayId, ON_TOP);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -3652,14 +3657,16 @@
try {
if (AppGlobals.getPackageManager().isUidPrivileged(callingUid)) {
allowed = true;
- if (DEBUG_TASKS) Slog.w(TAG, caller + ": caller " + callingUid
- + " is using old GET_TASKS but privileged; allowing");
+ ProtoLog.w(WM_DEBUG_TASKS,
+ "%s: caller %d is using old GET_TASKS but privileged; allowing",
+ caller, callingUid);
}
} catch (RemoteException e) {
}
}
- if (DEBUG_TASKS) Slog.w(TAG, caller + ": caller " + callingUid
- + " does not hold REAL_GET_TASKS; limiting output");
+ ProtoLog.w(WM_DEBUG_TASKS,
+ "%s: caller %d does not hold REAL_GET_TASKS; limiting output", caller,
+ callingUid);
}
return allowed;
}
@@ -3978,7 +3985,8 @@
@Override
public void suppressResizeConfigChanges(boolean suppress) throws RemoteException {
- mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "suppressResizeConfigChanges()");
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS,
+ "suppressResizeConfigChanges()");
synchronized (mGlobalLock) {
mSuppressResizeConfigChanges = suppress;
}
@@ -3988,10 +3996,9 @@
* Moves the top activity in the input stackId to the pinned stack.
*
* @param stackId Id of stack to move the top activity to pinned stack.
- * @param bounds Bounds to use for pinned stack.
- *
+ * @param bounds Bounds to use for pinned stack.
* @return True if the top activity of the input stack was successfully moved to the pinned
- * stack.
+ * stack.
*/
@Override
public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) {
@@ -4146,7 +4153,7 @@
if (params.hasSetAspectRatio()
&& !mWindowManager.isValidPictureInPictureAspectRatio(
- r.mDisplayContent, params.getAspectRatio())) {
+ r.mDisplayContent, params.getAspectRatio())) {
final float minAspectRatio = mContext.getResources().getFloat(
com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
final float maxAspectRatio = mContext.getResources().getFloat(
@@ -4194,8 +4201,8 @@
final WindowContainerTransaction wct = new WindowContainerTransaction();
final Rect primaryRect =
tempDockedTaskInsetBounds != null ? tempDockedTaskInsetBounds
- : (tempDockedTaskBounds != null ? tempDockedTaskBounds
- : dockedBounds);
+ : (tempDockedTaskBounds != null ? tempDockedTaskBounds
+ : dockedBounds);
wct.setBounds(primary.mRemoteToken.toWindowContainerToken(), primaryRect);
Rect otherRect = tempOtherTaskInsetBounds != null ? tempOtherTaskInsetBounds
: tempOtherTaskBounds;
@@ -4464,7 +4471,8 @@
public void updateLockTaskFeatures(int userId, int flags) {
final int callingUid = Binder.getCallingUid();
if (callingUid != 0 && callingUid != SYSTEM_UID) {
- mAmInternal.enforceCallingPermission(android.Manifest.permission.UPDATE_LOCK_TASK_PACKAGES,
+ mAmInternal.enforceCallingPermission(
+ android.Manifest.permission.UPDATE_LOCK_TASK_PACKAGES,
"updateLockTaskFeatures()");
}
synchronized (mGlobalLock) {
@@ -4768,11 +4776,12 @@
/**
* Clears launch params for the given package.
+ *
* @param packageNames the names of the packages of which the launch params are to be cleared
*/
@Override
public void clearLaunchParamsForPackages(List<String> packageNames) {
- mAmInternal.enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS,
"clearLaunchParamsForPackages");
synchronized (mGlobalLock) {
for (int i = 0; i < packageNames.size(); ++i) {
@@ -4787,7 +4796,7 @@
*/
@Override
public void setDisplayToSingleTaskInstance(int displayId) {
- mAmInternal.enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS,
"setDisplayToSingleTaskInstance");
final long origId = Binder.clearCallingIdentity();
try {
@@ -4806,7 +4815,7 @@
*/
@Override
public void requestPictureInPictureMode(IBinder token) throws RemoteException {
- mAmInternal.enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS,
"requestPictureInPictureMode");
final long origId = Binder.clearCallingIdentity();
try {
@@ -4902,7 +4911,7 @@
boolean needSep = printedAnything;
boolean printed = ActivityStackSupervisor.printThisActivity(pw,
- mRootWindowContainer.getTopResumedActivity(), dumpPackage, needSep,
+ mRootWindowContainer.getTopResumedActivity(), dumpPackage, needSep,
" ResumedActivity: ", null);
if (printed) {
printedAnything = true;
@@ -4936,19 +4945,20 @@
/**
* There are three things that cmd can be:
- * - a flattened component name that matches an existing activity
- * - the cmd arg isn't the flattened component name of an existing activity:
- * dump all activity whose component contains the cmd as a substring
- * - A hex number of the ActivityRecord object instance.
+ * - a flattened component name that matches an existing activity
+ * - the cmd arg isn't the flattened component name of an existing activity:
+ * dump all activity whose component contains the cmd as a substring
+ * - A hex number of the ActivityRecord object instance.
* <p>
* The caller should not hold lock when calling this method because it will wait for the
* activities to complete the dump.
*
- * @param dumpVisibleStacksOnly dump activity with {@param name} only if in a visible stack
- * @param dumpFocusedStackOnly dump activity with {@param name} only if in the focused stack
+ * @param dumpVisibleStacksOnly dump activity with {@param name} only if in a visible stack
+ * @param dumpFocusedStackOnly dump activity with {@param name} only if in the focused stack
*/
protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
- int opti, boolean dumpAll, boolean dumpVisibleStacksOnly, boolean dumpFocusedStackOnly) {
+ int opti, boolean dumpAll, boolean dumpVisibleStacksOnly,
+ boolean dumpFocusedStackOnly) {
ArrayList<ActivityRecord> activities;
synchronized (mGlobalLock) {
@@ -4975,9 +4985,12 @@
final Task task = r.getTask();
if (lastTask != task) {
lastTask = task;
- pw.print("TASK "); pw.print(lastTask.affinity);
- pw.print(" id="); pw.print(lastTask.mTaskId);
- pw.print(" userId="); pw.println(lastTask.mUserId);
+ pw.print("TASK ");
+ pw.print(lastTask.affinity);
+ pw.print(" id=");
+ pw.print(lastTask.mTaskId);
+ pw.print(" userId=");
+ pw.println(lastTask.mUserId);
if (dumpAll) {
lastTask.dump(pw, " ");
}
@@ -4997,8 +5010,11 @@
String innerPrefix = prefix + " ";
IApplicationThread appThread = null;
synchronized (mGlobalLock) {
- pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
- pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
+ pw.print(prefix);
+ pw.print("ACTIVITY ");
+ pw.print(r.shortComponentName);
+ pw.print(" ");
+ pw.print(Integer.toHexString(System.identityHashCode(r)));
pw.print(" pid=");
if (r.hasProcess()) {
pw.println(r.app.getPid());
@@ -5057,7 +5073,7 @@
public Configuration getConfiguration() {
Configuration ci;
- synchronized(mGlobalLock) {
+ synchronized (mGlobalLock) {
ci = new Configuration(getGlobalConfigurationForCallingPid());
ci.userSetLocale = false;
}
@@ -5902,7 +5918,7 @@
final IBinder threadBinder = thread.asBinder();
final ArrayMap<String, SparseArray<WindowProcessController>> pmap = mProcessNames.getMap();
- for (int i = pmap.size()-1; i >= 0; i--) {
+ for (int i = pmap.size() - 1; i >= 0; i--) {
final SparseArray<WindowProcessController> procs = pmap.valueAt(i);
for (int j = procs.size() - 1; j >= 0; j--) {
final WindowProcessController proc = procs.valueAt(j);
@@ -5967,7 +5983,7 @@
TimeMigrationUtils.formatMillisWithFixedFormat(System.currentTimeMillis());
sb.append(timeString);
sb.append(": ");
- TimeUtils.formatDuration(SystemClock.uptimeMillis()-startTime, sb);
+ TimeUtils.formatDuration(SystemClock.uptimeMillis() - startTime, sb);
sb.append(" since ");
sb.append(msg);
FileOutputStream fos = new FileOutputStream(tracesFile);
@@ -5990,7 +6006,7 @@
File lastTracesFile = null;
File curTracesFile = null;
- for (int i=9; i>=0; i--) {
+ for (int i = 9; i >= 0; i--) {
String name = String.format(Locale.US, "slow%02d.txt", i);
curTracesFile = new File(tracesDir, name);
if (curTracesFile.exists()) {
@@ -6037,7 +6053,8 @@
case REPORT_TIME_TRACKER_MSG: {
AppTimeTracker tracker = (AppTimeTracker) msg.obj;
tracker.deliverResult(mContext);
- } break;
+ }
+ break;
}
}
}
@@ -6233,7 +6250,7 @@
*/
@Override
public void setVr2dDisplayId(int vr2dDisplayId) {
- if (DEBUG_STACK) Slog.d(TAG, "setVr2dDisplayId called for: " + vr2dDisplayId);
+ ProtoLog.d(WM_DEBUG_TASKS, "setVr2dDisplayId called for: %d", vr2dDisplayId);
synchronized (mGlobalLock) {
mVr2dDisplayId = vr2dDisplayId;
}
@@ -6541,7 +6558,7 @@
* Set the corresponding display information for the process global configuration. To be
* called when we need to show IME on a different display.
*
- * @param pid The process id associated with the IME window.
+ * @param pid The process id associated with the IME window.
* @param displayId The ID of the display showing the IME.
*/
@Override
@@ -6553,7 +6570,7 @@
if (pid == MY_PID || pid < 0) {
ProtoLog.w(WM_DEBUG_CONFIGURATION,
- "Trying to update display configuration for system/invalid process.");
+ "Trying to update display configuration for system/invalid process.");
return;
}
synchronized (mGlobalLock) {
@@ -6943,7 +6960,8 @@
pw.println();
getActivityStartController().dump(pw, " ", null);
pw.println();
- pw.println("-------------------------------------------------------------------------------");
+ pw.println("-------------------------------------------------------------------"
+ + "------------");
dumpActivitiesLocked(null /* fd */, pw, null /* args */, 0 /* opti */,
true /* dumpAll */, false /* dumpClient */, null /* dumpPackage */,
"" /* header */);
diff --git a/services/core/java/com/android/server/wm/DisplayAreaGroup.java b/services/core/java/com/android/server/wm/DisplayAreaGroup.java
new file mode 100644
index 0000000..bcf8c7c
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DisplayAreaGroup.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.content.pm.ActivityInfo.reverseOrientation;
+
+import android.content.pm.ActivityInfo;
+import android.graphics.Rect;
+
+/** The root of a partition of the logical display. */
+class DisplayAreaGroup extends RootDisplayArea {
+
+ DisplayAreaGroup(WindowManagerService wms, String name, int featureId) {
+ super(wms, name, featureId);
+ }
+
+ @Override
+ boolean isOrientationDifferentFromDisplay() {
+ if (mDisplayContent == null) {
+ return false;
+ }
+
+ final Rect bounds = getBounds();
+ final Rect displayBounds = mDisplayContent.getBounds();
+
+ return (bounds.width() < bounds.height())
+ != (displayBounds.width() < displayBounds.height());
+ }
+
+ @ActivityInfo.ScreenOrientation
+ @Override
+ int getOrientation(int candidate) {
+ int orientation = super.getOrientation(candidate);
+
+ // Reverse the requested orientation if the orientation of this DAG is different from the
+ // display, so that when the display rotates to the reversed orientation, this DAG will be
+ // in the requested orientation, so as the requested app.
+ // For example, if the display is 1200x900 (landscape), and this DAG is 600x900 (portrait).
+ // When an app below this DAG is requesting landscape, it should actually request the
+ // display to be portrait, so that the DAG and the app will be in landscape.
+ return isOrientationDifferentFromDisplay() ? reverseOrientation(orientation) : orientation;
+ }
+}
diff --git a/services/core/java/com/android/server/wm/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java
index 56e1187..a0074a2 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsController.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsController.java
@@ -144,11 +144,11 @@
mTmpParams.mPreferredTaskDisplayArea, true /* onTop */);
}
- if (mTmpParams.hasWindowingMode()
- && mTmpParams.mWindowingMode != task.getRootTask().getWindowingMode()) {
+ if (mTmpParams.hasWindowingMode() && task.isRootTask()
+ && mTmpParams.mWindowingMode != task.getWindowingMode()) {
final int activityType = activity != null
? activity.getActivityType() : task.getActivityType();
- task.getRootTask().setWindowingMode(task.getDisplayArea().validateWindowingMode(
+ task.setWindowingMode(task.getDisplayArea().validateWindowingMode(
mTmpParams.mWindowingMode, activity, task, activityType));
}
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 255b3f1..d292580 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -35,10 +35,10 @@
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.os.Process.SYSTEM_UID;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS_TRIM_TASKS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
@@ -72,6 +72,7 @@
import android.view.WindowManagerPolicyConstants.PointerEventListener;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.am.ActivityManagerService;
@@ -157,7 +158,8 @@
*/
private int mRecentsUid = -1;
private ComponentName mRecentsComponent = null;
- private @Nullable String mFeatureId;
+ @Nullable
+ private String mFeatureId;
/**
* Mapping of user id -> whether recent tasks have been loaded for that user.
@@ -397,7 +399,7 @@
/**
* @return whether the given component is the recents component and shares the same uid as the
- * recents component.
+ * recents component.
*/
boolean isRecentsComponent(ComponentName cn, int uid) {
return cn.equals(mRecentsComponent) && UserHandle.isSameApp(uid, mRecentsUid);
@@ -423,7 +425,8 @@
/**
* @return the featureId for the recents component.
*/
- @Nullable String getRecentsComponentFeatureId() {
+ @Nullable
+ String getRecentsComponentFeatureId() {
return mFeatureId;
}
@@ -617,7 +620,7 @@
/** Remove recent tasks for a user. */
private void removeTasksForUserLocked(int userId) {
- if(userId <= 0) {
+ if (userId <= 0) {
Slog.i(TAG, "Can't remove recent task on user " + userId);
return;
}
@@ -625,8 +628,8 @@
for (int i = mTasks.size() - 1; i >= 0; --i) {
Task task = mTasks.get(i);
if (task.mUserId == userId) {
- if(DEBUG_TASKS) Slog.i(TAG_TASKS,
- "remove RecentTask " + task + " when finishing user" + userId);
+ ProtoLog.i(WM_DEBUG_TASKS, "remove RecentTask %s when finishing user "
+ + "%d", task, userId);
remove(task);
}
}
@@ -640,11 +643,11 @@
&& packageNames.contains(task.realActivity.getPackageName())
&& task.mUserId == userId
&& task.realActivitySuspended != suspended) {
- task.realActivitySuspended = suspended;
- if (suspended) {
- mSupervisor.removeTask(task, false, REMOVE_FROM_RECENTS, "suspended-package");
- }
- notifyTaskPersisterLocked(task, false);
+ task.realActivitySuspended = suspended;
+ if (suspended) {
+ mSupervisor.removeTask(task, false, REMOVE_FROM_RECENTS, "suspended-package");
+ }
+ notifyTaskPersisterLocked(task, false);
}
}
}
@@ -780,25 +783,31 @@
continue;
} else {
// Otherwise just not available for now.
- if (DEBUG_RECENTS && task.isAvailable) Slog.d(TAG_RECENTS,
- "Making recent unavailable: " + task);
+ if (DEBUG_RECENTS && task.isAvailable) {
+ Slog.d(TAG_RECENTS,
+ "Making recent unavailable: " + task);
+ }
task.isAvailable = false;
}
} else {
if (!ai.enabled || !ai.applicationInfo.enabled
|| (ai.applicationInfo.flags
- & ApplicationInfo.FLAG_INSTALLED) == 0) {
- if (DEBUG_RECENTS && task.isAvailable) Slog.d(TAG_RECENTS,
- "Making recent unavailable: " + task
- + " (enabled=" + ai.enabled + "/"
- + ai.applicationInfo.enabled
- + " flags="
- + Integer.toHexString(ai.applicationInfo.flags)
- + ")");
+ & ApplicationInfo.FLAG_INSTALLED) == 0) {
+ if (DEBUG_RECENTS && task.isAvailable) {
+ Slog.d(TAG_RECENTS,
+ "Making recent unavailable: " + task
+ + " (enabled=" + ai.enabled + "/"
+ + ai.applicationInfo.enabled
+ + " flags="
+ + Integer.toHexString(ai.applicationInfo.flags)
+ + ")");
+ }
task.isAvailable = false;
} else {
- if (DEBUG_RECENTS && !task.isAvailable) Slog.d(TAG_RECENTS,
- "Making recent available: " + task);
+ if (DEBUG_RECENTS && !task.isAvailable) {
+ Slog.d(TAG_RECENTS,
+ "Making recent available: " + task);
+ }
task.isAvailable = true;
}
}
@@ -974,16 +983,20 @@
final int size = mTasks.size();
for (int i = 0; i < size; i++) {
final Task task = mTasks.get(i);
- if (TaskPersister.DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task
- + " persistable=" + task.isPersistable);
+ if (TaskPersister.DEBUG) {
+ Slog.d(TAG, "LazyTaskWriter: task=" + task
+ + " persistable=" + task.isPersistable);
+ }
final Task rootTask = task.getRootTask();
if ((task.isPersistable || task.inRecents)
&& (rootTask == null || !rootTask.isHomeOrRecentsStack())) {
if (TaskPersister.DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
persistentTaskIds.add(task.mTaskId);
} else {
- if (TaskPersister.DEBUG) Slog.d(TAG, "omitting from persistentTaskIds task="
- + task);
+ if (TaskPersister.DEBUG) {
+ Slog.d(TAG, "omitting from persistentTaskIds task="
+ + task);
+ }
}
}
}
@@ -1051,8 +1064,10 @@
// TODO: VI what about if it's just an activity?
// Probably nothing to do here
if (task.voiceSession != null) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "addRecent: not adding voice interaction " + task);
+ if (DEBUG_RECENTS) {
+ Slog.d(TAG_RECENTS,
+ "addRecent: not adding voice interaction " + task);
+ }
return;
}
// Another quick case: check if the top-most recent task is the same.
@@ -1064,8 +1079,10 @@
// tasks that are at the top.
if (isAffiliated && recentsCount > 0 && task.inRecents
&& task.mAffiliatedTaskId == mTasks.get(0).mAffiliatedTaskId) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: affiliated " + mTasks.get(0)
- + " at top when adding " + task);
+ if (DEBUG_RECENTS) {
+ Slog.d(TAG_RECENTS, "addRecent: affiliated " + mTasks.get(0)
+ + " at top when adding " + task);
+ }
return;
}
@@ -1122,14 +1139,17 @@
if (other == task.mNextAffiliate) {
// We found the index of our next affiliation, which is who is
// before us in the list, so add after that point.
- taskIndex = otherIndex+1;
+ taskIndex = otherIndex + 1;
} else {
// We found the index of our previous affiliation, which is who is
// after us in the list, so add at their position.
taskIndex = otherIndex;
}
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "addRecent: new affiliated task added at " + taskIndex + ": " + task);
+ if (DEBUG_RECENTS) {
+ Slog.d(TAG_RECENTS,
+ "addRecent: new affiliated task added at " + taskIndex + ": "
+ + task);
+ }
mTasks.add(taskIndex, task);
notifyTaskAdded(task);
@@ -1143,13 +1163,17 @@
// everything and then go through our general path of adding a new task.
needAffiliationFix = true;
} else {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "addRecent: couldn't find other affiliation " + other);
+ if (DEBUG_RECENTS) {
+ Slog.d(TAG_RECENTS,
+ "addRecent: couldn't find other affiliation " + other);
+ }
needAffiliationFix = true;
}
} else {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "addRecent: adding affiliated task without next/prev:" + task);
+ if (DEBUG_RECENTS) {
+ Slog.d(TAG_RECENTS,
+ "addRecent: adding affiliated task without next/prev:" + task);
+ }
needAffiliationFix = true;
}
}
@@ -1204,8 +1228,10 @@
final Task task = mTasks.remove(recentsCount - 1);
notifyTaskRemoved(task, true /* wasTrimmed */, false /* killProcess */);
recentsCount--;
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming over max-recents task=" + task
- + " max=" + mGlobalMaxNumTasks);
+ if (DEBUG_RECENTS_TRIM_TASKS) {
+ Slog.d(TAG, "Trimming over max-recents task=" + task
+ + " max=" + mGlobalMaxNumTasks);
+ }
}
// Remove any tasks that belong to currently quiet profiles
@@ -1216,13 +1242,15 @@
if (userInfo != null && userInfo.isManagedProfile() && userInfo.isQuietModeEnabled()) {
mTmpQuietProfileUserIds.put(userId, true);
}
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "User: " + userInfo
- + " quiet=" + mTmpQuietProfileUserIds.get(userId));
+ if (DEBUG_RECENTS_TRIM_TASKS) {
+ Slog.d(TAG, "User: " + userInfo
+ + " quiet=" + mTmpQuietProfileUserIds.get(userId));
+ }
}
// Remove any inactive tasks, calculate the latest set of visible tasks.
int numVisibleTasks = 0;
- for (int i = 0; i < mTasks.size();) {
+ for (int i = 0; i < mTasks.size(); ) {
final Task task = mTasks.get(i);
if (isActiveRecentTask(task, mTmpQuietProfileUserIds)) {
@@ -1246,8 +1274,10 @@
} else {
// Fall through to trim visible tasks that are no longer in range and
// trimmable
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG,
- "Trimming out-of-range visible task=" + task);
+ if (DEBUG_RECENTS_TRIM_TASKS) {
+ Slog.d(TAG,
+ "Trimming out-of-range visible task=" + task);
+ }
}
}
} else {
@@ -1266,8 +1296,10 @@
* @return whether the given task should be considered active.
*/
private boolean isActiveRecentTask(Task task, SparseBooleanArray quietProfileUserIds) {
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "isActiveRecentTask: task=" + task
- + " globalMax=" + mGlobalMaxNumTasks);
+ if (DEBUG_RECENTS_TRIM_TASKS) {
+ Slog.d(TAG, "isActiveRecentTask: task=" + task
+ + " globalMax=" + mGlobalMaxNumTasks);
+ }
if (quietProfileUserIds.get(task.mUserId)) {
// Quiet profile user's tasks are never active
@@ -1280,8 +1312,10 @@
final Task affiliatedTask = getTask(task.mAffiliatedTaskId);
if (affiliatedTask != null) {
if (!isActiveRecentTask(affiliatedTask, quietProfileUserIds)) {
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG,
- "\taffiliatedWithTask=" + affiliatedTask + " is not active");
+ if (DEBUG_RECENTS_TRIM_TASKS) {
+ Slog.d(TAG,
+ "\taffiliatedWithTask=" + affiliatedTask + " is not active");
+ }
return false;
}
}
@@ -1296,13 +1330,15 @@
*/
@VisibleForTesting
boolean isVisibleRecentTask(Task task) {
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "isVisibleRecentTask: task=" + task
- + " minVis=" + mMinNumVisibleTasks + " maxVis=" + mMaxNumVisibleTasks
- + " sessionDuration=" + mActiveTasksSessionDurationMs
- + " inactiveDuration=" + task.getInactiveDuration()
- + " activityType=" + task.getActivityType()
- + " windowingMode=" + task.getWindowingMode()
- + " intentFlags=" + task.getBaseIntent().getFlags());
+ if (DEBUG_RECENTS_TRIM_TASKS) {
+ Slog.d(TAG, "isVisibleRecentTask: task=" + task
+ + " minVis=" + mMinNumVisibleTasks + " maxVis=" + mMaxNumVisibleTasks
+ + " sessionDuration=" + mActiveTasksSessionDurationMs
+ + " inactiveDuration=" + task.getInactiveDuration()
+ + " activityType=" + task.getActivityType()
+ + " windowingMode=" + task.getWindowingMode()
+ + " intentFlags=" + task.getBaseIntent().getFlags());
+ }
switch (task.getActivityType()) {
case ACTIVITY_TYPE_HOME:
@@ -1468,8 +1504,10 @@
mHiddenTasks.add(removedTask);
}
notifyTaskRemoved(removedTask, false /* wasTrimmed */, false /* killProcess */);
- if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming task=" + removedTask
- + " for addition of task=" + task);
+ if (DEBUG_RECENTS_TRIM_TASKS) {
+ Slog.d(TAG, "Trimming task=" + removedTask
+ + " for addition of task=" + task);
+ }
}
notifyTaskPersisterLocked(removedTask, false /* flush */);
}
@@ -1622,16 +1660,20 @@
top = top.mNextAffiliate;
topIndex--;
}
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: adding affilliates starting at "
- + topIndex + " from intial " + taskIndex);
+ if (DEBUG_RECENTS) {
+ Slog.d(TAG_RECENTS, "addRecent: adding affiliates starting at "
+ + topIndex + " from initial " + taskIndex);
+ }
// Find the end of the chain, doing a validity check along the way.
boolean isValid = top.mAffiliatedTaskId == task.mAffiliatedTaskId;
int endIndex = topIndex;
Task prev = top;
while (endIndex < recentsCount) {
Task cur = mTasks.get(endIndex);
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: looking at next chain @"
- + endIndex + " " + cur);
+ if (DEBUG_RECENTS) {
+ Slog.d(TAG_RECENTS, "addRecent: looking at next chain @"
+ + endIndex + " " + cur);
+ }
if (cur == top) {
// Verify start of the chain.
if (cur.mNextAffiliate != null || cur.mNextAffiliateTaskId != INVALID_TASK_ID) {
@@ -1701,14 +1743,18 @@
if (isValid) {
// All looks good, we can just move all of the affiliated tasks
// to the top.
- for (int i=topIndex; i<=endIndex; i++) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: moving affiliated " + task
- + " from " + i + " to " + (i-topIndex));
+ for (int i = topIndex; i <= endIndex; i++) {
+ if (DEBUG_RECENTS) {
+ Slog.d(TAG_RECENTS, "addRecent: moving affiliated " + task
+ + " from " + i + " to " + (i - topIndex));
+ }
Task cur = mTasks.remove(i);
mTasks.add(i - topIndex, cur);
}
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: done moving tasks " + topIndex
- + " to " + endIndex);
+ if (DEBUG_RECENTS) {
+ Slog.d(TAG_RECENTS, "addRecent: done moving tasks " + topIndex
+ + " to " + endIndex);
+ }
return true;
}
@@ -1768,7 +1814,9 @@
printedHeader = true;
printedAnything = true;
}
- pw.print(" * Recent #"); pw.print(i); pw.print(": ");
+ pw.print(" * Recent #");
+ pw.print(i);
+ pw.print(": ");
pw.println(task);
if (dumpAll) {
task.dump(pw, " ");
@@ -1787,7 +1835,7 @@
boolean match = taskInfo.baseIntent != null
&& taskInfo.baseIntent.getComponent() != null
&& dumpPackage.equals(
- taskInfo.baseIntent.getComponent().getPackageName());
+ taskInfo.baseIntent.getComponent().getPackageName());
if (!match) {
match |= taskInfo.baseActivity != null
&& dumpPackage.equals(taskInfo.baseActivity.getPackageName());
@@ -1818,7 +1866,9 @@
printedAnything = true;
}
- pw.print(" * RecentTaskInfo #"); pw.print(i); pw.print(": ");
+ pw.print(" * RecentTaskInfo #");
+ pw.print(i);
+ pw.print(": ");
taskInfo.dump(pw, " ");
}
}
@@ -1842,8 +1892,8 @@
/**
* @return Whether the activity types and windowing modes of the two tasks are considered
- * compatible. This is necessary because we currently don't persist the activity type
- * or the windowing mode with the task, so they can be undefined when restored.
+ * compatible. This is necessary because we currently don't persist the activity type
+ * or the windowing mode with the task, so they can be undefined when restored.
*/
private boolean hasCompatibleActivityTypeAndWindowingMode(Task t1, Task t2) {
final int activityType = t1.getActivityType();
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 35338bb..1cf50ab 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -161,7 +161,7 @@
}
}
- void startRecentsActivity(IRecentsAnimationRunner recentsAnimationRunner) {
+ void startRecentsActivity(IRecentsAnimationRunner recentsAnimationRunner, long eventTime) {
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "startRecentsActivity(): intent=%s", mTargetIntent);
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "RecentsAnimation#startRecentsActivity");
@@ -249,8 +249,13 @@
// we fetch the visible tasks to be controlled by the animation
mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ ActivityOptions options = null;
+ if (eventTime > 0) {
+ options = ActivityOptions.makeBasic();
+ options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_RECENTS_ANIMATION, eventTime);
+ }
mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState,
- START_TASK_TO_FRONT, targetActivity, null /* options */);
+ START_TASK_TO_FRONT, targetActivity, options);
// Register for stack order changes
mDefaultTaskDisplayArea.registerStackOrderChangedListener(this);
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 42a20ff..38d20a8 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -932,7 +932,7 @@
!topApp.fillsParent(), new Rect(),
insets, mTask.getPrefixOrderIndex(), new Point(mBounds.left, mBounds.top),
mLocalBounds, mBounds, mTask.getWindowConfiguration(),
- mIsRecentTaskInvisible, null, null);
+ mIsRecentTaskInvisible, null, null, mTask.getPictureInPictureParams());
return mTarget;
}
diff --git a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
index c3953b4..9181a0f 100644
--- a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
+++ b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
@@ -17,14 +17,12 @@
package com.android.server.wm;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
-import static com.android.server.wm.Task.TAG_TASKS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
import android.app.ActivityOptions;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Debug;
-import android.util.Slog;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.pooled.PooledConsumer;
@@ -201,8 +199,8 @@
noOptions = takeOption(p, noOptions);
- if (DEBUG_TASKS) Slog.w(TAG_TASKS,
- "resetTaskIntendedTask: calling finishActivity on " + p);
+ ProtoLog.w(WM_DEBUG_TASKS, "resetTaskIntendedTask: calling finishActivity "
+ + "on %s", p);
p.finishIfPossible(reason, false /* oomAdj */);
}
}
@@ -213,15 +211,15 @@
while (!mResultActivities.isEmpty()) {
final ActivityRecord p = mResultActivities.remove(0);
- if (ignoreFinishing&& p.finishing) continue;
+ if (ignoreFinishing && p.finishing) continue;
if (takeOptions) {
noOptions = takeOption(p, noOptions);
}
ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Removing activity %s from task=%s "
- + "adding to task=%s Callers=%s", p, mTask, targetTask, Debug.getCallers(4));
- if (DEBUG_TASKS) Slog.v(TAG_TASKS,
- "Pushing next activity " + p + " out to target's task " + target);
+ + "adding to task=%s Callers=%s", p, mTask, targetTask, Debug.getCallers(4));
+ ProtoLog.v(WM_DEBUG_TASKS, "Pushing next activity %s out to target's task %s", p,
+ target);
p.reparent(targetTask, position, "resetTargetTaskIfNeeded");
}
}
@@ -253,8 +251,8 @@
// If the activity currently at the bottom has the same task affinity as
// the one we are moving, then merge it into the same task.
targetTask = task;
- if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity "
- + r + " out to bottom task " + targetTask);
+ ProtoLog.v(WM_DEBUG_TASKS, "Start pushing activity %s out to bottom task %s", r,
+ targetTask);
}
if (targetTask == null) {
if (alwaysCreateTask) {
diff --git a/services/core/java/com/android/server/wm/RootDisplayArea.java b/services/core/java/com/android/server/wm/RootDisplayArea.java
index faed7fa..d9a8773 100644
--- a/services/core/java/com/android/server/wm/RootDisplayArea.java
+++ b/services/core/java/com/android/server/wm/RootDisplayArea.java
@@ -27,7 +27,8 @@
/**
* Root of a {@link DisplayArea} hierarchy. It can be either the {@link DisplayContent} as the root
- * of the whole logical display, or the root of a {@link DisplayArea} group.
+ * of the whole logical display, or a {@link DisplayAreaGroup} as the root of a partition of the
+ * logical display.
*/
class RootDisplayArea extends DisplayArea<DisplayArea> {
@@ -50,6 +51,16 @@
super(wms, Type.ANY, name, featureId);
}
+ @Override
+ RootDisplayArea getRootDisplayArea() {
+ return this;
+ }
+
+ /** Whether the orientation (based on dimensions) of this root is different from the Display. */
+ boolean isOrientationDifferentFromDisplay() {
+ return false;
+ }
+
/** Finds the {@link DisplayArea.Tokens} that this type of window should be attached to. */
DisplayArea.Tokens findAreaForToken(WindowToken token) {
int windowLayerFromType = token.getWindowLayerFromType();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 2df56a3..cabf1bf 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -44,6 +44,8 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.policy.PhoneWindowManager.SYSTEM_DIALOG_REASON_ASSIST;
@@ -55,11 +57,8 @@
import static com.android.server.wm.ActivityStackSupervisor.printThisActivity;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
@@ -179,7 +178,6 @@
private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
static final String TAG_TASKS = TAG + POSTFIX_TASKS;
- private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
static final String TAG_STATES = TAG + POSTFIX_STATES;
private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
@@ -235,7 +233,9 @@
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
})
- public @interface AnyTaskForIdMatchTaskMode {}
+ public @interface AnyTaskForIdMatchTaskMode {
+ }
+
// Match only tasks in the current stacks
static final int MATCH_TASK_IN_STACKS_ONLY = 0;
// Match either tasks in the current stacks, or in the recent tasks if not found in the stacks
@@ -305,6 +305,7 @@
};
private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
+
static class FindTaskResult implements Function<Task, Boolean> {
ActivityRecord mRecord;
boolean mIdealMatch;
@@ -335,7 +336,8 @@
// If documentData is non-null then it must match the existing task data.
documentData = isDocument ? intent.getData() : null;
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + parent);
+ ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of %s in %s", target,
+ parent);
parent.forAllLeafTasks(this);
}
@@ -353,12 +355,12 @@
public Boolean apply(Task task) {
if (task.voiceSession != null) {
// We never match voice sessions; those always run independently.
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
+ ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: voice session", task);
return false;
}
if (task.mUserId != userId) {
// Looking for a different task.
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user");
+ ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: different user", task);
return false;
}
@@ -366,11 +368,11 @@
final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */);
if (r == null || r.finishing || r.mUserId != userId
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
+ ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch root %s", task, r);
return false;
}
if (!r.hasCompatibleActivityType(mTarget)) {
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type");
+ ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch activity type", task);
return false;
}
@@ -389,40 +391,40 @@
taskDocumentData = null;
}
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
- + (task.realActivity != null ? task.realActivity.flattenToShortString() : "")
- + "/aff=" + r.getTask().rootAffinity + " to new cls="
- + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
+ ProtoLog.d(WM_DEBUG_TASKS, "Comparing existing cls=%s /aff=%s to new cls=%s /aff=%s",
+ r.getTask().rootAffinity, intent.getComponent().flattenToShortString(),
+ info.taskAffinity, (task.realActivity != null
+ ? task.realActivity.flattenToShortString() : ""));
// TODO Refactor to remove duplications. Check if logic can be simplified.
if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
&& Objects.equals(documentData, taskDocumentData)) {
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
+ ProtoLog.d(WM_DEBUG_TASKS, "Found matching class!");
//dump();
- if (DEBUG_TASKS) Slog.d(TAG_TASKS,
- "For Intent " + intent + " bringing to top: " + r.intent);
+ ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", intent, r.intent);
mRecord = r;
mIdealMatch = true;
return true;
} else if (affinityIntent != null && affinityIntent.getComponent() != null
&& affinityIntent.getComponent().compareTo(cls) == 0 &&
Objects.equals(documentData, taskDocumentData)) {
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
- if (DEBUG_TASKS) Slog.d(TAG_TASKS,
- "For Intent " + intent + " bringing to top: " + r.intent);
+ ProtoLog.d(WM_DEBUG_TASKS, "Found matching class!");
+ ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", intent, r.intent);
mRecord = r;
mIdealMatch = true;
return true;
} else if (!isDocument && !taskIsDocument
&& mRecord == null && task.rootAffinity != null) {
if (task.rootAffinity.equals(mTarget.taskAffinity)) {
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!");
+ ProtoLog.d(WM_DEBUG_TASKS, "Found matching affinity candidate!");
// It is possible for multiple tasks to have the same root affinity especially
// if they are in separate stacks. We save off this candidate, but keep looking
// to see if there is a better candidate.
mRecord = r;
mIdealMatch = false;
}
- } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
+ } else {
+ ProtoLog.d(WM_DEBUG_TASKS, "Not a match: %s", task);
+ }
return false;
}
@@ -578,6 +580,7 @@
* Returns {@code true} if the callingUid has any non-toast window currently visible to the
* user. Also ignores {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_STARTING},
* since those windows don't belong to apps.
+ *
* @see WindowState#isNonToastOrStarting()
*/
boolean isAnyNonToastWindowVisibleForUid(int callingUid) {
@@ -791,7 +794,7 @@
"Looks like we have reclaimed some memory, clearing surface for retry.");
if (surfaceController != null) {
ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
- "SURFACE RECOVER DESTROY: %s", winAnimator.mWin);
+ "SURFACE RECOVER DESTROY: %s", winAnimator.mWin);
winAnimator.destroySurface();
if (winAnimator.mWin.mActivityRecord != null) {
winAnimator.mWin.mActivityRecord.removeStartingWindow();
@@ -822,8 +825,10 @@
// "Something has changed! Let's make it correct now."
// TODO: Super long method that should be broken down...
void performSurfacePlacementNoTrace() {
- if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
- + Debug.getCallers(3));
+ if (DEBUG_WINDOW_TRACE) {
+ Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
+ + Debug.getCallers(3));
+ }
int i;
@@ -851,8 +856,10 @@
final DisplayContent defaultDisplay = mWmService.getDefaultDisplayContentLocked();
final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
+ if (SHOW_LIGHT_TRANSACTIONS) {
+ Slog.i(TAG,
+ ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
+ }
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applySurfaceChanges");
mWmService.openSurfaceTransaction();
try {
@@ -862,8 +869,10 @@
} finally {
mWmService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
+ if (SHOW_LIGHT_TRANSACTIONS) {
+ Slog.i(TAG,
+ "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
+ }
}
mWmService.mAnimator.executeAfterPrepareSurfacesRunnables();
@@ -896,8 +905,10 @@
if (isLayoutNeeded()) {
defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
- if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("mLayoutNeeded",
- defaultDisplay.pendingLayoutChanges);
+ if (DEBUG_LAYOUT_REPEATS) {
+ surfacePlacer.debugLayoutRepeats("mLayoutNeeded",
+ defaultDisplay.pendingLayoutChanges);
+ }
}
handleResizingWindows();
@@ -1105,11 +1116,11 @@
}
/**
- * @param w WindowState this method is applied to.
+ * @param w WindowState this method is applied to.
* @param obscured True if there is a window on top of this obscuring the display.
- * @param syswin System window?
+ * @param syswin System window?
* @return True when the display contains content to show the user. When false, the display
- * manager may choose to mirror or blank the display.
+ * manager may choose to mirror or blank the display.
*/
boolean handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin) {
final WindowManager.LayoutParams attrs = w.mAttrs;
@@ -1243,7 +1254,8 @@
}
void dumpTopFocusedDisplayId(PrintWriter pw) {
- pw.print(" mTopFocusedDisplayId="); pw.println(mTopFocusedDisplayId);
+ pw.print(" mTopFocusedDisplayId=");
+ pw.println(mTopFocusedDisplayId);
}
void dumpLayoutNeededDisplayIds(PrintWriter pw) {
@@ -1359,7 +1371,8 @@
}
}
- @Nullable Context getDisplayUiContext(int displayId) {
+ @Nullable
+ Context getDisplayUiContext(int displayId) {
return getDisplayContent(displayId) != null
? getDisplayContent(displayId).getDisplayUiContext() : null;
}
@@ -1437,7 +1450,8 @@
* corresponding record in display manager.
*/
// TODO: Look into consolidating with getDisplayContent()
- @Nullable DisplayContent getDisplayContentOrCreate(int displayId) {
+ @Nullable
+ DisplayContent getDisplayContentOrCreate(int displayId) {
DisplayContent displayContent = getDisplayContent(displayId);
if (displayContent != null) {
return displayContent;
@@ -1494,8 +1508,8 @@
final DisplayContent display = getDisplayContent(displayId);
return display.reduceOnAllTaskDisplayAreas((taskDisplayArea, result) ->
- result | startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
- allowInstrumenting, fromHomeKey),
+ result | startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
+ allowInstrumenting, fromHomeKey),
false /* initValue */);
}
@@ -1504,11 +1518,11 @@
* displayId - default display area always uses primary home component.
* For secondary display areas, the home activity must have category SECONDARY_HOME and then
* resolves according to the priorities listed below.
- * - If default home is not set, always use the secondary home defined in the config.
- * - Use currently selected primary home activity.
- * - Use the activity in the same package as currently selected primary home activity.
- * If there are multiple activities matched, use first one.
- * - Use the secondary home defined in the config.
+ * - If default home is not set, always use the secondary home defined in the config.
+ * - Use currently selected primary home activity.
+ * - Use the activity in the same package as currently selected primary home activity.
+ * If there are multiple activities matched, use first one.
+ * - Use the secondary home defined in the config.
*/
boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
boolean allowInstrumenting, boolean fromHomeKey) {
@@ -1556,6 +1570,7 @@
/**
* This resolves the home activity info.
+ *
* @return the home activity info if any.
*/
@VisibleForTesting
@@ -1629,7 +1644,8 @@
}
if (aInfo != null) {
- if (!canStartHomeOnDisplayArea(aInfo, taskDisplayArea, false /* allowInstrumenting */)) {
+ if (!canStartHomeOnDisplayArea(aInfo, taskDisplayArea,
+ false /* allowInstrumenting */)) {
aInfo = null;
}
}
@@ -1687,6 +1703,7 @@
/**
* Check if the display area is valid for secondary home activity.
+ *
* @param taskDisplayArea The target display area.
* @return {@code true} if allow to launch, {@code false} otherwise.
*/
@@ -1727,8 +1744,10 @@
/**
* Check if home activity start should be allowed on a display.
- * @param homeInfo {@code ActivityInfo} of the home activity that is going to be launched.
- * @param taskDisplayArea The target display area.
+ *
+ * @param homeInfo {@code ActivityInfo} of the home activity that is going to be
+ * launched.
+ * @param taskDisplayArea The target display area.
* @param allowInstrumenting Whether launching home should be allowed if being instrumented.
* @return {@code true} if allow to launch, {@code false} otherwise.
*/
@@ -1773,13 +1792,14 @@
/**
* Ensure all activities visibility, update orientation and configuration.
*
- * @param starting The currently starting activity or {@code null} if there is none.
- * @param displayId The id of the display where operation is executed.
+ * @param starting The currently starting activity or {@code null} if there is
+ * none.
+ * @param displayId The id of the display where operation is executed.
* @param markFrozenIfConfigChanged Whether to set {@link ActivityRecord#frozenBeforeDestroy} to
* {@code true} if config changed.
- * @param deferResume Whether to defer resume while updating config.
+ * @param deferResume Whether to defer resume while updating config.
* @return 'true' if starting activity was kept or wasn't provided, 'false' if it was relaunched
- * because of configuration update.
+ * because of configuration update.
*/
boolean ensureVisibilityAndConfig(ActivityRecord starting, int displayId,
boolean markFrozenIfConfigChanged, boolean deferResume) {
@@ -2066,9 +2086,10 @@
/**
* Move stack with all its existing content to specified task display area.
- * @param stackId Id of stack to move.
+ *
+ * @param stackId Id of stack to move.
* @param taskDisplayArea The task display area to move stack to.
- * @param onTop Indicates whether container should be place on top or on bottom.
+ * @param onTop Indicates whether container should be place on top or on bottom.
*/
void moveStackToTaskDisplayArea(int stackId, TaskDisplayArea taskDisplayArea, boolean onTop) {
final Task stack = getStack(stackId);
@@ -2098,9 +2119,10 @@
/**
* Move stack with all its existing content to specified display.
- * @param stackId Id of stack to move.
+ *
+ * @param stackId Id of stack to move.
* @param displayId Id of display to move stack to.
- * @param onTop Indicates whether container should be place on top or on bottom.
+ * @param onTop Indicates whether container should be place on top or on bottom.
*/
void moveStackToDisplay(int stackId, int displayId, boolean onTop) {
final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
@@ -2192,7 +2214,7 @@
final ActivityRecord oldTopActivity = task.getTopMostActivity();
if (oldTopActivity != null && oldTopActivity.isState(STOPPED)
&& task.getDisplayContent().mAppTransition.getAppTransition()
- == TRANSIT_TASK_TO_BACK) {
+ == TRANSIT_TASK_TO_BACK) {
task.getDisplayContent().mClosingApps.add(oldTopActivity);
oldTopActivity.mRequestForceTransition = true;
}
@@ -2227,6 +2249,7 @@
/**
* Notifies when an activity enters or leaves PIP mode.
+ *
* @param r indicates the activity currently in PIP, can be null to indicate no activity is
* currently in PIP mode.
*/
@@ -2249,7 +2272,7 @@
@Nullable
ActivityRecord findTask(ActivityRecord r, TaskDisplayArea preferredTaskDisplayArea) {
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
+ ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of %s", r);
mTmpFindTaskResult.clear();
// Looking up task on preferred display area first
@@ -2277,13 +2300,16 @@
return task;
}
- if (DEBUG_TASKS && mTmpFindTaskResult.mRecord == null) Slog.d(TAG_TASKS, "No task found");
+ if (WM_DEBUG_TASKS.isEnabled() && mTmpFindTaskResult.mRecord == null) {
+ ProtoLog.d(WM_DEBUG_TASKS, "No task found");
+ }
return mTmpFindTaskResult.mRecord;
}
/**
* Finish the topmost activities in all stacks that belong to the crashed app.
- * @param app The app that crashed.
+ *
+ * @param app The app that crashed.
* @param reason Reason to perform this action.
* @return The task id that was finished in this stack, or INVALID_TASK_ID if none was finished.
*/
@@ -2751,9 +2777,11 @@
private void destroyActivity(ActivityRecord r) {
if (r.finishing || !r.isDestroyable()) return;
- if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Destroying " + r + " in state " + r.getState()
- + " resumed=" + r.getStack().mResumedActivity + " pausing="
- + r.getStack().mPausingActivity + " for reason " + mDestroyAllActivitiesReason);
+ if (DEBUG_SWITCH) {
+ Slog.v(TAG_SWITCH, "Destroying " + r + " in state " + r.getState()
+ + " resumed=" + r.getStack().mResumedActivity + " pausing="
+ + r.getStack().mPausingActivity + " for reason " + mDestroyAllActivitiesReason);
+ }
r.destroyImmediately(mDestroyAllActivitiesReason);
}
@@ -2814,7 +2842,7 @@
private static boolean matchesActivity(ActivityRecord r, int userId,
boolean compareIntentFilters, Intent intent, ComponentName cls) {
- if (!r.canBeTopRunning() || r.mUserId != userId) return false;
+ if (!r.canBeTopRunning() || r.mUserId != userId) return false;
if (compareIntentFilters) {
if (r.intent.filterEquals(intent)) {
@@ -2849,10 +2877,10 @@
/**
* Returns the right stack to use for launching factoring in all the input parameters.
*
- * @param r The activity we are trying to launch. Can be null.
- * @param options The activity options used to the launch. Can be null.
- * @param candidateTask The possible task the activity might be launched in. Can be null.
- * @param launchParams The resolved launch params to use.
+ * @param r The activity we are trying to launch. Can be null.
+ * @param options The activity options used to the launch. Can be null.
+ * @param candidateTask The possible task the activity might be launched in. Can be null.
+ * @param launchParams The resolved launch params to use.
* @param realCallingPid The pid from {@link ActivityStarter#setRealCallingPid}
* @param realCallingUid The uid from {@link ActivityStarter#setRealCallingUid}
* @return The stack to use for the launch or INVALID_STACK_ID.
@@ -2986,9 +3014,10 @@
/**
* Get a topmost stack on the display area, that is a valid launch stack for specified activity.
* If there is no such stack, new dynamic stack can be created.
+ *
* @param taskDisplayArea Target display area.
- * @param r Activity that should be launched there.
- * @param candidateTask The possible task the activity might be put in.
+ * @param r Activity that should be launched there.
+ * @param candidateTask The possible task the activity might be put in.
* @return Existing stack if there is a valid one, new dynamic stack if it is valid or null.
*/
@VisibleForTesting
@@ -3054,10 +3083,14 @@
// TODO: Can probably be consolidated into getLaunchStack()...
private boolean isValidLaunchStack(Task stack, ActivityRecord r, int windowingMode) {
switch (stack.getActivityType()) {
- case ACTIVITY_TYPE_HOME: return r.isActivityTypeHome();
- case ACTIVITY_TYPE_RECENTS: return r.isActivityTypeRecents();
- case ACTIVITY_TYPE_ASSISTANT: return r.isActivityTypeAssistant();
- case ACTIVITY_TYPE_DREAM: return r.isActivityTypeDream();
+ case ACTIVITY_TYPE_HOME:
+ return r.isActivityTypeHome();
+ case ACTIVITY_TYPE_RECENTS:
+ return r.isActivityTypeRecents();
+ case ACTIVITY_TYPE_ASSISTANT:
+ return r.isActivityTypeAssistant();
+ case ACTIVITY_TYPE_DREAM:
+ return r.isActivityTypeDream();
}
if (stack.mCreatedByOrganizer) {
// Don't launch directly into task created by organizer...but why can't we?
@@ -3097,9 +3130,9 @@
* from the target stack. If no valid candidates will be found, it will then go through all
* displays and stacks in last-focused order.
*
- * @param currentFocus The stack that previously had focus.
+ * @param currentFocus The stack that previously had focus.
* @param ignoreCurrent If we should ignore {@param currentFocus} when searching for next
- * candidate.
+ * candidate.
* @return Next focusable {@link Task}, {@code null} if not found.
*/
Task getNextFocusableStack(@NonNull Task currentFocus,
@@ -3162,6 +3195,7 @@
FinishDisabledPackageActivitiesHelper mFinishDisabledPackageActivitiesHelper =
new FinishDisabledPackageActivitiesHelper();
+
class FinishDisabledPackageActivitiesHelper {
private String mPackageName;
private Set<String> mFilterByClasses;
@@ -3318,10 +3352,8 @@
}
final ActivityRecord resumedActivity = stack.getResumedActivity();
if (resumedActivity == null || !resumedActivity.idle) {
- if (DEBUG_STATES) {
- Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
- + stack.getRootTaskId() + " " + resumedActivity + " not idle");
- }
+ ProtoLog.d(WM_DEBUG_STATES, "allResumedActivitiesIdle: stack=%d %s "
+ + "not idle", stack.getRootTaskId(), resumedActivity);
return false;
}
}
@@ -3360,9 +3392,9 @@
final Task stack = taskDisplayArea.getStackAt(sNdx);
final ActivityRecord r = stack.mPausingActivity;
if (r != null && !r.isState(PAUSED, STOPPED, STOPPING, FINISHING)) {
- if (DEBUG_STATES) {
- Slog.d(TAG_STATES, "allPausedActivitiesComplete: r=" + r
- + " state=" + r.getState());
+ ProtoLog.d(WM_DEBUG_STATES, "allPausedActivitiesComplete: "
+ + "r=%s state=%s", r, r.getState());
+ if (WM_DEBUG_STATES.isEnabled()) {
pausing[0] = false;
} else {
return true;
@@ -3441,10 +3473,11 @@
/**
* Returns a {@link Task} for the input id if available. {@code null} otherwise.
- * @param id Id of the task we would like returned.
+ *
+ * @param id Id of the task we would like returned.
* @param matchMode The mode to match the given task id in.
- * @param aOptions The activity options to use for restoration. Can be null.
- * @param onTop If the stack for the task should be the topmost on the display.
+ * @param aOptions The activity options to use for restoration. Can be null.
+ * @param onTop If the stack for the task should be the topmost on the display.
*/
Task anyTaskForId(int id, @RootWindowContainer.AnyTaskForIdMatchTaskMode int matchMode,
@Nullable ActivityOptions aOptions, boolean onTop) {
@@ -3499,8 +3532,10 @@
// Implicitly, this case is MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
if (!mStackSupervisor.restoreRecentTaskLocked(task, aOptions, onTop)) {
- if (DEBUG_RECENTS) Slog.w(TAG_RECENTS,
- "Couldn't restore task id=" + id + " found in recents");
+ if (DEBUG_RECENTS) {
+ Slog.w(TAG_RECENTS,
+ "Couldn't restore task id=" + id + " found in recents");
+ }
return null;
}
if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, "Restored task id=" + id + " from in recents");
@@ -3611,14 +3646,19 @@
/**
* Dump all connected displays' configurations.
+ *
* @param prefix Prefix to apply to each line of the dump.
*/
void dumpDisplayConfigs(PrintWriter pw, String prefix) {
- pw.print(prefix); pw.println("Display override configurations:");
+ pw.print(prefix);
+ pw.println("Display override configurations:");
final int displayCount = getChildCount();
for (int i = 0; i < displayCount; i++) {
final DisplayContent displayContent = getChildAt(i);
- pw.print(prefix); pw.print(" "); pw.print(displayContent.mDisplayId); pw.print(": ");
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print(displayContent.mDisplayId);
+ pw.print(": ");
pw.println(displayContent.getRequestedOverrideConfiguration());
}
}
@@ -3632,7 +3672,8 @@
if (printed[0]) {
pw.println();
}
- pw.print("Display #"); pw.print(displayContent.mDisplayId);
+ pw.print("Display #");
+ pw.print(displayContent.mDisplayId);
pw.println(" (activities from top to bottom):");
displayContent.forAllTaskDisplayAreas(taskDisplayArea -> {
for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 22776e0..f984576 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -80,6 +80,8 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
@@ -87,13 +89,9 @@
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList;
import static com.android.server.wm.ActivityStackSupervisor.printThisActivity;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
@@ -161,6 +159,7 @@
import android.app.ActivityTaskManager;
import android.app.AppGlobals;
import android.app.IActivityController;
+import android.app.PictureInPictureParams;
import android.app.RemoteAction;
import android.app.ResultInfo;
import android.app.TaskInfo;
@@ -1279,7 +1278,7 @@
_intent.setSourceBounds(null);
}
}
- if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
+ ProtoLog.v(WM_DEBUG_TASKS, "Setting Intent of %s to %s", this, _intent);
intent = _intent;
realActivity = _intent != null ? _intent.getComponent() : null;
origActivity = null;
@@ -1290,8 +1289,7 @@
Intent targetIntent = new Intent(_intent);
targetIntent.setSelector(null);
targetIntent.setSourceBounds(null);
- if (DEBUG_TASKS) Slog.v(TAG_TASKS,
- "Setting Intent of " + this + " to target " + targetIntent);
+ ProtoLog.v(WM_DEBUG_TASKS, "Setting Intent of %s to target %s", this, targetIntent);
intent = targetIntent;
realActivity = targetComponent;
origActivity = _intent.getComponent();
@@ -4060,17 +4058,20 @@
info.topActivityType = top.getActivityType();
info.isResizeable = isResizeable();
- ActivityRecord rootActivity = top.getRootActivity();
- if (rootActivity == null || rootActivity.pictureInPictureArgs.empty()) {
- info.pictureInPictureParams = null;
- } else {
- info.pictureInPictureParams = rootActivity.pictureInPictureArgs;
- }
+ info.pictureInPictureParams = getPictureInPictureParams();
info.topActivityInfo = mReuseActivitiesReport.top != null
? mReuseActivitiesReport.top.info
: null;
}
+ @Nullable PictureInPictureParams getPictureInPictureParams() {
+ final Task top = getTopMostTask();
+ if (top == null) return null;
+ final ActivityRecord rootActivity = top.getRootActivity();
+ return (rootActivity == null || rootActivity.pictureInPictureArgs.empty())
+ ? null : rootActivity.pictureInPictureArgs;
+ }
+
/**
* Returns a {@link TaskInfo} with information from this task.
*/
@@ -5313,8 +5314,8 @@
}
void minimalResumeActivityLocked(ActivityRecord r) {
- if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + r + " (starting new instance)"
- + " callers=" + Debug.getCallers(5));
+ ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (starting new instance) "
+ + "callers=%s", r, Debug.getCallers(5));
r.setState(RESUMED, "minimalResumeActivityLocked");
r.completeResumeLocked();
}
@@ -5358,7 +5359,7 @@
if (mResumedActivity != null) {
// Still have something resumed; can't sleep until it is paused.
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep needs to pause " + mResumedActivity);
+ ProtoLog.v(WM_DEBUG_STATES, "Sleep needs to pause %s", mResumedActivity);
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"Sleep => pause with userLeaving=false");
@@ -5367,15 +5368,15 @@
shouldSleep = false ;
} else if (mPausingActivity != null) {
// Still waiting for something to pause; can't sleep yet.
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still waiting to pause " + mPausingActivity);
+ ProtoLog.v(WM_DEBUG_STATES, "Sleep still waiting to pause %s", mPausingActivity);
shouldSleep = false;
}
if (!shuttingDown) {
if (containsActivityFromStack(mStackSupervisor.mStoppingActivities)) {
// Still need to tell some activities to stop; can't sleep yet.
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to stop "
- + mStackSupervisor.mStoppingActivities.size() + " activities");
+ ProtoLog.v(WM_DEBUG_STATES, "Sleep still need to stop %d activities",
+ mStackSupervisor.mStoppingActivities.size());
mStackSupervisor.scheduleIdle();
shouldSleep = false;
@@ -5454,8 +5455,7 @@
return false;
}
- if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
- else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
+ ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSING: %s", prev);
mPausingActivity = prev;
mLastPausedActivity = prev;
mLastNoHistoryActivity = prev.isNoHistory() ? prev : null;
@@ -5486,13 +5486,13 @@
boolean didAutoPip = false;
if (prev.attachedToProcess()) {
if (shouldAutoPip) {
- if (DEBUG_PAUSE) {
- Slog.d(TAG_PAUSE, "Auto-PIP allowed, entering PIP mode directly: " + prev);
- }
+ ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, entering PIP mode "
+ + "directly: %s", prev);
+
didAutoPip = mAtmService.enterPictureInPictureMode(prev, prev.pictureInPictureArgs);
mPausingActivity = null;
} else {
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
+ ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev);
try {
EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
prev.shortComponentName, "userLeaving=" + userLeaving, reason);
@@ -5532,8 +5532,8 @@
// key dispatch; the same activity will pick it up again on wakeup.
if (!uiSleeping) {
prev.pauseKeyDispatchingLocked();
- } else if (DEBUG_PAUSE) {
- Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
+ } else {
+ ProtoLog.v(WM_DEBUG_STATES, "Key dispatch not paused for screen off");
}
if (pauseImmediately) {
@@ -5550,7 +5550,7 @@
} else {
// This activity failed to schedule the
// pause, so just treat it as being paused now.
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
+ ProtoLog.v(WM_DEBUG_STATES, "Activity not running, resuming next.");
if (resuming == null) {
mRootWindowContainer.resumeFocusedStacksTopActivities();
}
@@ -5561,22 +5561,22 @@
@VisibleForTesting
void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
ActivityRecord prev = mPausingActivity;
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
+ ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev);
if (prev != null) {
prev.setWillCloseOrEnterPip(false);
final boolean wasStopping = prev.isState(STOPPING);
prev.setState(PAUSED, "completePausedLocked");
if (prev.finishing) {
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
+ ProtoLog.v(WM_DEBUG_STATES, "Executing finish of activity: %s", prev);
prev = prev.completeFinishing("completePausedLocked");
} else if (prev.hasProcess()) {
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
- + " wasStopping=" + wasStopping
- + " visibleRequested=" + prev.mVisibleRequested);
+ ProtoLog.v(WM_DEBUG_STATES, "Enqueue pending stop if needed: %s "
+ + "wasStopping=%b visibleRequested=%b", prev, wasStopping,
+ prev.mVisibleRequested);
if (prev.deferRelaunchUntilPaused) {
// Complete the deferred relaunch that was waiting for pause to complete.
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
+ ProtoLog.v(WM_DEBUG_STATES, "Re-launching after pause: %s", prev);
prev.relaunchActivityLocked(prev.preserveWindowOnDeferredRelaunch);
} else if (wasStopping) {
// We are also stopping, the stop request must have gone soon after the pause.
@@ -5592,7 +5592,7 @@
"completePauseLocked");
}
} else {
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev);
+ ProtoLog.v(WM_DEBUG_STATES, "App died during pause, not stopping: %s", prev);
prev = null;
}
// It is possible the activity was freezing the screen before it was paused.
@@ -5888,8 +5888,8 @@
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
- if (DEBUG_STATES) Slog.d(TAG_STATES,
- "resumeTopActivityLocked: Top activity resumed " + next);
+ ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Top activity "
+ + "resumed %s", next);
return false;
}
@@ -5900,9 +5900,9 @@
// If we are currently pausing an activity, then don't do anything until that is done.
final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();
if (!allPausedComplete) {
- if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) {
- Slog.v(TAG_PAUSE, "resumeTopActivityLocked: Skip resume: some activity pausing.");
- }
+ ProtoLog.v(WM_DEBUG_STATES,
+ "resumeTopActivityLocked: Skip resume: some activity pausing.");
+
return false;
}
@@ -5914,8 +5914,8 @@
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
- if (DEBUG_STATES) Slog.d(TAG_STATES,
- "resumeTopActivityLocked: Going to sleep and all paused");
+ ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Going to sleep and"
+ + " all paused");
return false;
}
@@ -5937,7 +5937,7 @@
// If we are currently pausing an activity, then don't do anything until that is done.
if (!mRootWindowContainer.allPausedActivitiesComplete()) {
- if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
+ ProtoLog.v(WM_DEBUG_STATES,
"resumeTopActivityLocked: Skip resume: some activity pausing.");
return false;
@@ -5963,14 +5963,13 @@
boolean pausing = taskDisplayArea.pauseBackStacks(userLeaving, next);
if (mResumedActivity != null) {
- if (DEBUG_STATES) Slog.d(TAG_STATES,
- "resumeTopActivityLocked: Pausing " + mResumedActivity);
+ ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Pausing %s", mResumedActivity);
pausing |= startPausingLocked(userLeaving, false /* uiSleeping */, next,
- "resumeTopActivityInnerLocked");
+ "resumeTopActivityInnerLocked");
}
if (pausing) {
- if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
- "resumeTopActivityLocked: Skip resume: need to start pausing");
+ ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivityLocked: Skip resume: need to"
+ + " start pausing");
// At this point we want to put the upcoming activity's process
// at the top of the LRU list, since we know we will be needing it
// very soon and it would be a waste to let it get killed if it
@@ -5999,8 +5998,8 @@
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
- if (DEBUG_STATES) Slog.d(TAG_STATES,
- "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
+ ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Top activity resumed "
+ + "(dontWaitForPause) %s", next);
return true;
}
@@ -6010,8 +6009,8 @@
if (shouldSleepActivities() && mLastNoHistoryActivity != null
&& !mLastNoHistoryActivity.finishing
&& mLastNoHistoryActivity != next) {
- if (DEBUG_STATES) Slog.d(TAG_STATES,
- "no-history finish of " + mLastNoHistoryActivity + " on new resume");
+ ProtoLog.d(WM_DEBUG_STATES, "no-history finish of %s on new resume",
+ mLastNoHistoryActivity);
mLastNoHistoryActivity.finishIfPossible("resume-no-history", false /* oomAdj */);
mLastNoHistoryActivity = null;
}
@@ -6130,8 +6129,7 @@
mAtmService.updateCpuStats();
- if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
- + " (in existing)");
+ ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (in existing)", next);
next.setState(RESUMED, "resumeTopActivityInnerLocked");
@@ -6161,9 +6159,8 @@
// is still at the top and schedule another run if something
// weird happened.
ActivityRecord nextNext = topRunningActivity();
- if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES,
- "Activity config changed during resume: " + next
- + ", new next: " + nextNext);
+ ProtoLog.i(WM_DEBUG_STATES, "Activity config changed during resume: "
+ + "%s, new next: %s", next, nextNext);
if (nextNext != next) {
// Do over!
mStackSupervisor.scheduleResumeTopActivities();
@@ -6210,12 +6207,11 @@
dc.isNextTransitionForward()));
mAtmService.getLifecycleManager().scheduleTransaction(transaction);
- if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
- + next);
+ ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Resumed %s", next);
} catch (Exception e) {
// Whoops, need to restart this activity!
- if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
- + lastState + ": " + next);
+ ProtoLog.v(WM_DEBUG_STATES, "Resume failed; resetting state to %s: "
+ + "%s", lastState, next);
next.setState(lastState, "resumeTopActivityInnerLocked");
// lastResumedActivity being non-null implies there is a lastStack present.
@@ -6257,7 +6253,7 @@
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
}
- if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
+ ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Restarting %s", next);
mStackSupervisor.startSpecificActivity(next, true, true);
}
@@ -6289,8 +6285,8 @@
// If the current stack is a home stack, or if focus didn't switch to a different stack -
// just start up the Launcher...
ActivityOptions.abort(options);
- if (DEBUG_STATES) Slog.d(TAG_STATES,
- "resumeNextFocusableActivityWhenStackIsEmpty: " + reason + ", go home");
+ ProtoLog.d(WM_DEBUG_STATES, "resumeNextFocusableActivityWhenStackIsEmpty: %s, "
+ + "go home", reason);
return mRootWindowContainer.resumeHomeActivity(prev, reason, getDisplayArea());
}
@@ -7018,8 +7014,8 @@
boolean handleAppDied(WindowProcessController app) {
boolean isPausingDied = false;
if (mPausingActivity != null && mPausingActivity.app == app) {
- if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE,
- "App died while pausing: " + mPausingActivity);
+ ProtoLog.v(WM_DEBUG_STATES, "App died while pausing: %s",
+ mPausingActivity);
mPausingActivity = null;
isPausingDied = true;
}
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 2c8770f..ce99102 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -33,12 +33,10 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK;
import static com.android.server.wm.DisplayContent.alwaysCreateStack;
-import static com.android.server.wm.RootWindowContainer.TAG_STATES;
import static com.android.server.wm.Task.ActivityState.RESUMED;
import static com.android.server.wm.Task.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
@@ -212,11 +210,13 @@
return mChildren.indexOf(task);
}
- @Nullable Task getRootHomeTask() {
+ @Nullable
+ Task getRootHomeTask() {
return mRootHomeTask;
}
- @Nullable Task getRootRecentsTask() {
+ @Nullable
+ Task getRootRecentsTask() {
return mRootRecentsTask;
}
@@ -526,19 +526,20 @@
* When stack is added or repositioned, find a proper position for it.
*
* The order is defined as:
- * - Dream is on top of everything
- * - PiP is directly below the Dream
- * - always-on-top stacks are directly below PiP; new always-on-top stacks are added above
- * existing ones
- * - other non-always-on-top stacks come directly below always-on-top stacks; new
- * non-always-on-top stacks are added directly below always-on-top stacks and above existing
- * non-always-on-top stacks
- * - if {@link #mAssistantOnTopOfDream} is enabled, then Assistant is on top of everything
- * (including the Dream); otherwise, it is a normal non-always-on-top stack
+ * - Dream is on top of everything
+ * - PiP is directly below the Dream
+ * - always-on-top stacks are directly below PiP; new always-on-top stacks are added above
+ * existing ones
+ * - other non-always-on-top stacks come directly below always-on-top stacks; new
+ * non-always-on-top stacks are added directly below always-on-top stacks and above existing
+ * non-always-on-top stacks
+ * - if {@link #mAssistantOnTopOfDream} is enabled, then Assistant is on top of everything
+ * (including the Dream); otherwise, it is a normal non-always-on-top stack
*
* @param requestedPosition Position requested by caller.
- * @param stack Stack to be added or positioned.
- * @param adding Flag indicates whether we're adding a new stack or positioning an existing.
+ * @param stack Stack to be added or positioned.
+ * @param adding Flag indicates whether we're adding a new stack or positioning an
+ * existing.
* @return The proper position for the stack.
*/
private int findPositionForStack(int requestedPosition, Task stack, boolean adding) {
@@ -655,6 +656,7 @@
/**
* Sets whether the task display area should ignore fixed-orientation request from apps.
+ *
* @return Whether the display orientation changed
*/
boolean setIgnoreOrientationRequest(boolean ignoreOrientationRequest) {
@@ -774,7 +776,7 @@
* Adjusts the layer of the stack which belongs to the same group.
* Note that there are three stack groups: home stacks, always on top stacks, and normal stacks.
*
- * @param startLayer The beginning layer of this group of stacks.
+ * @param startLayer The beginning layer of this group of stacks.
* @param normalStacks Set {@code true} if this group is neither home nor always on top.
* @return The adjusted layer value.
*/
@@ -921,6 +923,7 @@
/**
* Returns an existing stack compatible with the windowing mode and activity type or creates one
* if a compatible stack doesn't exist.
+ *
* @see #getOrCreateStack(int, int, boolean, Intent, Task)
*/
Task getOrCreateStack(int windowingMode, int activityType, boolean onTop) {
@@ -933,6 +936,7 @@
* existing compatible root task or creates a new one.
* For one level task, the candidate task would be reused to also be the root task or create
* a new root task if no candidate task.
+ *
* @see #getStack(int, int)
* @see #createStack(int, int, boolean)
*/
@@ -978,6 +982,7 @@
/**
* Returns an existing stack compatible with the input params or creates one
* if a compatible stack doesn't exist.
+ *
* @see #getOrCreateStack(int, int, boolean)
*/
Task getOrCreateStack(@Nullable ActivityRecord r,
@@ -1006,17 +1011,21 @@
/**
* Creates a stack matching the input windowing mode and activity type on this display.
- * @param windowingMode The windowing mode the stack should be created in. If
- * {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will
- * inherit its parent's windowing mode.
- * @param activityType The activityType the stack should be created in. If
- * {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will
- * be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
- * @param onTop If true the stack will be created at the top of the display, else at the bottom.
- * @param info The started activity info.
- * @param intent The intent that started this task.
+ *
+ * @param windowingMode The windowing mode the stack should be created in. If
+ * {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack
+ * will
+ * inherit its parent's windowing mode.
+ * @param activityType The activityType the stack should be created in. If
+ * {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack
+ * will
+ * be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
+ * @param onTop If true the stack will be created at the top of the display, else
+ * at the bottom.
+ * @param info The started activity info.
+ * @param intent The intent that started this task.
* @param createdByOrganizer @{code true} if this is created by task organizer, @{code false}
- * otherwise.
+ * otherwise.
* @return The newly created stack.
*/
Task createStack(int windowingMode, int activityType, boolean onTop, ActivityInfo info,
@@ -1223,8 +1232,9 @@
* paused in stacks that are no longer visible or in pinned windowing mode. This does not
* pause activities in visible stacks, so if an activity is launched within the same stack/task,
* then we should explicitly pause that stack's top activity.
+ *
* @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
- * @param resuming The resuming activity.
+ * @param resuming The resuming activity.
* @return {@code true} if any activity was paused as a result of this call.
*/
boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming) {
@@ -1235,10 +1245,8 @@
if (resumedActivity != null
&& (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
|| !stack.isTopActivityFocusable())) {
- if (DEBUG_STATES) {
- Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack
- + " mResumedActivity=" + resumedActivity);
- }
+ ProtoLog.d(WM_DEBUG_STATES, "pauseBackStacks: stack=%s "
+ + "mResumedActivity=%s", stack, resumedActivity);
someActivityPaused |= stack.startPausingLocked(userLeaving, false /* uiSleeping*/,
resuming, "pauseBackStacks");
}
@@ -1255,9 +1263,8 @@
for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
final Task stack = getStackAt(stackNdx);
if (!r.hasCompatibleActivityType(stack) && stack.isLeafTask()) {
- if (DEBUG_TASKS) {
- Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + stack);
- }
+ ProtoLog.d(WM_DEBUG_TASKS, "Skipping stack: (mismatch activity/stack) "
+ + "%s", stack);
continue;
}
@@ -1298,10 +1305,9 @@
final int windowingMode = windowingModes[j];
for (int i = getStackCount() - 1; i >= 0; --i) {
final Task stack = getStackAt(i);
- if (!stack.isActivityTypeStandardOrUndefined()) {
- continue;
- }
- if (stack.getWindowingMode() != windowingMode) {
+ if (stack.mCreatedByOrganizer
+ || !stack.isActivityTypeStandardOrUndefined()
+ || stack.getWindowingMode() != windowingMode) {
continue;
}
stacks.add(stack);
@@ -1400,12 +1406,13 @@
/**
* Returns true if the {@param windowingMode} is supported based on other parameters passed in.
- * @param windowingMode The windowing mode we are checking support for.
+ *
+ * @param windowingMode The windowing mode we are checking support for.
* @param supportsMultiWindow If we should consider support for multi-window mode in general.
* @param supportsSplitScreen If we should consider support for split-screen multi-window.
- * @param supportsFreeform If we should consider support for freeform multi-window.
- * @param supportsPip If we should consider support for picture-in-picture mutli-window.
- * @param activityType The activity type under consideration.
+ * @param supportsFreeform If we should consider support for freeform multi-window.
+ * @param supportsPip If we should consider support for picture-in-picture mutli-window.
+ * @param activityType The activity type under consideration.
* @return true if the windowing mode is supported.
*/
private boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
@@ -1444,9 +1451,9 @@
* Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this
* display with the provided parameters.
*
- * @param r The ActivityRecord in question.
- * @param options Options to start with.
- * @param task The task within-which the activity would start.
+ * @param r The ActivityRecord in question.
+ * @param options Options to start with.
+ * @param task The task within-which the activity would start.
* @param activityType The type of activity to start.
* @return The resolved (not UNDEFINED) windowing-mode that the activity would be in.
*/
@@ -1481,9 +1488,9 @@
* on this display.
*
* @param windowingMode The windowing-mode to validate.
- * @param r The {@link ActivityRecord} to check against.
- * @param task The {@link Task} to check against.
- * @param activityType An activity type.
+ * @param r The {@link ActivityRecord} to check against.
+ * @param task The {@link Task} to check against.
+ * @param activityType An activity type.
* @return {@code true} if windowingMode is valid, {@code false} otherwise.
*/
boolean isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
@@ -1508,7 +1515,7 @@
return windowingMode != WINDOWING_MODE_UNDEFINED
&& isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
- supportsFreeform, supportsPip, activityType);
+ supportsFreeform, supportsPip, activityType);
}
/**
@@ -1516,9 +1523,9 @@
* on this display.
*
* @param windowingMode The windowing-mode to validate.
- * @param r The {@link ActivityRecord} to check against.
- * @param task The {@link Task} to check against.
- * @param activityType An activity type.
+ * @param r The {@link ActivityRecord} to check against.
+ * @param task The {@link Task} to check against.
+ * @param activityType An activity type.
* @return The provided windowingMode or the closest valid mode which is appropriate.
*/
int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
@@ -1606,6 +1613,7 @@
/**
* Returns the existing home stack or creates and returns a new one if it should exist for the
* display.
+ *
* @param onTop Only be used when there is no existing home stack. If true the home stack will
* be created at the top of the display, else at the bottom.
*/
@@ -1743,7 +1751,7 @@
/**
* @return the stack currently above the {@param stack}. Can be null if the {@param stack} is
- * already top-most.
+ * already top-most.
*/
static Task getStackAbove(Task stack) {
final WindowContainer wc = stack.getParent();
@@ -1789,6 +1797,7 @@
/**
* Notifies of a stack order change
+ *
* @param stack The stack which triggered the order change
*/
void onStackOrderChanged(Task stack) {
@@ -1832,6 +1841,7 @@
/**
* Removes the stacks in the node applying the content removal node from the display.
+ *
* @return last reparented stack, or {@code null} if the stacks had to be destroyed.
*/
Task remove() {
diff --git a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
index 38bff9e..416b9df 100644
--- a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
@@ -93,7 +93,7 @@
RemoteAnimationTarget createRemoteAnimationTarget() {
mTarget = new RemoteAnimationTarget(-1, -1, getLeash(), false, null, null,
mWallpaperToken.getPrefixOrderIndex(), new Point(), null, null,
- mWallpaperToken.getWindowConfiguration(), true, null, null);
+ mWallpaperToken.getWindowConfiguration(), true, null, null, null);
return mTarget;
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 5c6266a..ff5c174 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -103,7 +103,8 @@
mAnimationFrameCallback = frameTimeNs -> {
synchronized (mService.mGlobalLock) {
mAnimationFrameCallbackScheduled = false;
- animate(frameTimeNs);
+ final long vsyncId = mChoreographer.getVsyncId();
+ animate(frameTimeNs, vsyncId);
if (mNotifyWhenNoAnimation && !mLastRootAnimating) {
mService.mGlobalLock.notifyAll();
}
@@ -125,7 +126,7 @@
mInitialized = true;
}
- private void animate(long frameTimeNs) {
+ private void animate(long frameTimeNs, long vsyncId) {
if (!mInitialized) {
return;
}
@@ -133,6 +134,8 @@
// Schedule next frame already such that back-pressure happens continuously.
scheduleAnimation();
+ mTransaction.setFrameTimelineVsync(vsyncId);
+
mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
if (DEBUG_WINDOW_TRACE) {
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 2ece30d..38ec924 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -22,6 +22,7 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
+import static android.content.pm.ActivityInfo.reverseOrientation;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
@@ -809,6 +810,13 @@
return parent != null ? parent.getDisplayArea() : null;
}
+ /** Get the first node of type {@link RootDisplayArea} above or at this node. */
+ @Nullable
+ RootDisplayArea getRootDisplayArea() {
+ WindowContainer parent = getParent();
+ return parent != null ? parent.getRootDisplayArea() : null;
+ }
+
boolean isAttached() {
return getDisplayArea() != null;
}
@@ -1154,17 +1162,30 @@
* {@link Configuration#ORIENTATION_UNDEFINED}).
*/
int getRequestedConfigurationOrientation() {
- if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
+ int requestedOrientation = mOrientation;
+ final RootDisplayArea root = getRootDisplayArea();
+ if (root != null && root.isOrientationDifferentFromDisplay()) {
+ // Reverse the requested orientation if the orientation of its root is different from
+ // the display, so that when the display rotates to the reversed orientation, the
+ // requested app will be in the requested orientation.
+ // For example, if the display is 1200x900 (landscape), and the DAG is 600x900
+ // (portrait).
+ // When an app below the DAG is requesting landscape, it should actually request the
+ // display to be portrait, so that the DAG and the app will be in landscape.
+ requestedOrientation = reverseOrientation(mOrientation);
+ }
+
+ if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
// NOSENSOR means the display's "natural" orientation, so return that.
if (mDisplayContent != null) {
return mDisplayContent.getNaturalOrientation();
}
- } else if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
+ } else if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
// LOCKED means the activity's orientation remains unchanged, so return existing value.
return getConfiguration().orientation;
- } else if (isFixedOrientationLandscape(mOrientation)) {
+ } else if (isFixedOrientationLandscape(requestedOrientation)) {
return ORIENTATION_LANDSCAPE;
- } else if (isFixedOrientationPortrait(mOrientation)) {
+ } else if (isFixedOrientationPortrait(requestedOrientation)) {
return ORIENTATION_PORTRAIT;
}
return ORIENTATION_UNDEFINED;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 9f653d6..13d8dc4 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -23,12 +23,10 @@
import static android.graphics.Matrix.MTRANS_X;
import static android.graphics.Matrix.MTRANS_Y;
import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TRANSIT_NONE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_DRAW;
@@ -46,19 +44,16 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_CROP;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
import static com.android.server.wm.WindowManagerService.logWithStack;
import static com.android.server.wm.WindowStateAnimatorProto.DRAW_STATE;
-import static com.android.server.wm.WindowStateAnimatorProto.LAST_CLIP_RECT;
import static com.android.server.wm.WindowStateAnimatorProto.SURFACE;
import static com.android.server.wm.WindowStateAnimatorProto.SYSTEM_DECOR_RECT;
import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
-import android.app.WindowConfiguration;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
@@ -365,7 +360,7 @@
if (mSurfaceController != null && mPendingDestroySurface != null) {
mPostDrawTransaction.reparentChildren(
mSurfaceController.getClientViewRootSurface(),
- mPendingDestroySurface.mSurfaceControl).apply();
+ mPendingDestroySurface.getClientViewRootSurface()).apply();
}
destroySurfaceLocked();
mSurfaceDestroyDeferred = true;
@@ -399,7 +394,7 @@
&& (mWin.mActivityRecord == null || !mWin.mActivityRecord.isRelaunching())) {
mPostDrawTransaction.reparentChildren(
mPendingDestroySurface.getClientViewRootSurface(),
- mSurfaceController.mSurfaceControl).apply();
+ mSurfaceController.getClientViewRootSurface()).apply();
}
destroyDeferredSurfaceLocked();
@@ -993,7 +988,7 @@
if (!mPendingDestroySurface.mChildrenDetached) {
mPostDrawTransaction.reparentChildren(
mPendingDestroySurface.getClientViewRootSurface(),
- mSurfaceController.mSurfaceControl);
+ mSurfaceController.getClientViewRootSurface());
}
}
diff --git a/services/core/xsd/vts/Android.mk b/services/core/xsd/vts/Android.mk
deleted file mode 100644
index 6dc2c43..0000000
--- a/services/core/xsd/vts/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (C) 2019 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := VtsValidateDefaultPermissions
-include test/vts/tools/build/Android.host_config.mk
diff --git a/services/core/xsd/vts/AndroidTest.xml b/services/core/xsd/vts/AndroidTest.xml
deleted file mode 100644
index 4f3b2ef..0000000
--- a/services/core/xsd/vts/AndroidTest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 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.
--->
-<configuration description="Config for VTS VtsValidateDefaultPermissions.">
- <option name="config-descriptor:metadata" key="plan" value="vts-treble" />
- <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
- <option name="abort-on-push-failure" value="false"/>
- <option name="push-group" value="HostDrivenTest.push"/>
- <option name="push" value="DATA/etc/default-permissions.xsd->/data/local/tmp/default-permissions.xsd"/>
- </target_preparer>
- <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
- <option name="test-module-name" value="VtsValidateDefaultPermissions"/>
- <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_defaultPermissions_validate_test/vts_defaultPermissions_validate_test" />
- <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_defaultPermissions_validate_test/vts_defaultPermissions_validate_test" />
- <option name="binary-test-type" value="gtest"/>
- <option name="test-timeout" value="30s"/>
- </test>
-</configuration>
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f348664..282cee0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2129,7 +2129,9 @@
ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle, boolean parent) {
ensureLocked();
if (parent) {
- enforceManagedProfile(userHandle, "call APIs on the parent profile");
+ Preconditions.checkCallAuthorization(isManagedProfile(userHandle), String.format(
+ "You can not call APIs on the parent profile outside a managed profile, "
+ + "userId = %d", userHandle));
}
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
if (admin != null && parent) {
@@ -2280,8 +2282,8 @@
}
}
- ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy, boolean parent)
- throws SecurityException {
+ ActiveAdmin getActiveAdminForCallerLocked(@Nullable ComponentName who, int reqPolicy,
+ boolean parent) throws SecurityException {
return getActiveAdminOrCheckPermissionForCallerLocked(
who, reqPolicy, parent, /* permission= */ null);
}
@@ -2295,14 +2297,13 @@
*/
@Nullable
ActiveAdmin getActiveAdminOrCheckPermissionForCallerLocked(
- ComponentName who,
+ @Nullable ComponentName who,
int reqPolicy,
boolean parent,
@Nullable String permission) throws SecurityException {
ensureLocked();
if (parent) {
- enforceManagedProfile(mInjector.userHandleGetCallingUserId(),
- "call APIs on the parent profile");
+ Preconditions.checkCallingUser(isManagedProfile(getCallerIdentity().getUserId()));
}
ActiveAdmin admin = getActiveAdminOrCheckPermissionForCallerLocked(
who, reqPolicy, permission);
@@ -2894,7 +2895,7 @@
if (!mHasFeature) {
return;
}
- enforceManageUsers();
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
synchronized (getLockObject()) {
final DevicePolicyData policy = getUserData(userHandle.getIdentifier());
@@ -4090,10 +4091,13 @@
if (!mHasFeature) {
return true;
}
- final int userId = mInjector.userHandleGetCallingUserId();
- enforceProfileOrDeviceOwner(admin);
- enforceManagedProfile(userId, "query unified challenge status");
- return !isSeparateProfileChallengeEnabled(userId);
+ Objects.requireNonNull(admin, "ComponentName is null");
+
+ final CallerIdentity caller = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallingUser(isManagedProfile(caller.getUserId()));
+
+ return !isSeparateProfileChallengeEnabled(caller.getUserId());
}
@Override
@@ -4105,7 +4109,9 @@
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle));
- enforceManagedProfile(userHandle, "call APIs refering to the parent profile");
+ Preconditions.checkCallAuthorization(isManagedProfile(userHandle), String.format(
+ "can not call APIs refering to the parent profile outside a managed profile, "
+ + "userId = %d", userHandle));
synchronized (getLockObject()) {
final int targetUser = getProfileParentId(userHandle);
@@ -4127,7 +4133,9 @@
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle));
- enforceNotManagedProfile(userHandle, "check password sufficiency");
+ Preconditions.checkCallAuthorization(!isManagedProfile(userHandle), String.format(
+ "You can not check password sufficiency for a managed profile, userId = %d",
+ userHandle));
enforceUserUnlocked(userHandle);
synchronized (getLockObject()) {
@@ -4683,8 +4691,9 @@
if (!mHasFeature && !hasCallingPermission(permission.LOCK_DEVICE)) {
return;
}
+ final CallerIdentity caller = getCallerIdentity();
- final int callingUserId = mInjector.userHandleGetCallingUserId();
+ final int callingUserId = caller.getUserId();
ComponentName adminComponent = null;
synchronized (getLockObject()) {
// Make sure the caller has any active admin with the right policy or
@@ -4701,16 +4710,13 @@
// For Profile Owners only, callers with only permission not allowed.
if ((flags & DevicePolicyManager.FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY) != 0) {
// Evict key
- enforceManagedProfile(
- callingUserId, "set FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY");
+ Preconditions.checkCallingUser(isManagedProfile(callingUserId));
+ Preconditions.checkArgument(!parent,
+ "Cannot set FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY for the parent");
if (!isProfileOwner(adminComponent, callingUserId)) {
throw new SecurityException("Only profile owner admins can set "
+ "FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY");
}
- if (parent) {
- throw new IllegalArgumentException(
- "Cannot set FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY for the parent");
- }
if (!mInjector.storageManagerIsFileBasedEncryptionEnabled()) {
throw new UnsupportedOperationException(
"FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY only applies to FBE devices");
@@ -4755,32 +4761,20 @@
@Override
public void enforceCanManageCaCerts(ComponentName who, String callerPackage) {
- if (who == null) {
- if (!isCallerDelegate(callerPackage, mInjector.binderGetCallingUid(),
- DELEGATION_CERT_INSTALL)) {
- mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null);
- }
- } else {
- enforceProfileOrDeviceOwner(who);
- }
+ final CallerIdentity caller = getCallerIdentity(who, callerPackage);
+ Preconditions.checkCallAuthorization(canManageCaCerts(caller));
}
- private void enforceProfileOrDeviceOwner(ComponentName who) {
- synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- }
- }
-
- private void enforceNetworkStackOrProfileOrDeviceOwner(ComponentName who) {
- if (hasCallingPermission(PERMISSION_MAINLINE_NETWORK_STACK)) {
- return;
- }
- enforceProfileOrDeviceOwner(who);
+ private boolean canManageCaCerts(CallerIdentity caller) {
+ return (caller.hasAdminComponent() && (isDeviceOwner(caller) || isProfileOwner(caller)))
+ || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_CERT_INSTALL))
+ || hasCallingOrSelfPermission(MANAGE_CA_CERTIFICATES);
}
@Override
public boolean approveCaCert(String alias, int userId, boolean approval) {
- enforceManageUsers();
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+
synchronized (getLockObject()) {
Set<String> certs = getUserData(userId).mAcceptedCaCertificates;
boolean changed = (approval ? certs.add(alias) : certs.remove(alias));
@@ -4795,7 +4789,8 @@
@Override
public boolean isCaCertApproved(String alias, int userId) {
- enforceManageUsers();
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+
synchronized (getLockObject()) {
return getUserData(userId).mAcceptedCaCertificates.contains(alias);
}
@@ -4820,21 +4815,20 @@
}
@Override
- public boolean installCaCert(ComponentName admin, String callerPackage, byte[] certBuffer)
- throws RemoteException {
+ public boolean installCaCert(ComponentName admin, String callerPackage, byte[] certBuffer) {
if (!mHasFeature) {
return false;
}
- enforceCanManageCaCerts(admin, callerPackage);
+ final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
+ Preconditions.checkCallAuthorization(canManageCaCerts(caller));
- final UserHandle userHandle = mInjector.binderGetCallingUserHandle();
final String alias = mInjector.binderWithCleanCallingIdentity(() -> {
- String installedAlias = mCertificateMonitor.installCaCert(userHandle, certBuffer);
- final boolean isDelegate = (admin == null);
+ String installedAlias = mCertificateMonitor.installCaCert(
+ caller.getUserHandle(), certBuffer);
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.INSTALL_CA_CERT)
- .setAdmin(callerPackage)
- .setBoolean(isDelegate)
+ .setAdmin(caller.getPackageName())
+ .setBoolean(/* isDelegate */ admin == null)
.write();
return installedAlias;
});
@@ -4845,8 +4839,8 @@
}
synchronized (getLockObject()) {
- getUserData(userHandle.getIdentifier()).mOwnerInstalledCaCerts.add(alias);
- saveSettingsLocked(userHandle.getIdentifier());
+ getUserData(caller.getUserId()).mOwnerInstalledCaCerts.add(alias);
+ saveSettingsLocked(caller.getUserId());
}
return true;
}
@@ -4856,22 +4850,22 @@
if (!mHasFeature) {
return;
}
- enforceCanManageCaCerts(admin, callerPackage);
+ final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
+ Preconditions.checkCallAuthorization(canManageCaCerts(caller));
- final int userId = mInjector.userHandleGetCallingUserId();
mInjector.binderWithCleanCallingIdentity(() -> {
- mCertificateMonitor.uninstallCaCerts(UserHandle.of(userId), aliases);
- final boolean isDelegate = (admin == null);
+ mCertificateMonitor.uninstallCaCerts(caller.getUserHandle(), aliases);
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.UNINSTALL_CA_CERTS)
- .setAdmin(callerPackage)
- .setBoolean(isDelegate)
+ .setAdmin(caller.getPackageName())
+ .setBoolean(/* isDelegate */ admin == null)
.write();
});
synchronized (getLockObject()) {
- if (getUserData(userId).mOwnerInstalledCaCerts.removeAll(Arrays.asList(aliases))) {
- saveSettingsLocked(userId);
+ if (getUserData(caller.getUserId()).mOwnerInstalledCaCerts.removeAll(
+ Arrays.asList(aliases))) {
+ saveSettingsLocked(caller.getUserId());
}
}
}
@@ -5668,8 +5662,8 @@
throws SecurityException {
Objects.requireNonNull(who, "ComponentName is null");
- enforceProfileOrDeviceOwner(who);
final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
final int userId = caller.getUserId();
mInjector.binderWithCleanCallingIdentity(() -> {
@@ -5695,7 +5689,7 @@
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_ALWAYS_ON_VPN_PACKAGE)
- .setAdmin(who)
+ .setAdmin(caller.getComponentName())
.setStrings(vpnPackage)
.setBoolean(lockdown)
.setInt(lockdownWhitelist != null ? lockdownWhitelist.size() : 0)
@@ -5715,11 +5709,14 @@
@Override
public String getAlwaysOnVpnPackage(ComponentName admin) throws SecurityException {
- enforceProfileOrDeviceOwner(admin);
+ Objects.requireNonNull(admin, "ComponentName is null");
- final int userId = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity caller = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+
return mInjector.binderWithCleanCallingIdentity(
- () -> mInjector.getConnectivityManager().getAlwaysOnVpnPackageForUser(userId));
+ () -> mInjector.getConnectivityManager().getAlwaysOnVpnPackageForUser(
+ caller.getUserId()));
}
@Override
@@ -5733,11 +5730,14 @@
@Override
public boolean isAlwaysOnVpnLockdownEnabled(ComponentName admin) throws SecurityException {
- enforceNetworkStackOrProfileOrDeviceOwner(admin);
+ Objects.requireNonNull(admin, "ComponentName is null");
- final int userId = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity caller = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller)
+ || hasCallingPermission(PERMISSION_MAINLINE_NETWORK_STACK));
+
return mInjector.binderWithCleanCallingIdentity(
- () -> mInjector.getConnectivityManager().isVpnLockdownEnabled(userId));
+ () -> mInjector.getConnectivityManager().isVpnLockdownEnabled(caller.getUserId()));
}
@Override
@@ -5752,11 +5752,14 @@
@Override
public List<String> getAlwaysOnVpnLockdownWhitelist(ComponentName admin)
throws SecurityException {
- enforceProfileOrDeviceOwner(admin);
+ Objects.requireNonNull(admin, "ComponentName is null");
- final int userId = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity caller = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+
return mInjector.binderWithCleanCallingIdentity(
- () -> mInjector.getConnectivityManager().getVpnLockdownWhitelist(userId));
+ () -> mInjector.getConnectivityManager().getVpnLockdownWhitelist(
+ caller.getUserId()));
}
private void forceWipeDeviceNoLock(boolean wipeExtRequested, String reason, boolean wipeEuicc) {
@@ -6046,11 +6049,13 @@
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
return;
}
- enforceSystemCaller("report password change");
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(isSystemUid(caller));
// Managed Profile password can only be changed when it has a separate challenge.
if (!isSeparateProfileChallengeEnabled(userId)) {
- enforceNotManagedProfile(userId, "set the active password");
+ Preconditions.checkCallAuthorization(!isManagedProfile(userId), String.format("You can "
+ + "not set the active password for a managed profile, userId = %d", userId));
}
DevicePolicyData policy = getUserData(userId);
@@ -6103,8 +6108,9 @@
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle));
Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN));
if (!isSeparateProfileChallengeEnabled(userHandle)) {
- enforceNotManagedProfile(userHandle,
- "report failed password attempt if separate profile challenge is not in place");
+ Preconditions.checkCallAuthorization(!isManagedProfile(userHandle), String.format(
+ "You can not report failed password attempt if separate profile challenge is "
+ + "not in place for a managed profile, userId = %d", userHandle));
}
boolean wipeData = false;
@@ -7329,7 +7335,7 @@
return null;
}
if (!callingUserOnly) {
- enforceManageUsers();
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
}
synchronized (getLockObject()) {
if (!mOwners.hasDeviceOwner()) {
@@ -7348,7 +7354,8 @@
if (!mHasFeature) {
return UserHandle.USER_NULL;
}
- enforceManageUsers();
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+
synchronized (getLockObject()) {
return mOwners.hasDeviceOwner() ? mOwners.getDeviceOwnerUserId() : UserHandle.USER_NULL;
}
@@ -7363,7 +7370,8 @@
if (!mHasFeature) {
return null;
}
- enforceManageUsers();
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+
synchronized (getLockObject()) {
if (!mOwners.hasDeviceOwner()) {
return null;
@@ -7588,8 +7596,10 @@
}
Objects.requireNonNull(who, "ComponentName is null");
- final int userId = mInjector.userHandleGetCallingUserId();
- enforceNotManagedProfile(userId, "clear profile owner");
+ final CallerIdentity caller = getCallerIdentity(who);
+ final int userId = caller.getUserId();
+ Preconditions.checkCallingUser(!isManagedProfile(userId));
+
enforceUserUnlocked(userId);
synchronized (getLockObject()) {
// Check if this is the profile owner who is calling
@@ -7706,9 +7716,10 @@
if (!mHasFeature) {
return DevicePolicyManager.STATE_USER_UNMANAGED;
}
- enforceManageUsers();
- int userHandle = mInjector.userHandleGetCallingUserId();
- return getUserProvisioningState(userHandle);
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(canManageUsers(caller));
+
+ return getUserProvisioningState(caller.getUserId());
}
private int getUserProvisioningState(int userHandle) {
@@ -7746,8 +7757,8 @@
}
transitionCheckNeeded = false;
} else {
- // For all other cases, caller must have MANAGE_PROFILE_AND_DEVICE_OWNERS.
- enforceCanManageProfileAndDeviceOwners();
+ Preconditions.checkCallAuthorization(
+ hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
}
final DevicePolicyData policyData = getUserData(userHandle);
@@ -7802,11 +7813,13 @@
return;
}
Objects.requireNonNull(who, "ComponentName is null");
+
+ final CallerIdentity caller = getCallerIdentity(who);
+ final int userId = caller.getUserId();
+ Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallingUser(isManagedProfile(userId));
+
synchronized (getLockObject()) {
- // Check if this is the profile owner who is calling
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- final int userId = UserHandle.getCallingUserId();
- enforceManagedProfile(userId, "enable the profile");
// Check if the profile is already enabled.
UserInfo managedProfile = getUserInfo(userId);
if (managedProfile.isEnabled()) {
@@ -7832,14 +7845,15 @@
@Override
public void setProfileName(ComponentName who, String profileName) {
Objects.requireNonNull(who, "ComponentName is null");
- enforceProfileOrDeviceOwner(who);
- final int userId = UserHandle.getCallingUserId();
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+
mInjector.binderWithCleanCallingIdentity(() -> {
- mUserManager.setUserName(userId, profileName);
+ mUserManager.setUserName(caller.getUserId(), profileName);
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_PROFILE_NAME)
- .setAdmin(who)
+ .setAdmin(caller.getComponentName())
.write();
});
}
@@ -7948,7 +7962,8 @@
if (!mHasFeature) {
return null;
}
- enforceManageUsers();
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+
ComponentName profileOwner = getProfileOwner(userHandle);
if (profileOwner == null) {
return null;
@@ -8120,7 +8135,8 @@
}
return;
}
- enforceCanManageProfileAndDeviceOwners();
+ Preconditions.checkCallAuthorization(
+ hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
if ((mIsWatch || hasUserSetupCompleted(userHandle))) {
if (!isCallerWithSystemUid()) {
@@ -8156,7 +8172,8 @@
@UserIdInt int userId,
boolean hasIncompatibleAccountsOrNonAdb) {
if (!isAdb()) {
- enforceCanManageProfileAndDeviceOwners();
+ Preconditions.checkCallAuthorization(
+ hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
}
final int code = checkDeviceOwnerProvisioningPreConditionLocked(
@@ -8210,11 +8227,9 @@
}
}
- private void enforceManageUsers() {
- final int callingUid = mInjector.binderGetCallingUid();
- if (!(isCallerWithSystemUid() || callingUid == Process.ROOT_UID)) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
- }
+ private boolean canManageUsers(CallerIdentity caller) {
+ return isSystemUid(caller) || isRootUid(caller)
+ || hasCallingOrSelfPermission(permission.MANAGE_USERS);
}
private boolean hasCallingPermission(String permission) {
@@ -8244,20 +8259,6 @@
|| hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS);
}
- private void enforceManagedProfile(int userId, String message) {
- if (!isManagedProfile(userId)) {
- throw new SecurityException(String.format(
- "You can not %s outside a managed profile, userId = %d", message, userId));
- }
- }
-
- private void enforceNotManagedProfile(int userId, String message) {
- if (isManagedProfile(userId)) {
- throw new SecurityException(String.format(
- "You can not %s for a managed profile, userId = %d", message, userId));
- }
- }
-
private void enforceDeviceOwnerOrManageUsers() {
synchronized (getLockObject()) {
if (getActiveAdminWithPolicyForUidLocked(null, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER,
@@ -8265,7 +8266,7 @@
return;
}
}
- enforceManageUsers();
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
}
private void enforceProfileOwnerOrSystemUser() {
@@ -8879,7 +8880,8 @@
if (!mHasFeature) {
return null;
}
- enforceManageUsers();
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+
synchronized (getLockObject()) {
List<String> result = null;
// If we have multiple profiles we return the intersection of the
@@ -8964,6 +8966,7 @@
return false;
}
Objects.requireNonNull(who, "ComponentName is null");
+
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
@@ -9005,6 +9008,7 @@
return null;
}
Objects.requireNonNull(who, "ComponentName is null");
+
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
@@ -9016,13 +9020,13 @@
@Override
public List getPermittedInputMethodsForCurrentUser() {
- enforceManageUsers();
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(canManageUsers(caller));
- final int callingUserId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
List<String> result = null;
// Only device or profile owners can have permitted lists set.
- DevicePolicyData policy = getUserDataUnchecked(callingUserId);
+ DevicePolicyData policy = getUserDataUnchecked(caller.getUserId());
for (int i = 0; i < policy.mAdminList.size(); i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
List<String> fromAdmin = admin.permittedInputMethods;
@@ -9037,8 +9041,8 @@
// If we have a permitted list add all system input methods.
if (result != null) {
- List<InputMethodInfo> imes =
- InputMethodManagerInternal.get().getInputMethodListAsUser(callingUserId);
+ List<InputMethodInfo> imes = InputMethodManagerInternal
+ .get().getInputMethodListAsUser(caller.getUserId());
if (imes != null) {
for (InputMethodInfo ime : imes) {
ServiceInfo serviceInfo = ime.getServiceInfo();
@@ -9482,11 +9486,12 @@
@Override
public boolean isEphemeralUser(ComponentName who) {
Objects.requireNonNull(who, "ComponentName is null");
- enforceProfileOrDeviceOwner(who);
- final int callingUserId = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+
return mInjector.binderWithCleanCallingIdentity(
- () -> mInjector.getUserManager().isUserEphemeral(callingUserId));
+ () -> mInjector.getUserManager().isUserEphemeral(caller.getUserId()));
}
@Override
@@ -10225,6 +10230,7 @@
return;
}
Objects.requireNonNull(who, "ComponentName is null");
+
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
@@ -10248,6 +10254,7 @@
return false;
}
Objects.requireNonNull(who, "ComponentName is null");
+
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
@@ -10270,12 +10277,23 @@
@Override
public void setSecondaryLockscreenEnabled(ComponentName who, boolean enabled) {
- enforceCanSetSecondaryLockscreenEnabled(who);
+ Objects.requireNonNull(who, "ComponentName is null");
+
+ // Check can set secondary lockscreen enabled
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(!isManagedProfile(caller.getUserId()),
+ String.format("User %d is not allowed to call setSecondaryLockscreenEnabled",
+ caller.getUserId()));
+ // Allow testOnly admins to bypass supervision config requirement.
+ Preconditions.checkCallAuthorization(isAdminTestOnlyLocked(who, caller.getUserId())
+ || isDefaultSupervisor(caller), String.format("Admin %s is not the "
+ + "default supervision component", caller.getComponentName()));
+
synchronized (getLockObject()) {
- final int userId = mInjector.userHandleGetCallingUserId();
- DevicePolicyData policy = getUserData(userId);
+ DevicePolicyData policy = getUserData(caller.getUserId());
policy.mSecondaryLockscreenEnabled = enabled;
- saveSettingsLocked(userId);
+ saveSettingsLocked(caller.getUserId());
}
}
@@ -10286,31 +10304,14 @@
}
}
- private void enforceCanSetSecondaryLockscreenEnabled(ComponentName who) {
- enforceProfileOrDeviceOwner(who);
- final int userId = mInjector.userHandleGetCallingUserId();
- if (isManagedProfile(userId)) {
- throw new SecurityException(
- "User " + userId + " is not allowed to call setSecondaryLockscreenEnabled");
- }
- synchronized (getLockObject()) {
- if (isAdminTestOnlyLocked(who, userId)) {
- // Allow testOnly admins to bypass supervision config requirement.
- return;
- }
- }
- // Only the default supervision app can use this API.
+ private boolean isDefaultSupervisor(CallerIdentity caller) {
final String supervisor = mContext.getResources().getString(
com.android.internal.R.string.config_defaultSupervisionProfileOwnerComponent);
if (supervisor == null) {
- throw new SecurityException("Unable to set secondary lockscreen setting, no "
- + "default supervision component defined");
+ return false;
}
final ComponentName supervisorComponent = ComponentName.unflattenFromString(supervisor);
- if (!who.equals(supervisorComponent)) {
- throw new SecurityException(
- "Admin " + who + " is not the default supervision component");
- }
+ return caller.getComponentName().equals(supervisorComponent);
}
@Override
@@ -11655,7 +11656,9 @@
@Override
public SystemUpdateInfo getPendingSystemUpdate(ComponentName admin) {
Objects.requireNonNull(admin, "ComponentName is null");
- enforceProfileOrDeviceOwner(admin);
+
+ final CallerIdentity caller = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
return mOwners.getSystemUpdateInfo();
}
@@ -11848,8 +11851,11 @@
@Override
public int checkProvisioningPreCondition(String action, String packageName) {
- Objects.requireNonNull(packageName);
- enforceCanManageProfileAndDeviceOwners();
+ Objects.requireNonNull(packageName, "packageName is null");
+
+ Preconditions.checkCallAuthorization(
+ hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
+
return checkProvisioningPreConditionSkipPermission(action, packageName);
}
@@ -12110,8 +12116,12 @@
@Override
public boolean isManagedProfile(ComponentName admin) {
- enforceProfileOrDeviceOwner(admin);
- return isManagedProfile(mInjector.userHandleGetCallingUserId());
+ Objects.requireNonNull(admin, "ComponentName is null");
+
+ final CallerIdentity caller = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+
+ return isManagedProfile(caller.getUserId());
}
@Override
@@ -12237,8 +12247,10 @@
return;
}
Objects.requireNonNull(who, "ComponentName is null");
+
final CallerIdentity caller = getCallerIdentity(who);
- enforceManagedProfile(caller.getUserId(), "set organization color");
+ Preconditions.checkCallingUser(isManagedProfile(caller.getUserId()));
+
synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
admin.organizationColor = color;
@@ -12246,7 +12258,7 @@
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_ORGANIZATION_COLOR)
- .setAdmin(who)
+ .setAdmin(caller.getComponentName())
.write();
}
@@ -12259,9 +12271,10 @@
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userId));
+ Preconditions.checkCallAuthorization(canManageUsers(caller));
+ Preconditions.checkCallAuthorization(isManagedProfile(userId), String.format("You can not "
+ + "set organization color outside a managed profile, userId = %d", userId));
- enforceManageUsers();
- enforceManagedProfile(userId, "set organization color");
synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerAdminLocked(userId);
admin.organizationColor = color;
@@ -12275,8 +12288,10 @@
return ActiveAdmin.DEF_ORGANIZATION_COLOR;
}
Objects.requireNonNull(who, "ComponentName is null");
+
final CallerIdentity caller = getCallerIdentity(who);
- enforceManagedProfile(caller.getUserId(), "get organization color");
+ Preconditions.checkCallingUser(isManagedProfile(caller.getUserId()));
+
synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
return admin.organizationColor;
@@ -12292,8 +12307,9 @@
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle));
+ Preconditions.checkCallAuthorization(isManagedProfile(userHandle), String.format("You can "
+ + "not get organization color outside a managed profile, userId = %d", userHandle));
- enforceManagedProfile(userHandle, "get organization color");
synchronized (getLockObject()) {
ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle);
return (profileOwner != null)
@@ -12326,8 +12342,10 @@
return null;
}
Objects.requireNonNull(who, "ComponentName is null");
+
final CallerIdentity caller = getCallerIdentity(who);
- enforceManagedProfile(caller.getUserId(), "get organization name");
+ Preconditions.checkCallingUser(isManagedProfile(caller.getUserId()));
+
synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
return admin.organizationName;
@@ -12355,8 +12373,10 @@
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle));
+ Preconditions.checkCallAuthorization(isManagedProfile(userHandle), String.format(
+ "You can not get organization name outside a managed profile, userId = %d",
+ userHandle));
- enforceManagedProfile(userHandle, "get organization name");
synchronized (getLockObject()) {
ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle);
return (profileOwner != null)
@@ -12793,16 +12813,6 @@
return mSecurityLogMonitor.forceLogs();
}
- private void enforceCanManageDeviceAdmin() {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS,
- null);
- }
-
- private void enforceCanManageProfileAndDeviceOwners() {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
- }
-
private void enforceCallerSystemUserHandle() {
final int callingUid = mInjector.binderGetCallingUid();
final int userId = UserHandle.getUserId(callingUid);
@@ -12813,9 +12823,11 @@
@Override
public boolean isUninstallInQueue(final String packageName) {
- enforceCanManageDeviceAdmin();
- final int userId = mInjector.userHandleGetCallingUserId();
- Pair<String, Integer> packageUserPair = new Pair<>(packageName, userId);
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(
+ hasCallingOrSelfPermission(permission.MANAGE_DEVICE_ADMINS));
+
+ Pair<String, Integer> packageUserPair = new Pair<>(packageName, caller.getUserId());
synchronized (getLockObject()) {
return mPackagesToRemove.contains(packageUserPair);
}
@@ -12823,11 +12835,13 @@
@Override
public void uninstallPackageWithActiveAdmins(final String packageName) {
- enforceCanManageDeviceAdmin();
Preconditions.checkArgument(!TextUtils.isEmpty(packageName));
- final int userId = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(
+ hasCallingOrSelfPermission(permission.MANAGE_DEVICE_ADMINS));
+ final int userId = caller.getUserId();
enforceUserUnlocked(userId);
final ComponentName profileOwner = getProfileOwner(userId);
@@ -12876,7 +12890,9 @@
@Override
public boolean isDeviceProvisioned() {
- enforceManageUsers();
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(canManageUsers(caller));
+
synchronized (getLockObject()) {
return getUserDataUnchecked(UserHandle.USER_SYSTEM).mUserSetupComplete;
}
@@ -12960,7 +12976,8 @@
@Override
public void setDeviceProvisioningConfigApplied() {
- enforceManageUsers();
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+
synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
policy.mDeviceProvisioningConfigApplied = true;
@@ -12970,7 +12987,8 @@
@Override
public boolean isDeviceProvisioningConfigApplied() {
- enforceManageUsers();
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+
synchronized (getLockObject()) {
final DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
return policy.mDeviceProvisioningConfigApplied;
@@ -12986,8 +13004,10 @@
*/
@Override
public void forceUpdateUserSetupComplete() {
- enforceCanManageProfileAndDeviceOwners();
+ Preconditions.checkCallAuthorization(
+ hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
enforceCallerSystemUserHandle();
+
// no effect if it's called from user build
if (!mInjector.isBuildDebuggable()) {
return;
@@ -13008,25 +13028,28 @@
if (!mHasFeature) {
return;
}
- Objects.requireNonNull(admin);
- enforceProfileOrDeviceOwner(admin);
- int userId = mInjector.userHandleGetCallingUserId();
- toggleBackupServiceActive(userId, enabled);
+ Objects.requireNonNull(admin, "ComponentName is null");
+
+ final CallerIdentity caller = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+
+ toggleBackupServiceActive(caller.getUserId(), enabled);
}
@Override
public boolean isBackupServiceEnabled(ComponentName admin) {
- Objects.requireNonNull(admin);
if (!mHasFeature) {
return true;
}
+ Objects.requireNonNull(admin, "ComponentName is null");
- enforceProfileOrDeviceOwner(admin);
+ final CallerIdentity caller = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+
synchronized (getLockObject()) {
try {
IBackupManager ibm = mInjector.getIBackupManager();
- return ibm != null && ibm.isBackupServiceActive(
- mInjector.userHandleGetCallingUserId());
+ return ibm != null && ibm.isBackupServiceActive(caller.getUserId());
} catch (RemoteException e) {
throw new IllegalStateException("Failed requesting backup service state.", e);
}
@@ -13608,13 +13631,14 @@
Objects.requireNonNull(admin, "ComponentName is null");
Objects.requireNonNull(packageName, "packageName is null");
Objects.requireNonNull(callback, "callback is null");
- enforceProfileOrDeviceOwner(admin);
- final int userId = UserHandle.getCallingUserId();
+
+ final CallerIdentity caller = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
long ident = mInjector.binderClearCallingIdentity();
try {
ActivityManager.getService().clearApplicationUserData(packageName, false, callback,
- userId);
+ caller.getUserId());
} catch(RemoteException re) {
// Same process, should not happen.
} catch (SecurityException se) {
@@ -13667,7 +13691,9 @@
@Override
public List<String> getDisallowedSystemApps(ComponentName admin, int userId,
String provisioningAction) throws RemoteException {
- enforceCanManageProfileAndDeviceOwners();
+ Preconditions.checkCallAuthorization(
+ hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
+
return new ArrayList<>(
mOverlayPackagesProvider.getNonRequiredApps(admin, userId, provisioningAction));
}
@@ -13678,31 +13704,23 @@
if (!mHasFeature) {
return;
}
-
- Objects.requireNonNull(admin, "Admin cannot be null.");
+ Objects.requireNonNull(admin, "ComponentName is null");
Objects.requireNonNull(target, "Target cannot be null.");
+ Preconditions.checkArgument(!admin.equals(target),
+ "Provided administrator and target are the same object.");
+ Preconditions.checkArgument(!admin.getPackageName().equals(target.getPackageName()),
+ "Provided administrator and target have the same package name.");
- enforceProfileOrDeviceOwner(admin);
+ final CallerIdentity caller = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
- if (admin.equals(target)) {
- throw new IllegalArgumentException("Provided administrator and target are "
- + "the same object.");
- }
-
- if (admin.getPackageName().equals(target.getPackageName())) {
- throw new IllegalArgumentException("Provided administrator and target have "
- + "the same package name.");
- }
-
- final int callingUserId = mInjector.userHandleGetCallingUserId();
+ final int callingUserId = caller.getUserId();
final DevicePolicyData policy = getUserData(callingUserId);
final DeviceAdminInfo incomingDeviceInfo = findAdmin(target, callingUserId,
/* throwForMissingPermission= */ true);
checkActiveAdminPrecondition(target, incomingDeviceInfo, policy);
- if (!incomingDeviceInfo.supportsTransferOwnership()) {
- throw new IllegalArgumentException("Provided target does not support "
- + "ownership transfer.");
- }
+ Preconditions.checkArgument(incomingDeviceInfo.supportsTransferOwnership(),
+ "Provided target does not support ownership transfer.");
final long id = mInjector.binderClearCallingIdentity();
String ownerType = null;
@@ -13725,7 +13743,7 @@
if (bundle == null) {
bundle = new PersistableBundle();
}
- if (isProfileOwner(admin, callingUserId)) {
+ if (isProfileOwner(caller)) {
ownerType = ADMIN_TYPE_PROFILE_OWNER;
prepareTransfer(admin, target, bundle, callingUserId,
ADMIN_TYPE_PROFILE_OWNER);
@@ -13736,7 +13754,7 @@
if (isUserAffiliatedWithDeviceLocked(callingUserId)) {
notifyAffiliatedProfileTransferOwnershipComplete(callingUserId);
}
- } else if (isDeviceOwner(admin, callingUserId)) {
+ } else if (isDeviceOwner(caller)) {
ownerType = ADMIN_TYPE_DEVICE_OWNER;
prepareTransfer(admin, target, bundle, callingUserId,
ADMIN_TYPE_DEVICE_OWNER);
@@ -14406,7 +14424,8 @@
if (!mHasFeature) {
return false;
}
- enforceManageUsers();
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+
long id = mInjector.binderClearCallingIdentity();
try {
return isManagedKioskInternal();
@@ -14431,7 +14450,8 @@
if (!mHasFeature) {
return false;
}
- enforceManageUsers();
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+
return mInjector.binderWithCleanCallingIdentity(() -> isUnattendedManagedKioskUnchecked());
}
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index bbcb312..5f145f3 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -2135,6 +2135,11 @@
return binder::Status::ok();
}
+binder::Status IncrementalService::DataLoaderStub::reportStreamHealth(MountId mountId,
+ int newStatus) {
+ return binder::Status::ok();
+}
+
bool IncrementalService::DataLoaderStub::isHealthParamsValid() const {
return mHealthCheckParams.blockedTimeoutMs > 0 &&
mHealthCheckParams.blockedTimeoutMs < mHealthCheckParams.unhealthyTimeoutMs;
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index d820417..504c02a 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -200,6 +200,7 @@
private:
binder::Status onStatusChanged(MountId mount, int newStatus) final;
+ binder::Status reportStreamHealth(MountId mount, int newStatus) final;
sp<content::pm::IDataLoader> getDataLoader();
diff --git a/services/people/java/com/android/server/people/PeopleService.java b/services/people/java/com/android/server/people/PeopleService.java
index 8b1e9c5..91cb481 100644
--- a/services/people/java/com/android/server/people/PeopleService.java
+++ b/services/people/java/com/android/server/people/PeopleService.java
@@ -30,6 +30,7 @@
import android.content.pm.ParceledListSlice;
import android.os.Binder;
import android.os.CancellationSignal;
+import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -73,7 +74,7 @@
@Override
public void onStart() {
- publishBinderService(Context.PEOPLE_SERVICE, new BinderService());
+ publishBinderService(Context.PEOPLE_SERVICE, mService);
publishLocalService(PeopleServiceInternal.class, new LocalService());
}
@@ -117,7 +118,7 @@
message);
}
- private final class BinderService extends IPeopleManager.Stub {
+ final IBinder mService = new IPeopleManager.Stub() {
@Override
public ParceledListSlice<ConversationChannel> getRecentConversations() {
@@ -146,7 +147,7 @@
enforceSystemRootOrSystemUI(getContext(), "get last interaction");
return mDataManager.getLastInteraction(packageName, userId, shortcutId);
}
- }
+ };
@VisibleForTesting
final class LocalService extends PeopleServiceInternal {
diff --git a/services/robotests/src/com/android/server/location/LocationRequestStatisticsTest.java b/services/robotests/src/com/android/server/location/LocationRequestStatisticsTest.java
deleted file mode 100644
index 2d0fe58..0000000
--- a/services/robotests/src/com/android/server/location/LocationRequestStatisticsTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.location;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.platform.test.annotations.Presubmit;
-
-import com.android.internal.util.IndentingPrintWriter;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-/**
- * Unit tests for {@link LocationRequestStatistics}.
- */
-@RunWith(RobolectricTestRunner.class)
-@Presubmit
-public class LocationRequestStatisticsTest {
- private static final String FEATURE_ID = "featureId";
-
- /**
- * Check adding and removing requests & strings
- */
- @Test
- public void testRequestSummary() {
- LocationRequestStatistics.RequestSummary summary =
- new LocationRequestStatistics.RequestSummary(
- "com.example", FEATURE_ID, "gps", 1000);
- StringWriter stringWriter = new StringWriter();
- summary.dump(new IndentingPrintWriter(new PrintWriter(stringWriter), " "), 1234);
- assertThat(stringWriter.toString()).startsWith("At");
-
- StringWriter stringWriterRemove = new StringWriter();
- summary = new LocationRequestStatistics.RequestSummary(
- "com.example", "gps", FEATURE_ID,
- LocationRequestStatistics.RequestSummary.REQUEST_ENDED_INTERVAL);
- summary.dump(new IndentingPrintWriter(new PrintWriter(stringWriterRemove), " "), 2345);
- assertThat(stringWriterRemove.toString()).contains("-");
- assertThat(stringWriterRemove.toString()).contains(FEATURE_ID);
- }
-
- /**
- * Check summary list size capping
- */
- @Test
- public void testSummaryList() {
- LocationRequestStatistics statistics = new LocationRequestStatistics();
- statistics.history.addRequest("com.example", FEATURE_ID, "gps", 1000);
- assertThat(statistics.history.mList.size()).isEqualTo(1);
- // Try (not) to overflow
- for (int i = 0; i < LocationRequestStatistics.RequestSummaryLimitedHistory.MAX_SIZE; i++) {
- statistics.history.addRequest("com.example", FEATURE_ID, "gps", 1000);
- }
- assertThat(statistics.history.mList.size()).isEqualTo(
- LocationRequestStatistics.RequestSummaryLimitedHistory.MAX_SIZE);
- }
-}
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
index be258dc..3cd415e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
@@ -202,22 +202,20 @@
@Test
public void testIsEnabled() {
assertThat(mManager.isEnabled(CURRENT_USER)).isTrue();
+ assertThat(mManager.isEnabled(OTHER_USER)).isTrue();
mInjector.getSettingsHelper().setLocationEnabled(false, CURRENT_USER);
assertThat(mManager.isEnabled(CURRENT_USER)).isFalse();
+ assertThat(mManager.isEnabled(OTHER_USER)).isTrue();
mInjector.getSettingsHelper().setLocationEnabled(true, CURRENT_USER);
mProvider.setAllowed(false);
assertThat(mManager.isEnabled(CURRENT_USER)).isFalse();
+ assertThat(mManager.isEnabled(OTHER_USER)).isFalse();
mProvider.setAllowed(true);
- mInjector.getUserInfoHelper().setCurrentUserId(OTHER_USER);
- assertThat(mManager.isEnabled(CURRENT_USER)).isFalse();
- assertThat(mManager.isEnabled(OTHER_USER)).isTrue();
-
- mInjector.getUserInfoHelper().setCurrentUserId(CURRENT_USER);
assertThat(mManager.isEnabled(CURRENT_USER)).isTrue();
- assertThat(mManager.isEnabled(OTHER_USER)).isFalse();
+ assertThat(mManager.isEnabled(OTHER_USER)).isTrue();
}
@Test
@@ -237,23 +235,15 @@
mProvider.setAllowed(false);
verify(listener, timeout(TIMEOUT_MS).times(2)).onProviderEnabledChanged(NAME, CURRENT_USER,
false);
+ verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, OTHER_USER,
+ false);
mProvider.setAllowed(true);
verify(listener, timeout(TIMEOUT_MS).times(2)).onProviderEnabledChanged(NAME, CURRENT_USER,
true);
-
- mInjector.getUserInfoHelper().setCurrentUserId(OTHER_USER);
- verify(listener, timeout(TIMEOUT_MS).times(3)).onProviderEnabledChanged(NAME, CURRENT_USER,
- false);
verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, OTHER_USER,
true);
- mInjector.getUserInfoHelper().setCurrentUserId(CURRENT_USER);
- verify(listener, timeout(TIMEOUT_MS).times(3)).onProviderEnabledChanged(NAME, CURRENT_USER,
- true);
- verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, OTHER_USER,
- false);
-
mManager.removeEnabledListener(listener);
mInjector.getSettingsHelper().setLocationEnabled(false, CURRENT_USER);
verifyNoMoreInteractions(listener);
@@ -397,16 +387,6 @@
mProvider.setAllowed(true);
verify(listener, timeout(TIMEOUT_MS).times(2)).onProviderEnabledChanged(NAME, true);
- mInjector.getUserInfoHelper().setCurrentUserId(OTHER_USER);
- verify(listener, timeout(TIMEOUT_MS).times(3)).onProviderEnabledChanged(NAME, false);
- loc = createLocation(NAME, mRandom);
- mProvider.setProviderLocation(loc);
- verify(listener, times(1)).onLocationChanged(any(Location.class),
- nullable(IRemoteCallback.class));
-
- mInjector.getUserInfoHelper().setCurrentUserId(CURRENT_USER);
- verify(listener, timeout(TIMEOUT_MS).times(3)).onProviderEnabledChanged(NAME, true);
-
loc = createLocation(NAME, mRandom);
mProvider.setProviderLocation(loc);
verify(listener, times(2)).onLocationChanged(locationCaptor.capture(),
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/util/FakeLocationPowerSaveModeHelper.java b/services/tests/mockingservicestests/src/com/android/server/location/util/FakeLocationPowerSaveModeHelper.java
index 3ead5d4..aea0170 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/util/FakeLocationPowerSaveModeHelper.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/util/FakeLocationPowerSaveModeHelper.java
@@ -28,7 +28,8 @@
@LocationPowerSaveMode
private int mLocationPowerSaveMode;
- public FakeLocationPowerSaveModeHelper() {
+ public FakeLocationPowerSaveModeHelper(LocationEventLog locationEventLog) {
+ super(locationEventLog);
mLocationPowerSaveMode = IPowerManager.LOCATION_MODE_NO_CHANGE;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/util/SystemLocationPowerSaveModeHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/location/util/SystemLocationPowerSaveModeHelperTest.java
index 2acb70c..7890454 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/util/SystemLocationPowerSaveModeHelperTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/util/SystemLocationPowerSaveModeHelperTest.java
@@ -84,7 +84,7 @@
Context context = mock(Context.class);
doReturn(powerManager).when(context).getSystemService(PowerManager.class);
- mHelper = new SystemLocationPowerSaveModeHelper(context);
+ mHelper = new SystemLocationPowerSaveModeHelper(context, new LocationEventLog());
mHelper.onSystemReady();
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/util/TestInjector.java b/services/tests/mockingservicestests/src/com/android/server/location/util/TestInjector.java
index 69f7376..94651e6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/util/TestInjector.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/util/TestInjector.java
@@ -16,10 +16,9 @@
package com.android.server.location.util;
-import com.android.server.location.LocationRequestStatistics;
-
public class TestInjector implements Injector {
+ private final LocationEventLog mLocationEventLog;
private final FakeUserInfoHelper mUserInfoHelper;
private final FakeAlarmHelper mAlarmHelper;
private final FakeAppOpsHelper mAppOpsHelper;
@@ -30,20 +29,19 @@
private final FakeScreenInteractiveHelper mScreenInteractiveHelper;
private final LocationAttributionHelper mLocationAttributionHelper;
private final LocationUsageLogger mLocationUsageLogger;
- private final LocationRequestStatistics mLocationRequestStatistics;
public TestInjector() {
+ mLocationEventLog = new LocationEventLog();
mUserInfoHelper = new FakeUserInfoHelper();
mAlarmHelper = new FakeAlarmHelper();
mAppOpsHelper = new FakeAppOpsHelper();
mLocationPermissionsHelper = new FakeLocationPermissionsHelper(mAppOpsHelper);
mSettingsHelper = new FakeSettingsHelper();
mAppForegroundHelper = new FakeAppForegroundHelper();
- mLocationPowerSaveModeHelper = new FakeLocationPowerSaveModeHelper();
+ mLocationPowerSaveModeHelper = new FakeLocationPowerSaveModeHelper(mLocationEventLog);
mScreenInteractiveHelper = new FakeScreenInteractiveHelper();
mLocationAttributionHelper = new LocationAttributionHelper(mAppOpsHelper);
mLocationUsageLogger = new LocationUsageLogger();
- mLocationRequestStatistics = new LocationRequestStatistics();
}
@Override
@@ -97,7 +95,7 @@
}
@Override
- public LocationRequestStatistics getLocationRequestStatistics() {
- return mLocationRequestStatistics;
+ public LocationEventLog getLocationEventLog() {
+ return mLocationEventLog;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index 36c55cc..c890c52 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -16,11 +16,21 @@
package com.android.server.biometrics.sensors;
+import static junit.framework.Assert.assertTrue;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
import android.content.Context;
+import android.hardware.biometrics.IBiometricService;
import android.platform.test.annotations.Presubmit;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -40,18 +50,21 @@
@Mock
private Context mContext;
@Mock
- private ClientMonitor.LazyDaemon<Object> mLazyDaemon;
+ private IBiometricService mBiometricService;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mScheduler = new BiometricScheduler(TAG, null /* gestureAvailabilityTracker */);
+ mScheduler = new BiometricScheduler(TAG, null /* gestureAvailabilityTracker */,
+ mBiometricService);
}
@Test
public void testClientDuplicateFinish_ignoredBySchedulerAndDoesNotCrash() {
- final ClientMonitor<Object> client1 = new TestClientMonitor(mContext, mLazyDaemon);
- final ClientMonitor<Object> client2 = new TestClientMonitor(mContext, mLazyDaemon);
+ final ClientMonitor.LazyDaemon<Object> nonNullDaemon = () -> mock(Object.class);
+
+ final ClientMonitor<Object> client1 = new TestClientMonitor(mContext, nonNullDaemon);
+ final ClientMonitor<Object> client2 = new TestClientMonitor(mContext, nonNullDaemon);
mScheduler.scheduleClientMonitor(client1);
mScheduler.scheduleClientMonitor(client2);
@@ -59,7 +72,93 @@
client1.mCallback.onClientFinished(client1, true /* success */);
}
+ @Test
+ public void testRemovesPendingOperations_whenNullHal_andNotBiometricPrompt() {
+ // Even if second client has a non-null daemon, it needs to be canceled.
+ Object daemon2 = mock(Object.class);
+
+ final ClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> null;
+ final ClientMonitor.LazyDaemon<Object> lazyDaemon2 = () -> daemon2;
+
+ final TestClientMonitor client1 = new TestClientMonitor(mContext, lazyDaemon1);
+ final TestClientMonitor client2 = new TestClientMonitor(mContext, lazyDaemon2);
+
+ final ClientMonitor.Callback callback1 = mock(ClientMonitor.Callback.class);
+ final ClientMonitor.Callback callback2 = mock(ClientMonitor.Callback.class);
+
+ // Pretend the scheduler is busy so the first operation doesn't start right away. We want
+ // to pretend like there are two operations in the queue before kicking things off
+ mScheduler.mCurrentOperation = new BiometricScheduler.Operation(
+ mock(ClientMonitor.class), mock(ClientMonitor.Callback.class));
+
+ mScheduler.scheduleClientMonitor(client1, callback1);
+ assertEquals(1, mScheduler.mPendingOperations.size());
+ // client1 is pending. Allow the scheduler to start once second client is added.
+ mScheduler.mCurrentOperation = null;
+ mScheduler.scheduleClientMonitor(client2, callback2);
+ waitForIdle();
+
+ assertTrue(client1.wasUnableToStart());
+ verify(callback1).onClientFinished(eq(client1), eq(false) /* success */);
+ verify(callback1, never()).onClientStarted(any());
+
+ assertTrue(client2.wasUnableToStart());
+ verify(callback2).onClientFinished(eq(client2), eq(false) /* success */);
+ verify(callback2, never()).onClientStarted(any());
+
+ assertTrue(mScheduler.mPendingOperations.isEmpty());
+ }
+
+ @Test
+ public void testRemovesOnlyBiometricPromptOperation_whenNullHal() {
+ // Second non-BiometricPrompt client has a valid daemon
+ final Object daemon2 = mock(Object.class);
+
+ final ClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> null;
+ final ClientMonitor.LazyDaemon<Object> lazyDaemon2 = () -> daemon2;
+
+ final TestClientMonitor client1 =
+ new TestBiometricPromptClientMonitor(mContext, lazyDaemon1);
+ final TestClientMonitor client2 = new TestClientMonitor(mContext, lazyDaemon2);
+
+ final ClientMonitor.Callback callback1 = mock(ClientMonitor.Callback.class);
+ final ClientMonitor.Callback callback2 = mock(ClientMonitor.Callback.class);
+
+ // Pretend the scheduler is busy so the first operation doesn't start right away. We want
+ // to pretend like there are two operations in the queue before kicking things off
+ mScheduler.mCurrentOperation = new BiometricScheduler.Operation(
+ mock(ClientMonitor.class), mock(ClientMonitor.Callback.class));
+
+ mScheduler.scheduleClientMonitor(client1, callback1);
+ assertEquals(1, mScheduler.mPendingOperations.size());
+ // client1 is pending. Allow the scheduler to start once second client is added.
+ mScheduler.mCurrentOperation = null;
+ mScheduler.scheduleClientMonitor(client2, callback2);
+ waitForIdle();
+
+ // Simulate that the BiometricPrompt client's sensor is ready
+ mScheduler.startPreparedClient(client1.getCookie());
+
+ assertTrue(client1.wasUnableToStart());
+ verify(callback1).onClientFinished(eq(client1), eq(false) /* success */);
+ verify(callback1, never()).onClientStarted(any());
+
+ // Client 2 was able to start
+ assertFalse(client2.wasUnableToStart());
+ assertTrue(client2.hasStarted());
+ verify(callback2).onClientStarted(eq(client2));
+ }
+
+ private static class TestBiometricPromptClientMonitor extends TestClientMonitor {
+ public TestBiometricPromptClientMonitor(@NonNull Context context,
+ @NonNull LazyDaemon<Object> lazyDaemon) {
+ super(context, lazyDaemon, 1 /* cookie */);
+ }
+ }
+
private static class TestClientMonitor extends ClientMonitor<Object> {
+ private boolean mUnableToStart;
+ private boolean mStarted;
public TestClientMonitor(@NonNull Context context, @NonNull LazyDaemon<Object> lazyDaemon) {
super(context, lazyDaemon, null /* token */, null /* listener */, 0 /* userId */,
@@ -67,14 +166,42 @@
0 /* statsAction */, 0 /* statsClient */);
}
+ public TestClientMonitor(@NonNull Context context, @NonNull LazyDaemon<Object> lazyDaemon,
+ int cookie) {
+ super(context, lazyDaemon, null /* token */, null /* listener */, 0 /* userId */,
+ TAG, cookie, 0 /* sensorId */, 0 /* statsModality */,
+ 0 /* statsAction */, 0 /* statsClient */);
+ }
+
+
@Override
public void unableToStart() {
+ assertFalse(mUnableToStart);
+ mUnableToStart = true;
+ }
+ @Override
+ public void start(@NonNull Callback callback) {
+ super.start(callback);
+ assertFalse(mStarted);
+ mStarted = true;
}
@Override
protected void startHalOperation() {
}
+
+ public boolean wasUnableToStart() {
+ return mUnableToStart;
+ }
+
+ public boolean hasStarted() {
+ return mStarted;
+ }
+ }
+
+ private static void waitForIdle() {
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/Face10Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/Face10Test.java
new file mode 100644
index 0000000..7a0d894
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/Face10Test.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.face;
+
+import android.content.Context;
+import android.hardware.biometrics.BiometricManager;
+import android.os.Binder;
+import android.os.IBinder;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import com.android.server.biometrics.sensors.LockoutResetDispatcher;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@Presubmit
+@SmallTest
+public class Face10Test {
+
+ private static final String TAG = "Face10Test";
+ private static final int SENSOR_ID = 1;
+
+ @Mock
+ private Context mContext;
+
+ private LockoutResetDispatcher mLockoutResetDispatcher;
+ private Face10 mFace10;
+ private IBinder mBinder;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
+ mFace10 = new Face10(mContext, SENSOR_ID, BiometricManager.Authenticators.BIOMETRIC_STRONG,
+ mLockoutResetDispatcher, false /* supportsSelfIllumination */,
+ 1 /* maxTemplatesAllowed */);
+ mBinder = new Binder();
+ }
+
+ @Test
+ public void scheduleRevokeChallenge_doesNotCrash() {
+ mFace10.scheduleRevokeChallenge(mBinder, TAG);
+ waitForIdle();
+ }
+
+ private static void waitForIdle() {
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 4ce6411..631b4d4 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -4407,7 +4407,7 @@
// Caller is Profile Owner, but no supervision app is configured.
setAsProfileOwner(admin1);
- assertExpectException(SecurityException.class, "no default supervision component defined",
+ assertExpectException(SecurityException.class, "is not the default supervision component",
() -> dpm.setSecondaryLockscreenEnabled(admin1, true));
assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE)));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
index 63ad53b..2a9c394 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
@@ -160,7 +160,7 @@
assertThat(playbackDevice.getActiveSource().logicalAddress).isEqualTo(
playbackDevice.mAddress);
assertThat(playbackDevice.getActiveSource().physicalAddress).isEqualTo(mPhysicalAddress);
- assertThat(playbackDevice.mIsActiveSource).isTrue();
+ assertThat(playbackDevice.isActiveSource()).isTrue();
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
index 415ae07..74fd683 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -30,10 +30,15 @@
import static com.google.common.truth.Truth.assertThat;
+import android.content.Context;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiPortInfo;
import android.media.AudioManager;
+import android.os.Handler;
+import android.os.IPowerManager;
+import android.os.IThermalService;
import android.os.Looper;
+import android.os.PowerManager;
import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;
@@ -47,6 +52,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
@@ -81,8 +88,17 @@
private HdmiPortInfo[] mHdmiPortInfo;
private boolean mWokenUp;
+ @Mock private IPowerManager mIPowerManagerMock;
+ @Mock private IThermalService mIThermalServiceMock;
+
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ Context context = InstrumentationRegistry.getTargetContext();
+ mMyLooper = mTestLooper.getLooper();
+ PowerManager powerManager = new PowerManager(context, mIPowerManagerMock,
+ mIThermalServiceMock, new Handler(mMyLooper));
mHdmiControlService =
new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
@Override
@@ -166,6 +182,11 @@
return defVal;
}
}
+
+ @Override
+ PowerManager getPowerManager() {
+ return powerManager;
+ }
};
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
@@ -174,11 +195,6 @@
mHdmiCecLocalDeviceAudioSystem = new HdmiCecLocalDeviceAudioSystem(mHdmiControlService);
mHdmiCecLocalDevicePlayback = new HdmiCecLocalDevicePlayback(mHdmiControlService) {
@Override
- void setIsActiveSource(boolean on) {
- mIsActiveSource = on;
- }
-
- @Override
protected int getPreferredAddress() {
return ADDR_PLAYBACK_1;
}
@@ -827,4 +843,68 @@
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(unexpected);
}
+
+ @Test
+ public void setActiveSource_localDevice_playback() {
+ mHdmiControlService.setActiveSource(mHdmiCecLocalDevicePlayback.mAddress,
+ SELF_PHYSICAL_ADDRESS,
+ "HdmiControlServiceTest");
+
+ assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
+ mHdmiCecLocalDevicePlayback.mAddress);
+ assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(
+ SELF_PHYSICAL_ADDRESS);
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isTrue();
+ assertThat(mHdmiCecLocalDeviceAudioSystem.isActiveSource()).isFalse();
+ }
+
+ @Test
+ public void setActiveSource_localDevice_audio() {
+ mHdmiControlService.setActiveSource(mHdmiCecLocalDeviceAudioSystem.mAddress,
+ SELF_PHYSICAL_ADDRESS,
+ "HdmiControlServiceTest");
+
+ assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
+ mHdmiCecLocalDeviceAudioSystem.mAddress);
+ assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(
+ SELF_PHYSICAL_ADDRESS);
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
+ assertThat(mHdmiCecLocalDeviceAudioSystem.isActiveSource()).isTrue();
+ }
+
+ @Test
+ public void setActiveSource_remoteDevice() {
+ mHdmiControlService.setActiveSource(Constants.ADDR_TV, 0x0000, "HdmiControlServiceTest");
+
+ assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
+ Constants.ADDR_TV);
+ assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(0x000);
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
+ assertThat(mHdmiCecLocalDeviceAudioSystem.isActiveSource()).isFalse();
+ }
+
+ @Test
+ public void setActiveSource_nonCecDevice() {
+ mHdmiControlService.setActiveSource(Constants.ADDR_INVALID, 0x1234,
+ "HdmiControlServiceTest");
+
+ assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
+ Constants.ADDR_INVALID);
+ assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(0x1234);
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
+ assertThat(mHdmiCecLocalDeviceAudioSystem.isActiveSource()).isFalse();
+ }
+
+ @Test
+ public void setActiveSource_unknown() {
+ mHdmiControlService.setActiveSource(Constants.ADDR_INVALID,
+ Constants.INVALID_PHYSICAL_ADDRESS, "HdmiControlServiceTest");
+
+ assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
+ Constants.ADDR_INVALID);
+ assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(
+ Constants.INVALID_PHYSICAL_ADDRESS);
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
+ assertThat(mHdmiCecLocalDeviceAudioSystem.isActiveSource()).isFalse();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index 498ebf4..7cbf571 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -17,6 +17,7 @@
import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
+import static com.android.server.hdmi.Constants.ADDR_INVALID;
import static com.android.server.hdmi.Constants.ADDR_TV;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
@@ -266,106 +267,197 @@
@Test
public void handleRoutingChange_otherDevice_None() {
mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
- HdmiProperties.power_state_change_on_active_source_lost_values.NONE;
- mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ HdmiProperties.power_state_change_on_active_source_lost_values.NONE;
+ mHdmiCecLocalDevicePlayback.setActiveSource(mPlaybackLogicalAddress,
+ mPlaybackPhysicalAddress, "HdmiCecLocalDevicePlaybackTest");
mStandby = false;
HdmiCecMessage message =
HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x0000, 0x5000);
assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().physicalAddress).isEqualTo(
+ 0x5000);
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().logicalAddress).isEqualTo(
+ ADDR_INVALID);
+ assertThat(mStandby).isFalse();
+ }
+
+ @Test
+ public void handleRoutingChange_sameDevice_None_ActiveSource() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.NONE;
+ mHdmiCecLocalDevicePlayback.setActiveSource(mPlaybackLogicalAddress,
+ mPlaybackPhysicalAddress, "HdmiCecLocalDevicePlaybackTest");
+ mStandby = false;
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x0000,
+ mPlaybackPhysicalAddress);
+ assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().physicalAddress).isEqualTo(
+ mPlaybackPhysicalAddress);
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().logicalAddress).isEqualTo(
+ mPlaybackLogicalAddress);
+ assertThat(mStandby).isFalse();
+ }
+
+ @Test
+ public void handleRoutingChange_sameDevice_None_InactiveSource() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.NONE;
+ mHdmiCecLocalDevicePlayback.setActiveSource(ADDR_TV, 0x0000,
+ "HdmiCecLocalDevicePlaybackTest");
+ mStandby = false;
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x0000,
+ mPlaybackPhysicalAddress);
+ assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().physicalAddress).isEqualTo(
+ mPlaybackPhysicalAddress);
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().logicalAddress).isEqualTo(
+ ADDR_INVALID);
assertThat(mStandby).isFalse();
}
@Test
public void handleRoutingChange_otherDevice_StandbyNow() {
mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
- HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
- mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
+ mHdmiCecLocalDevicePlayback.setActiveSource(mPlaybackLogicalAddress,
+ mPlaybackPhysicalAddress, "HdmiCecLocalDevicePlaybackTest");
mStandby = false;
HdmiCecMessage message =
HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x0000, 0x5000);
assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
assertThat(mStandby).isTrue();
}
@Test
public void handleRoutingChange_otherDevice_StandbyNow_InactiveSource() {
mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
- HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
- mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
+ HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
+ mHdmiCecLocalDevicePlayback.setActiveSource(ADDR_TV, 0x0000,
+ "HdmiCecLocalDevicePlaybackTest");
mStandby = false;
HdmiCecMessage message =
HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x0000, 0x5000);
assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
assertThat(mStandby).isFalse();
}
@Test
public void handleRoutingChange_sameDevice_StandbyNow_ActiveSource() {
mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
- HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
- mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
+ mHdmiCecLocalDevicePlayback.setActiveSource(mPlaybackLogicalAddress,
+ mPlaybackPhysicalAddress, "HdmiCecLocalDevicePlaybackTest");
mStandby = false;
HdmiCecMessage message =
HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x0000,
mPlaybackPhysicalAddress);
assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isTrue();
assertThat(mStandby).isFalse();
}
@Test
public void handleRoutingInformation_otherDevice_None() {
mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
- HdmiProperties.power_state_change_on_active_source_lost_values.NONE;
- mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ HdmiProperties.power_state_change_on_active_source_lost_values.NONE;
+ mHdmiCecLocalDevicePlayback.setActiveSource(mPlaybackLogicalAddress,
+ mPlaybackPhysicalAddress, "HdmiCecLocalDevicePlaybackTest");
+ mStandby = false;
+ HdmiCecMessage message = HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, 0x5000);
+ assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().physicalAddress).isEqualTo(
+ 0x5000);
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().logicalAddress).isEqualTo(
+ ADDR_INVALID);
+ assertThat(mStandby).isFalse();
+ }
+
+ @Test
+ public void handleRoutingInformation_sameDevice_None_ActiveSource() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.NONE;
+ mHdmiCecLocalDevicePlayback.setActiveSource(mPlaybackLogicalAddress,
+ mPlaybackPhysicalAddress, "HdmiCecLocalDevicePlaybackTest");
mStandby = false;
HdmiCecMessage message =
- HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, 0x5000);
+ HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV,
+ mPlaybackPhysicalAddress);
assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().physicalAddress).isEqualTo(
+ mPlaybackPhysicalAddress);
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().logicalAddress).isEqualTo(
+ mPlaybackLogicalAddress);
+ assertThat(mStandby).isFalse();
+ }
+
+ @Test
+ public void handleRoutingInformation_sameDevice_None_InactiveSource() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ HdmiProperties.power_state_change_on_active_source_lost_values.NONE;
+ mHdmiCecLocalDevicePlayback.setActiveSource(ADDR_TV, 0x0000,
+ "HdmiCecLocalDevicePlaybackTest");
+ mStandby = false;
+ HdmiCecMessage message =
+ HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV,
+ mPlaybackPhysicalAddress);
+ assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().physicalAddress).isEqualTo(
+ mPlaybackPhysicalAddress);
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().logicalAddress).isEqualTo(
+ ADDR_INVALID);
assertThat(mStandby).isFalse();
}
@Test
public void handleRoutingInformation_otherDevice_StandbyNow() {
mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
- HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
- mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
+ mHdmiCecLocalDevicePlayback.setActiveSource(mPlaybackLogicalAddress,
+ mPlaybackPhysicalAddress, "HdmiCecLocalDevicePlaybackTest");
mStandby = false;
HdmiCecMessage message =
HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, 0x5000);
assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
assertThat(mStandby).isTrue();
}
@Test
public void handleRoutingInformation_otherDevice_StandbyNow_InactiveSource() {
mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
- HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
- mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
+ HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
+ mHdmiCecLocalDevicePlayback.setActiveSource(ADDR_TV, 0x0000,
+ "HdmiCecLocalDevicePlaybackTest");
mStandby = false;
HdmiCecMessage message =
HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, 0x5000);
assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
assertThat(mStandby).isFalse();
}
@Test
public void handleRoutingInformation_sameDevice_StandbyNow_ActiveSource() {
mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
- HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
- mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
+ mHdmiCecLocalDevicePlayback.setActiveSource(mPlaybackLogicalAddress,
+ mPlaybackPhysicalAddress, "HdmiCecLocalDevicePlaybackTest");
mStandby = false;
HdmiCecMessage message =
HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV,
mPlaybackPhysicalAddress);
assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isTrue();
assertThat(mStandby).isFalse();
}
@@ -430,7 +522,8 @@
mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
HdmiControlManager.SEND_STANDBY_ON_SLEEP_TO_TV);
- mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
+ mHdmiCecLocalDevicePlayback.setActiveSource(ADDR_TV, 0x0000,
+ "HdmiCecLocalDevicePlaybackTest");
mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
mTestLooper.dispatchAll();
@@ -449,7 +542,8 @@
mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST);
- mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
+ mHdmiCecLocalDevicePlayback.setActiveSource(ADDR_TV, 0x0000,
+ "HdmiCecLocalDevicePlaybackTest");
mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
mTestLooper.dispatchAll();
@@ -468,7 +562,8 @@
mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
HdmiControlManager.SEND_STANDBY_ON_SLEEP_NONE);
- mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
+ mHdmiCecLocalDevicePlayback.setActiveSource(ADDR_TV, 0x0000,
+ "HdmiCecLocalDevicePlaybackTest");
mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
mTestLooper.dispatchAll();
@@ -487,7 +582,8 @@
mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
HdmiControlManager.SEND_STANDBY_ON_SLEEP_TO_TV);
- mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ mHdmiCecLocalDevicePlayback.setActiveSource(mPlaybackLogicalAddress,
+ mPlaybackPhysicalAddress, "HdmiCecLocalDevicePlaybackTest");
mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
mTestLooper.dispatchAll();
@@ -506,7 +602,8 @@
mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST);
- mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ mHdmiCecLocalDevicePlayback.setActiveSource(mPlaybackLogicalAddress,
+ mPlaybackPhysicalAddress, "HdmiCecLocalDevicePlaybackTest");
mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
mTestLooper.dispatchAll();
@@ -525,7 +622,8 @@
mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
HdmiControlManager.SEND_STANDBY_ON_SLEEP_NONE);
- mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ mHdmiCecLocalDevicePlayback.setActiveSource(mPlaybackLogicalAddress,
+ mPlaybackPhysicalAddress, "HdmiCecLocalDevicePlaybackTest");
mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
mTestLooper.dispatchAll();
@@ -549,6 +647,11 @@
assertThat(mHdmiCecLocalDevicePlayback.handleActiveSource(message)).isTrue();
mTestLooper.dispatchAll();
assertThat(mStandby).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().physicalAddress).isEqualTo(
+ mPlaybackPhysicalAddress);
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().logicalAddress).isEqualTo(
+ mPlaybackLogicalAddress);
}
@Test
@@ -560,6 +663,11 @@
assertThat(mHdmiCecLocalDevicePlayback.handleActiveSource(message)).isTrue();
mTestLooper.dispatchAll();
assertThat(mStandby).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().physicalAddress).isEqualTo(
+ 0x0000);
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().logicalAddress).isEqualTo(
+ ADDR_TV);
}
@Test
@@ -572,6 +680,7 @@
assertThat(mHdmiCecLocalDevicePlayback.handleActiveSource(message)).isTrue();
mTestLooper.dispatchAll();
assertThat(mStandby).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isTrue();
}
@Test
@@ -583,6 +692,7 @@
assertThat(mHdmiCecLocalDevicePlayback.handleActiveSource(message)).isTrue();
mTestLooper.dispatchAll();
assertThat(mStandby).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
}
@Test
@@ -703,7 +813,7 @@
mPlaybackLogicalAddress, ADDR_TV);
mTestLooper.dispatchAll();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isTrue();
assertThat(mNativeWrapper.getResultMessages()).containsAllOf(pressed, released);
}
@@ -723,7 +833,7 @@
mPlaybackLogicalAddress, ADDR_AUDIO_SYSTEM);
mTestLooper.dispatchAll();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isTrue();
assertThat(mNativeWrapper.getResultMessages()).containsAllOf(pressed, released);
}
@@ -742,7 +852,7 @@
mPlaybackLogicalAddress, ADDR_TV);
mTestLooper.dispatchAll();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
assertThat(mNativeWrapper.getResultMessages()).containsAllOf(pressed, released);
}
@@ -761,7 +871,7 @@
mPlaybackLogicalAddress, ADDR_AUDIO_SYSTEM);
mTestLooper.dispatchAll();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
assertThat(mNativeWrapper.getResultMessages()).containsAllOf(pressed, released);
}
@@ -805,21 +915,28 @@
mHdmiCecLocalDevicePlayback.dispatchMessage(setStreamPath);
mTestLooper.dispatchAll();
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().physicalAddress).isEqualTo(
+ mPlaybackPhysicalAddress);
assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().logicalAddress).isEqualTo(
mHdmiCecLocalDevicePlayback.getDeviceInfo().getLogicalAddress());
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isTrue();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isTrue();
}
@Test
public void handleSetStreamPath_otherDevice_None() {
mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
- HdmiProperties.power_state_change_on_active_source_lost_values.NONE;
- mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ HdmiProperties.power_state_change_on_active_source_lost_values.NONE;
+ mHdmiCecLocalDevicePlayback.setActiveSource(mPlaybackLogicalAddress,
+ mPlaybackPhysicalAddress, "HdmiCecLocalDevicePlaybackTest");
mStandby = false;
HdmiCecMessage message =
HdmiCecMessageBuilder.buildSetStreamPath(ADDR_TV, 0x5000);
assertThat(mHdmiCecLocalDevicePlayback.handleSetStreamPath(message)).isTrue();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().physicalAddress).isEqualTo(
+ 0x5000);
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().logicalAddress).isEqualTo(
+ ADDR_INVALID);
assertThat(mStandby).isFalse();
}
@@ -827,12 +944,13 @@
public void handleSetStreamPath_otherDevice_StandbyNow() {
mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
- mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ mHdmiCecLocalDevicePlayback.setActiveSource(mPlaybackLogicalAddress,
+ mPlaybackPhysicalAddress, "HdmiCecLocalDevicePlaybackTest");
mStandby = false;
HdmiCecMessage message =
HdmiCecMessageBuilder.buildSetStreamPath(ADDR_TV, 0x5000);
assertThat(mHdmiCecLocalDevicePlayback.handleSetStreamPath(message)).isTrue();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
assertThat(mStandby).isTrue();
}
@@ -840,12 +958,13 @@
public void handleSetStreamPath_otherDevice_StandbyNow_InactiveSource() {
mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
HdmiProperties.power_state_change_on_active_source_lost_values.STANDBY_NOW;
- mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
+ mHdmiCecLocalDevicePlayback.setActiveSource(ADDR_TV, 0x0000,
+ "HdmiCecLocalDevicePlaybackTest");
mStandby = false;
HdmiCecMessage message =
HdmiCecMessageBuilder.buildSetStreamPath(ADDR_TV, 0x5000);
assertThat(mHdmiCecLocalDevicePlayback.handleSetStreamPath(message)).isTrue();
- assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isFalse();
+ assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isFalse();
assertThat(mStandby).isFalse();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java
index 7560a34..c4068d3 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceBinderAPITest.java
@@ -138,11 +138,6 @@
mPlaybackDevice = new HdmiCecLocalDevicePlayback(mHdmiControlService) {
@Override
- void setIsActiveSource(boolean on) {
- mIsActiveSource = on;
- }
-
- @Override
protected void wakeUpIfActiveSource() {}
@Override
@@ -186,13 +181,13 @@
}
});
assertEquals(mResult, -1);
- assertThat(mPlaybackDevice.mIsActiveSource).isFalse();
+ assertThat(mPlaybackDevice.isActiveSource()).isFalse();
mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
mTestLooper.dispatchAll();
assertThat(mHdmiControlService.isAddressAllocated()).isTrue();
assertEquals(mResult, HdmiControlManager.RESULT_SUCCESS);
- assertThat(mPlaybackDevice.mIsActiveSource).isTrue();
+ assertThat(mPlaybackDevice.isActiveSource()).isTrue();
}
@Test
@@ -207,6 +202,6 @@
}
});
assertEquals(mResult, HdmiControlManager.RESULT_SUCCESS);
- assertThat(mPlaybackDevice.mIsActiveSource).isTrue();
+ assertThat(mPlaybackDevice.isActiveSource()).isTrue();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 4849dd4..2f48b5e 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -405,82 +405,6 @@
assertThat(callback2.mVolumeControlEnabled).isTrue();
}
- @Test
- public void setActiveSource_localDevice_playback() {
- int physicalAddress = 0x1000;
- mNativeWrapper.setPhysicalAddress(physicalAddress);
-
- mHdmiControlService.setActiveSource(mMyPlaybackDevice.mAddress, physicalAddress,
- "HdmiControlServiceTest");
-
- assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
- mMyPlaybackDevice.mAddress);
- assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(
- physicalAddress);
- assertThat(mMyPlaybackDevice.mIsActiveSource).isTrue();
- assertThat(mMyAudioSystemDevice.mIsActiveSource).isFalse();
- }
-
- @Test
- public void setActiveSource_localDevice_audio() {
- int physicalAddress = 0x1000;
- mNativeWrapper.setPhysicalAddress(physicalAddress);
-
- mHdmiControlService.setActiveSource(mMyAudioSystemDevice.mAddress, physicalAddress,
- "HdmiControlServiceTest");
-
- assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
- mMyAudioSystemDevice.mAddress);
- assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(
- physicalAddress);
- assertThat(mMyPlaybackDevice.mIsActiveSource).isFalse();
- assertThat(mMyAudioSystemDevice.mIsActiveSource).isTrue();
- }
-
- @Test
- public void setActiveSource_remoteDevice() {
- int physicalAddress = 0x1000;
- mNativeWrapper.setPhysicalAddress(physicalAddress);
-
- mHdmiControlService.setActiveSource(Constants.ADDR_TV, 0x0000, "HdmiControlServiceTest");
-
- assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
- Constants.ADDR_TV);
- assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(0x000);
- assertThat(mMyPlaybackDevice.mIsActiveSource).isFalse();
- assertThat(mMyAudioSystemDevice.mIsActiveSource).isFalse();
- }
-
- @Test
- public void setActiveSource_nonCecDevice() {
- int physicalAddress = 0x1000;
- mNativeWrapper.setPhysicalAddress(physicalAddress);
-
- mHdmiControlService.setActiveSource(Constants.ADDR_INVALID, 0x1234,
- "HdmiControlServiceTest");
-
- assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
- Constants.ADDR_INVALID);
- assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(0x1234);
- assertThat(mMyPlaybackDevice.mIsActiveSource).isFalse();
- assertThat(mMyAudioSystemDevice.mIsActiveSource).isFalse();
- }
-
- @Test
- public void setActiveSource_unknown() {
- int physicalAddress = 0x1000;
- mNativeWrapper.setPhysicalAddress(physicalAddress);
-
- mHdmiControlService.setActiveSource(Constants.ADDR_INVALID,
- Constants.INVALID_PHYSICAL_ADDRESS, "HdmiControlServiceTest");
-
- assertThat(mHdmiControlService.getLocalActiveSource().logicalAddress).isEqualTo(
- Constants.ADDR_INVALID);
- assertThat(mHdmiControlService.getLocalActiveSource().physicalAddress).isEqualTo(
- Constants.INVALID_PHYSICAL_ADDRESS);
- assertThat(mMyPlaybackDevice.mIsActiveSource).isFalse();
- assertThat(mMyAudioSystemDevice.mIsActiveSource).isFalse();
- }
private static class VolumeControlFeatureCallback extends
IHdmiCecVolumeControlFeatureListener.Stub {
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
index c734242..6be28d9 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
@@ -150,7 +150,7 @@
@Override
public void setAndBroadcastActiveSourceFromOneDeviceType(
- int sourceAddress, int physicalAddress) {
+ int sourceAddress, int physicalAddress, String caller) {
mBroadcastActiveSource = true;
}
diff --git a/services/tests/servicestests/src/com/android/server/location/LocationRequestStatisticsTest.java b/services/tests/servicestests/src/com/android/server/location/LocationRequestStatisticsTest.java
deleted file mode 100644
index b6b8b82..0000000
--- a/services/tests/servicestests/src/com/android/server/location/LocationRequestStatisticsTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-package com.android.server.location;
-
-import android.os.SystemClock;
-import android.test.AndroidTestCase;
-
-import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
-import com.android.server.location.LocationRequestStatistics.PackageStatistics;
-
-/**
- * Unit tests for {@link LocationRequestStatistics}.
- */
-public class LocationRequestStatisticsTest extends AndroidTestCase {
- private static final String PACKAGE1 = "package1";
- private static final String PACKAGE2 = "package2";
- private static final String FEATURE_ID = "featureId";
- private static final String PROVIDER1 = "provider1";
- private static final String PROVIDER2 = "provider2";
- private static final long INTERVAL1 = 5000;
- private static final long INTERVAL2 = 100000;
-
- private LocationRequestStatistics mStatistics;
- private long mStartElapsedRealtimeMs;
-
- @Override
- public void setUp() {
- mStatistics = new LocationRequestStatistics();
- mStartElapsedRealtimeMs = SystemClock.elapsedRealtime();
- }
-
- /**
- * Tests that adding a single package works correctly.
- */
- public void testSinglePackage() {
- mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER1, INTERVAL1, true);
-
- assertEquals(1, mStatistics.statistics.size());
- PackageProviderKey key = mStatistics.statistics.keySet().iterator().next();
- assertEquals(PACKAGE1, key.mPackageName);
- assertEquals(PROVIDER1, key.mProviderName);
- assertEquals(FEATURE_ID, key.mFeatureId);
- PackageStatistics stats = mStatistics.statistics.values().iterator().next();
- verifyStatisticsTimes(stats);
- assertEquals(INTERVAL1, stats.getFastestIntervalMs());
- assertEquals(INTERVAL1, stats.getSlowestIntervalMs());
- assertTrue(stats.isActive());
- }
-
- /**
- * Tests that adding a single package works correctly when it is stopped and restarted.
- */
- public void testSinglePackage_stopAndRestart() {
- mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER1, INTERVAL1, true);
- mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER1);
- mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER1, INTERVAL1, true);
-
- assertEquals(1, mStatistics.statistics.size());
- PackageProviderKey key = mStatistics.statistics.keySet().iterator().next();
- assertEquals(PACKAGE1, key.mPackageName);
- assertEquals(FEATURE_ID, key.mFeatureId);
- assertEquals(PROVIDER1, key.mProviderName);
- PackageStatistics stats = mStatistics.statistics.values().iterator().next();
- verifyStatisticsTimes(stats);
- assertEquals(INTERVAL1, stats.getFastestIntervalMs());
- assertEquals(INTERVAL1, stats.getSlowestIntervalMs());
- assertTrue(stats.isActive());
-
- mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER1);
- assertFalse(stats.isActive());
- }
-
- /**
- * Tests that adding a single package works correctly when multiple intervals are used.
- */
- public void testSinglePackage_multipleIntervals() {
- mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER1, INTERVAL1, true);
- mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER1, INTERVAL2, true);
-
- assertEquals(1, mStatistics.statistics.size());
- PackageProviderKey key = mStatistics.statistics.keySet().iterator().next();
- assertEquals(PACKAGE1, key.mPackageName);
- assertEquals(PROVIDER1, key.mProviderName);
- assertEquals(FEATURE_ID, key.mFeatureId);
- PackageStatistics stats = mStatistics.statistics.values().iterator().next();
- verifyStatisticsTimes(stats);
- assertEquals(INTERVAL1, stats.getFastestIntervalMs());
- assertTrue(stats.isActive());
-
- mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER1);
- assertTrue(stats.isActive());
- mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER1);
- assertFalse(stats.isActive());
- }
-
- /**
- * Tests that adding a single package works correctly when multiple providers are used.
- */
- public void testSinglePackage_multipleProviders() {
- mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER1, INTERVAL1, true);
- mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER2, INTERVAL2, true);
-
- assertEquals(2, mStatistics.statistics.size());
- PackageProviderKey key1 = new PackageProviderKey(PACKAGE1, FEATURE_ID, PROVIDER1);
- PackageStatistics stats1 = mStatistics.statistics.get(key1);
- verifyStatisticsTimes(stats1);
- assertEquals(INTERVAL1, stats1.getSlowestIntervalMs());
- assertEquals(INTERVAL1, stats1.getFastestIntervalMs());
- assertTrue(stats1.isActive());
- PackageProviderKey key2 = new PackageProviderKey(PACKAGE1, FEATURE_ID, PROVIDER2);
- PackageStatistics stats2 = mStatistics.statistics.get(key2);
- verifyStatisticsTimes(stats2);
- assertEquals(INTERVAL2, stats2.getSlowestIntervalMs());
- assertEquals(INTERVAL2, stats2.getFastestIntervalMs());
- assertTrue(stats2.isActive());
-
- mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER1);
- assertFalse(stats1.isActive());
- assertTrue(stats2.isActive());
- mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER2);
- assertFalse(stats1.isActive());
- assertFalse(stats2.isActive());
- }
-
- /**
- * Tests that adding multiple packages works correctly.
- */
- public void testMultiplePackages() {
- mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER1, INTERVAL1, true);
- mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER2, INTERVAL1, true);
- mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER2, INTERVAL2, true);
- mStatistics.startRequesting(PACKAGE2, FEATURE_ID, PROVIDER1, INTERVAL1, true);
-
- assertEquals(3, mStatistics.statistics.size());
- PackageProviderKey key1 = new PackageProviderKey(PACKAGE1, FEATURE_ID, PROVIDER1);
- PackageStatistics stats1 = mStatistics.statistics.get(key1);
- verifyStatisticsTimes(stats1);
- assertEquals(INTERVAL1, stats1.getSlowestIntervalMs());
- assertEquals(INTERVAL1, stats1.getFastestIntervalMs());
- assertTrue(stats1.isActive());
-
- PackageProviderKey key2 = new PackageProviderKey(PACKAGE1, FEATURE_ID, PROVIDER2);
- PackageStatistics stats2 = mStatistics.statistics.get(key2);
- verifyStatisticsTimes(stats2);
- assertEquals(INTERVAL2, stats2.getSlowestIntervalMs());
- assertEquals(INTERVAL1, stats2.getFastestIntervalMs());
- assertTrue(stats2.isActive());
-
- PackageProviderKey key3 = new PackageProviderKey(PACKAGE2, FEATURE_ID, PROVIDER1);
- PackageStatistics stats3 = mStatistics.statistics.get(key3);
- verifyStatisticsTimes(stats3);
- assertEquals(INTERVAL1, stats3.getSlowestIntervalMs());
- assertEquals(INTERVAL1, stats3.getFastestIntervalMs());
- assertTrue(stats3.isActive());
-
- mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER1);
- assertFalse(stats1.isActive());
- assertTrue(stats2.isActive());
- assertTrue(stats3.isActive());
-
- mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER2);
- assertFalse(stats1.isActive());
- assertTrue(stats2.isActive());
- assertTrue(stats3.isActive());
- mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER2);
- assertFalse(stats2.isActive());
-
- mStatistics.stopRequesting(PACKAGE2, FEATURE_ID, PROVIDER1);
- assertFalse(stats1.isActive());
- assertFalse(stats2.isActive());
- assertFalse(stats3.isActive());
- }
-
- /**
- * Tests that switching foreground & background states accmulates time reasonably.
- */
- public void testForegroundBackground() {
- mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER1, INTERVAL1, true);
- mStatistics.startRequesting(PACKAGE1, FEATURE_ID, PROVIDER2, INTERVAL1, true);
- mStatistics.startRequesting(PACKAGE2, FEATURE_ID, PROVIDER1, INTERVAL1, false);
-
- mStatistics.updateForeground(PACKAGE1, FEATURE_ID, PROVIDER2, false);
- mStatistics.updateForeground(PACKAGE2, FEATURE_ID, PROVIDER1, true);
-
- mStatistics.stopRequesting(PACKAGE1, FEATURE_ID, PROVIDER1);
-
- for (PackageStatistics stats : mStatistics.statistics.values()) {
- verifyStatisticsTimes(stats);
- }
- }
-
- private void verifyStatisticsTimes(PackageStatistics stats) {
- long durationMs = stats.getDurationMs();
- long foregroundDurationMs = stats.getForegroundDurationMs();
- long timeSinceFirstRequestMs = stats.getTimeSinceFirstRequestMs();
- long maxDeltaMs = SystemClock.elapsedRealtime() - mStartElapsedRealtimeMs;
- assertTrue("Duration is too small", durationMs >= 0);
- assertTrue("Duration is too large", durationMs <= maxDeltaMs);
- assertTrue("Foreground Duration is too small", foregroundDurationMs >= 0);
- assertTrue("Foreground Duration is too large", foregroundDurationMs <= maxDeltaMs);
- assertTrue("Time since first request is too large", timeSinceFirstRequestMs <= maxDeltaMs);
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java b/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java
index 9ee9259..292b7c6 100644
--- a/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java
@@ -77,6 +77,7 @@
private TestThreadingDomain mTestThreadingDomain;
private TestCallback mTestCallback;
private TestLocationTimeZoneProvider mTestPrimaryLocationTimeZoneProvider;
+ private TestLocationTimeZoneProvider mTestSecondaryLocationTimeZoneProvider;
@Before
public void setUp() {
@@ -87,26 +88,30 @@
mTestCallback = new TestCallback(mTestThreadingDomain);
mTestPrimaryLocationTimeZoneProvider =
new TestLocationTimeZoneProvider(mTestThreadingDomain, "primary");
+ mTestSecondaryLocationTimeZoneProvider =
+ new TestLocationTimeZoneProvider(mTestThreadingDomain, "secondary");
}
@Test
public void initialState_enabled() {
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider);
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
Duration expectedInitTimeout = testEnvironment.getProviderInitializationTimeout()
.plus(testEnvironment.getProviderInitializationTimeoutFuzz());
- // Initialize. After initialization the provider must be initialized and should be
+ // Initialize. After initialization the providers must be initialized and one should be
// enabled.
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
+ mTestSecondaryLocationTimeZoneProvider.assertInitialized();
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestPrimaryLocationTimeZoneProvider.assertInitializationTimeoutSet(expectedInitTimeout);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -114,17 +119,19 @@
@Test
public void initialState_disabled() {
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider);
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_DISABLED);
- // Initialize. After initialization the provider must be initialized but should not be
+ // Initialize. After initialization the providers must be initialized but neither should be
// enabled.
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
+ mTestSecondaryLocationTimeZoneProvider.assertInitialized();
mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -132,7 +139,7 @@
@Test
public void enabled_uncertaintySuggestionSentIfNoEventReceived() {
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider);
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
@@ -141,6 +148,7 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -148,9 +156,24 @@
mTestThreadingDomain.executeNext();
// The primary should have reported uncertainty, which should trigger the controller to
- // start the uncertainty timeout.
+ // start the uncertainty timeout and enable the secondary.
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertNoSuggestionMade();
+ assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+
+ // Simulate time passing with no provider event being received from either the primary or
+ // secondary.
+ mTestThreadingDomain.executeNext();
+
+ // Now both initialization timeouts should have triggered. The uncertainty timeout should
+ // still not be triggered.
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
@@ -160,6 +183,8 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertUncertainSuggestionMadeAndCommit();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -167,7 +192,7 @@
@Test
public void enabled_eventReceivedBeforeInitializationTimeout() {
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider);
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
@@ -176,6 +201,7 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -186,6 +212,7 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -194,7 +221,7 @@
@Test
public void enabled_eventReceivedFromPrimaryAfterInitializationTimeout() {
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider);
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
@@ -203,6 +230,7 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -211,16 +239,59 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
// Simulate a location event being received from the primary provider. This should cause a
- // suggestion to be made.
+ // suggestion to be made and the secondary to be shut down.
mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestCallback.assertSuggestionMadeAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ }
+
+ @Test
+ public void enabled_eventReceivedFromSecondaryAfterInitializationTimeout() {
+ ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ TestEnvironment testEnvironment = new TestEnvironment(
+ mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+
+ // Initialize and check initial state.
+ controllerImpl.initialize(testEnvironment, mTestCallback);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestCallback.assertNoSuggestionMade();
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+
+ // Simulate time passing with no provider event being received from the primary.
+ mTestThreadingDomain.executeNext();
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertNoSuggestionMade();
+ assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+
+ // Simulate a location event being received from the secondary provider. This should cause a
+ // suggestion to be made.
+ mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertSuggestionMadeAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -229,7 +300,7 @@
@Test
public void enabled_repeatedPrimaryCertainty() {
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider);
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
@@ -238,6 +309,7 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -248,6 +320,7 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -258,6 +331,7 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -267,15 +341,16 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@Test
- public void enabled_uncertaintyTriggersASuggestionAfterUncertaintyTimeout() {
+ public void enabled_repeatedSecondaryCertainty() {
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider);
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
@@ -284,6 +359,70 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestCallback.assertNoSuggestionMade();
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+
+ // Simulate time passing with no provider event being received from the primary.
+ mTestThreadingDomain.executeNext();
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertNoSuggestionMade();
+ assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+
+ // Simulate a location event being received from the secondary provider. This should cause a
+ // suggestion to be made.
+ mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertSuggestionMadeAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+
+ // A second, identical event should not cause another suggestion.
+ mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertNoSuggestionMade();
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+
+ // And a third, different event should cause another suggestion.
+ mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertSuggestionMadeAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ }
+
+ @Test
+ public void enabled_uncertaintyTriggersASuggestionAfterUncertaintyTimeout() {
+ ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ TestEnvironment testEnvironment = new TestEnvironment(
+ mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+
+ // Initialize and check initial state.
+ controllerImpl.initialize(testEnvironment, mTestCallback);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -294,18 +433,48 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate an uncertain event being received from the primary provider. This should not
// cause a suggestion to be made straight away, but the uncertainty timeout should be
- // started.
+ // started and the secondary should be enabled.
mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertNoSuggestionMade();
+ assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+
+ // Simulate a location event being received from the secondary provider. This should cause a
+ // suggestion to be made, cancel the uncertainty timeout and ensure the secondary is
+ // considered initialized.
+ mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertSuggestionMadeAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+
+ // Simulate an uncertain event being received from the secondary provider. This should not
+ // cause a suggestion to be made straight away, but the uncertainty timeout should be
+ // started. Both providers are now enabled, with no initialization timeout set.
+ mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
@@ -315,6 +484,8 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertUncertainSuggestionMadeAndCommit();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -322,7 +493,7 @@
@Test
public void enabled_briefUncertaintyTriggersNoSuggestion() {
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider);
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
@@ -331,6 +502,7 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -341,27 +513,32 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Uncertainty should not cause a suggestion to be made straight away, but the uncertainty
- // timeout should be started.
+ // timeout should be started and the secondary should be enabled.
mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
// And a success event from the primary provider should cause the controller to make another
- // suggestion, the uncertainty timeout should be cancelled.
+ // suggestion, the uncertainty timeout should be cancelled and the secondary should be
+ // disabled again.
mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -370,7 +547,7 @@
@Test
public void configChanges_enableAndDisableWithNoPreviousSuggestion() {
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider);
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_DISABLED);
@@ -378,6 +555,7 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -386,6 +564,7 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -393,6 +572,7 @@
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -400,7 +580,7 @@
@Test
public void configChanges_enableAndDisableWithPreviousSuggestion() {
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider);
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_DISABLED);
@@ -408,6 +588,7 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -416,6 +597,7 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -425,6 +607,7 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -436,6 +619,7 @@
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertUncertainSuggestionMadeAndCommit();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -443,7 +627,7 @@
@Test
public void configChanges_userSwitch_enabledToEnabled() {
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider);
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
@@ -452,6 +636,7 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -463,6 +648,7 @@
// and also clear the scheduled uncertainty suggestion.
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -477,13 +663,14 @@
mTestPrimaryLocationTimeZoneProvider.assertStateChangesAndCommit(expectedStateTransitions);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfig(
PROVIDER_STATE_ENABLED_INITIALIZING, USER2_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@Test
- public void primaryPermFailure_disableAndEnable() {
+ public void primaryPermFailure_secondaryEventsReceived() {
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
- mTestPrimaryLocationTimeZoneProvider);
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
@@ -492,22 +679,86 @@
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate a failure location event being received from the primary provider. This should
- // cause an uncertain suggestion to be made.
+ // cause the secondary to be enabled.
mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
- mTestCallback.assertUncertainSuggestionMadeAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertNoSuggestionMade();
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+
+ // Simulate uncertainty from the secondary.
+ mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+
+ mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertNoSuggestionMade();
+ assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+
+ // And a success event from the secondary provider should cause the controller to make
+ // another suggestion, the uncertainty timeout should be cancelled.
+ mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
+
+ mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertSuggestionMadeAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+
+ // Simulate uncertainty from the secondary.
+ mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+
+ mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertNoSuggestionMade();
+ assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ }
+
+ @Test
+ public void primaryPermFailure_disableAndEnable() {
+ ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ TestEnvironment testEnvironment = new TestEnvironment(
+ mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+
+ // Initialize and check initial state.
+ controllerImpl.initialize(testEnvironment, mTestCallback);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestCallback.assertNoSuggestionMade();
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+
+ // Simulate a failure location event being received from the primary provider. This should
+ // cause the secondary to be enabled.
+ mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
+
+ mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is disabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -515,6 +766,164 @@
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertNoSuggestionMade();
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ }
+
+ @Test
+ public void secondaryPermFailure_primaryEventsReceived() {
+ ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ TestEnvironment testEnvironment = new TestEnvironment(
+ mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+
+ // Initialize and check initial state.
+ controllerImpl.initialize(testEnvironment, mTestCallback);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestCallback.assertNoSuggestionMade();
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+
+ // Simulate an uncertain event from the primary. This will enable the secondary, which will
+ // give this test the opportunity to simulate its failure. Then it will be possible to
+ // demonstrate controller behavior with only the primary working.
+ mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertNoSuggestionMade();
+ assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+
+ // Simulate failure event from the secondary. This should just affect the secondary's state.
+ mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestCallback.assertNoSuggestionMade();
+ assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+
+ // And a success event from the primary provider should cause the controller to make
+ // a suggestion, the uncertainty timeout should be cancelled.
+ mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestCallback.assertSuggestionMadeAndCommit(
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+
+ // Simulate uncertainty from the primary. The secondary cannot be enabled.
+ mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestCallback.assertNoSuggestionMade();
+ assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+ }
+
+ @Test
+ public void secondaryPermFailure_disableAndEnable() {
+ ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ TestEnvironment testEnvironment = new TestEnvironment(
+ mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+
+ // Initialize and check initial state.
+ controllerImpl.initialize(testEnvironment, mTestCallback);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestCallback.assertNoSuggestionMade();
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+
+ // Simulate an uncertain event from the primary. This will enable the secondary, which will
+ // give this test the opportunity to simulate its failure. Then it will be possible to
+ // demonstrate controller behavior with only the primary working.
+ mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertNoSuggestionMade();
+ assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+
+ // Simulate failure event from the secondary. This should just affect the secondary's state.
+ mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestCallback.assertNoSuggestionMade();
+ assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+
+ // Now signal a config change so that geo detection is disabled.
+ testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
+
+ mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestCallback.assertNoSuggestionMade();
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+
+ // Now signal a config change so that geo detection is enabled. Only the primary can be
+ // enabled.
+ testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestCallback.assertNoSuggestionMade();
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+ }
+
+ @Test
+ public void bothPermFailure_disableAndEnable() {
+ ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
+ mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+ TestEnvironment testEnvironment = new TestEnvironment(
+ mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+
+ // Initialize and check initial state.
+ controllerImpl.initialize(testEnvironment, mTestCallback);
+
+ mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestCallback.assertNoSuggestionMade();
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+
+ // Simulate a failure event from the primary. This will enable the secondary.
+ mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
+
+ mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
+ PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestCallback.assertNoSuggestionMade();
+ assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+
+ // Simulate failure event from the secondary.
+ mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
+
+ mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertUncertainSuggestionMadeAndCommit();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java b/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java
new file mode 100644
index 0000000..62e135b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.pm.IDataLoaderStatusListener;
+import android.content.pm.PackageManager;
+import android.os.ConditionVariable;
+import android.os.incremental.IStorageHealthListener;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Unit tests for {@link IncrementalStates}.
+ * Run with: atest -c FrameworksServicesTests:com.android.server.pm.IncrementalStatesTest
+ */
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class IncrementalStatesTest {
+ private IncrementalStates mIncrementalStates;
+ private ConditionVariable mUnstartableCalled = new ConditionVariable();
+ private ConditionVariable mStartableCalled = new ConditionVariable();
+ private ConditionVariable mFullyLoadedCalled = new ConditionVariable();
+ private AtomicInteger mUnstartableReason = new AtomicInteger(0);
+ private static final int WAIT_TIMEOUT_MILLIS = 1000; /* 1 second */
+ private IncrementalStates.Callback mCallback = new IncrementalStates.Callback() {
+ @Override
+ public void onPackageUnstartable(int reason) {
+ mUnstartableCalled.open();
+ mUnstartableReason.set(reason);
+ }
+
+ @Override
+ public void onPackageStartable() {
+ mStartableCalled.open();
+ }
+
+ @Override
+ public void onPackageFullyLoaded() {
+ mFullyLoadedCalled.open();
+ }
+ };
+
+ /**
+ * Setup the tests as if the package has just been committed.
+ * By default the package is now startable and is loading.
+ */
+ @Before
+ public void setUp() {
+ mIncrementalStates = new IncrementalStates();
+ assertFalse(mIncrementalStates.isStartable());
+ mIncrementalStates.setCallback(mCallback);
+ mIncrementalStates.onCommit(true);
+ // Test that package is now startable and loading
+ assertTrue(mStartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertTrue(mIncrementalStates.isStartable());
+ assertTrue(mIncrementalStates.isLoading());
+ mStartableCalled.close();
+ mUnstartableCalled.close();
+ mFullyLoadedCalled.close();
+ }
+
+ /**
+ * Test that startable state changes to false when Incremental Storage is unhealthy.
+ */
+ @Test
+ public void testStartableTransition_IncrementalStorageUnhealthy() {
+ mIncrementalStates.onStorageHealthStatusChanged(
+ IStorageHealthListener.HEALTH_STATUS_UNHEALTHY);
+ // Test that package is now unstartable
+ assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertFalse(mIncrementalStates.isStartable());
+ assertEquals(PackageManager.UNSTARTABLE_REASON_UNKNOWN, mUnstartableReason.get());
+ }
+
+ /**
+ * Test that the package is still startable when Incremental Storage has pending reads.
+ */
+ @Test
+ public void testStartableTransition_IncrementalStorageReadsPending()
+ throws InterruptedException {
+ mIncrementalStates.onStorageHealthStatusChanged(
+ IStorageHealthListener.HEALTH_STATUS_READS_PENDING);
+ // Test that package is still startable
+ assertFalse(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertTrue(mIncrementalStates.isStartable());
+ }
+
+ /**
+ * Test that the package is still startable when Incremental Storage is at blocked status.
+ */
+ @Test
+ public void testStartableTransition_IncrementalStorageBlocked() {
+ mIncrementalStates.onStorageHealthStatusChanged(
+ IStorageHealthListener.HEALTH_STATUS_BLOCKED);
+ // Test that package is still startable
+ assertFalse(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertTrue(mIncrementalStates.isStartable());
+ }
+
+ /**
+ * Test that the package is still startable when Data Loader has unknown transportation issues.
+ */
+ @Test
+ public void testStartableTransition_DataLoaderTransportError() {
+ mIncrementalStates.onStreamStatusChanged(
+ IDataLoaderStatusListener.STREAM_TRANSPORT_ERROR);
+ // Test that package is still startable
+ assertFalse(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertTrue(mIncrementalStates.isStartable());
+ }
+
+ /**
+ * Test that the package becomes unstartable when Data Loader has data integrity issues.
+ */
+ @Test
+ public void testStartableTransition_DataLoaderIntegrityError() {
+ mIncrementalStates.onStreamStatusChanged(
+ IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR);
+ // Test that package is now unstartable
+ assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertFalse(mIncrementalStates.isStartable());
+ assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT,
+ mUnstartableReason.get());
+ }
+
+ /**
+ * Test that the package becomes unstartable when Data Loader has data source issues.
+ */
+ @Test
+ public void testStartableTransition_DataLoaderSourceError() {
+ mIncrementalStates.onStreamStatusChanged(
+ IDataLoaderStatusListener.STREAM_SOURCE_ERROR);
+ // Test that package is now unstartable
+ assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertFalse(mIncrementalStates.isStartable());
+ assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT,
+ mUnstartableReason.get());
+ }
+
+ /**
+ * Test that the package becomes unstartable when Data Loader hits limited storage while
+ * Incremental storage has a pending reads.
+ */
+ @Test
+ public void testStartableTransition_DataLoaderStorageErrorWhenIncrementalStoragePending()
+ throws InterruptedException {
+ mIncrementalStates.onStreamStatusChanged(
+ IDataLoaderStatusListener.STREAM_STORAGE_ERROR);
+ // Test that package is still startable
+ assertFalse(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertTrue(mIncrementalStates.isStartable());
+ mIncrementalStates.onStorageHealthStatusChanged(
+ IStorageHealthListener.HEALTH_STATUS_READS_PENDING);
+ // Test that package is now unstartable
+ assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertFalse(mIncrementalStates.isStartable());
+ assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE,
+ mUnstartableReason.get());
+ }
+
+ /**
+ * Test that the package becomes unstartable when Data Loader hits limited storage while
+ * Incremental storage is at blocked status.
+ */
+ @Test
+ public void testStartableTransition_DataLoaderStorageErrorWhenIncrementalStorageBlocked()
+ throws InterruptedException {
+ mIncrementalStates.onStreamStatusChanged(
+ IDataLoaderStatusListener.STREAM_STORAGE_ERROR);
+ // Test that package is still startable
+ assertFalse(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertTrue(mIncrementalStates.isStartable());
+ mIncrementalStates.onStorageHealthStatusChanged(
+ IStorageHealthListener.HEALTH_STATUS_BLOCKED);
+ // Test that package is now unstartable
+ assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertFalse(mIncrementalStates.isStartable());
+ assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE,
+ mUnstartableReason.get());
+ }
+
+ /**
+ * Test that the package becomes unstartable when Incremental Storage is unhealthy, and it
+ * becomes startable again when Incremental Storage is healthy again.
+ */
+ @Test
+ public void testStartableTransition_IncrementalStorageUnhealthyBackToHealthy()
+ throws InterruptedException {
+ mIncrementalStates.onStorageHealthStatusChanged(
+ IStorageHealthListener.HEALTH_STATUS_UNHEALTHY);
+ // Test that package is unstartable
+ assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertFalse(mIncrementalStates.isStartable());
+
+ mIncrementalStates.onStorageHealthStatusChanged(
+ IStorageHealthListener.HEALTH_STATUS_OK);
+ // Test that package is now startable
+ assertTrue(mStartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertTrue(mIncrementalStates.isStartable());
+ }
+
+ /**
+ * Test that the package becomes unstartable when Data Loader has data integrity issue, and it
+ * becomes startable again when Data Loader is healthy again.
+ */
+ @Test
+ public void testStartableTransition_DataLoaderUnhealthyBackToHealthy()
+ throws InterruptedException {
+ mIncrementalStates.onStreamStatusChanged(IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR);
+ // Test that package is unstartable
+ assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertFalse(mIncrementalStates.isStartable());
+
+ mIncrementalStates.onStreamStatusChanged(IDataLoaderStatusListener.STREAM_HEALTHY);
+ // Test that package is now startable
+ assertTrue(mStartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertTrue(mIncrementalStates.isStartable());
+ }
+
+ /**
+ * Test that the package becomes unstartable when both Incremental Storage and Data Loader
+ * are unhealthy, and it becomes startable again when both Incremental Storage and Data Loader
+ * are healthy again.
+ */
+ @Test
+ public void testStartableTransition_DataLoaderAndIncrementalStorageUnhealthyBackToHealthy()
+ throws InterruptedException {
+ mIncrementalStates.onStorageHealthStatusChanged(
+ IStorageHealthListener.HEALTH_STATUS_UNHEALTHY);
+ mIncrementalStates.onStreamStatusChanged(IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR);
+ // Test that package is unstartable
+ assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertFalse(mIncrementalStates.isStartable());
+
+ mIncrementalStates.onStreamStatusChanged(IDataLoaderStatusListener.STREAM_HEALTHY);
+ // Test that package is still unstartable
+ assertFalse(mStartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertFalse(mIncrementalStates.isStartable());
+ mIncrementalStates.onStorageHealthStatusChanged(IStorageHealthListener.HEALTH_STATUS_OK);
+ // Test that package is now startable
+ assertTrue(mStartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertTrue(mIncrementalStates.isStartable());
+ }
+
+ /**
+ * Test that when loading progress is 1, the package becomes fully loaded, and the change of
+ * Incremental Storage health status does not affect the startable state.
+ */
+ @Test
+ public void testStartableTransition_HealthStatusChangeWhenFullyLoaded()
+ throws InterruptedException {
+ mIncrementalStates.setProgress(1.0f);
+ // Test that package is now fully loaded
+ assertTrue(mFullyLoadedCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertFalse(mIncrementalStates.isLoading());
+ mIncrementalStates.onStorageHealthStatusChanged(
+ IStorageHealthListener.HEALTH_STATUS_UNHEALTHY);
+ // Test that package is still startable
+ assertFalse(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertTrue(mIncrementalStates.isStartable());
+ }
+
+ /**
+ * Test that when loading progress is 1, the package becomes fully loaded, and if the package
+ * was unstartable, it becomes startable.
+ */
+ @Test
+ public void testLoadingTransition_FullyLoadedWhenUnstartable() throws InterruptedException {
+ mIncrementalStates.onStorageHealthStatusChanged(
+ IStorageHealthListener.HEALTH_STATUS_UNHEALTHY);
+ // Test that package is unstartable
+ assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertFalse(mIncrementalStates.isStartable());
+ // Test that package is still loading
+ assertTrue(mIncrementalStates.isLoading());
+
+ mIncrementalStates.setProgress(0.5f);
+ // Test that package is still unstartable
+ assertFalse(mStartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertFalse(mIncrementalStates.isStartable());
+ mIncrementalStates.setProgress(1.0f);
+ // Test that package is now startable
+ assertTrue(mStartableCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertTrue(mIncrementalStates.isStartable());
+ // Test that package is now fully loaded
+ assertTrue(mFullyLoadedCalled.block(WAIT_TIMEOUT_MILLIS));
+ assertFalse(mIncrementalStates.isLoading());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index bc74783..6255630 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -891,8 +891,10 @@
assertNotSame(origPkgSetting.mimeGroups, testPkgSetting.mimeGroups);
}
assertThat(origPkgSetting.mimeGroups, is(testPkgSetting.mimeGroups));
- assertNotSame(origPkgSetting.mPermissionsState, testPkgSetting.mPermissionsState);
- assertThat(origPkgSetting.mPermissionsState, is(testPkgSetting.mPermissionsState));
+ assertNotSame(origPkgSetting.mLegacyPermissionsState,
+ testPkgSetting.mLegacyPermissionsState);
+ assertThat(origPkgSetting.mLegacyPermissionsState,
+ is(testPkgSetting.mLegacyPermissionsState));
assertThat(origPkgSetting.name, is(testPkgSetting.name));
// mOldCodePaths is _not_ copied
// assertNotSame(origPkgSetting.mOldCodePaths, testPkgSetting.mOldCodePaths);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java
new file mode 100644
index 0000000..9a668b9
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
+
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for the {@link DisplayAreaGroup} container.
+ *
+ * Build/Install/Run:
+ * atest WmTests:DisplayAreaGroupTest
+ */
+@SmallTest
+@Presubmit
+@RunWith(WindowTestRunner.class)
+public class DisplayAreaGroupTest extends WindowTestsBase {
+
+ private DisplayAreaGroup mDisplayAreaGroup;
+ private TaskDisplayArea mTaskDisplayArea;
+ private Task mStack;
+ private ActivityRecord mActivity;
+
+ @Before
+ public void setUp() {
+ mDisplayAreaGroup = new DisplayAreaGroup(
+ mWm, "DisplayAreaGroup", FEATURE_VENDOR_FIRST);
+ final TaskDisplayArea defaultTda = mDisplayContent.getDefaultTaskDisplayArea();
+ final WindowContainer parentDA = defaultTda.getParent();
+ parentDA.addChild(mDisplayAreaGroup, parentDA.mChildren.indexOf(defaultTda) + 1);
+ mTaskDisplayArea = new TaskDisplayArea(
+ mDisplayContent, mWm, "TDA1", FEATURE_VENDOR_FIRST + 1);
+ mDisplayAreaGroup.addChild(mTaskDisplayArea, POSITION_TOP);
+ mStack = mTaskDisplayArea.createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ mActivity = new ActivityBuilder(mAtm).setCreateTask(true).setStack(mStack).build();
+ mDisplayContent.setLastFocusedTaskDisplayArea(mTaskDisplayArea);
+ }
+
+ @Test
+ public void testIsOrientationDifferentFromDisplay() {
+ // Display is portrait, DisplayAreaGroup inherits that
+ mDisplayContent.setBounds(0, 0, 600, 900);
+
+ assertThat(mDisplayAreaGroup.isOrientationDifferentFromDisplay()).isFalse();
+
+ // DisplayAreaGroup is landscape, different Display
+ mDisplayAreaGroup.setBounds(0, 0, 600, 450);
+
+ assertThat(mDisplayAreaGroup.isOrientationDifferentFromDisplay()).isTrue();
+
+ // DisplayAreaGroup is portrait, same as Display
+ mDisplayAreaGroup.setBounds(0, 0, 300, 900);
+
+ assertThat(mDisplayAreaGroup.isOrientationDifferentFromDisplay()).isFalse();
+ }
+
+ @Test
+ public void testGetOrientation() {
+ doReturn(true).when(mDisplayContent).onDescendantOrientationChanged(any(), any());
+ mActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
+
+ // Display is portrait, DisplayAreaGroup inherits that
+ mDisplayContent.setBounds(0, 0, 600, 900);
+
+ assertThat(mDisplayAreaGroup.getOrientation()).isEqualTo(SCREEN_ORIENTATION_PORTRAIT);
+ assertThat(mActivity.getRequestedConfigurationOrientation())
+ .isEqualTo(ORIENTATION_PORTRAIT);
+
+ // DisplayAreaGroup is landscape, different from Display
+ mDisplayAreaGroup.setBounds(0, 0, 600, 450);
+
+ assertThat(mDisplayAreaGroup.getOrientation()).isEqualTo(SCREEN_ORIENTATION_LANDSCAPE);
+ assertThat(mActivity.getRequestedConfigurationOrientation())
+ .isEqualTo(ORIENTATION_LANDSCAPE);
+
+ // DisplayAreaGroup is portrait, same as Display
+ mDisplayAreaGroup.setBounds(0, 0, 300, 900);
+
+ assertThat(mDisplayAreaGroup.getOrientation()).isEqualTo(SCREEN_ORIENTATION_PORTRAIT);
+ assertThat(mActivity.getRequestedConfigurationOrientation())
+ .isEqualTo(ORIENTATION_PORTRAIT);
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
index 820eca4..bc7516f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.view.Display.INVALID_DISPLAY;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
@@ -319,6 +320,29 @@
}
/**
+ * Ensures that {@link LaunchParamsModifier} doesn't alter non-root tasks' windowingMode.
+ */
+ @Test
+ public void testLayoutNonRootTaskWindowingModeChange() {
+ final LaunchParams params = new LaunchParams();
+ final int windowingMode = WINDOWING_MODE_FREEFORM;
+ params.mWindowingMode = windowingMode;
+ final InstrumentedPositioner positioner = new InstrumentedPositioner(RESULT_DONE, params);
+ final Task task = new TaskBuilder(mAtm.mStackSupervisor).setCreateParentTask(true).build();
+ task.getRootTask().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+
+ mController.registerModifier(positioner);
+
+ final int beforeWindowMode = task.getWindowingMode();
+ assertNotEquals(windowingMode, beforeWindowMode);
+
+ mController.layoutTask(task, null /* windowLayout */);
+
+ final int afterWindowMode = task.getWindowingMode();
+ assertEquals(afterWindowMode, beforeWindowMode);
+ }
+
+ /**
* Ensures that {@link LaunchParamsModifier} requests specifying bounds during
* layout are honored if window is in freeform.
*/
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index f4f172d..7a30c37 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -1188,7 +1188,7 @@
() -> mAtm.unregisterTaskStackListener(null));
assertSecurityException(expectCallable, () -> mAtm.getTaskDescription(0));
assertSecurityException(expectCallable, () -> mAtm.cancelTaskWindowTransition(0));
- assertSecurityException(expectCallable, () -> mAtm.startRecentsActivity(null, null,
+ assertSecurityException(expectCallable, () -> mAtm.startRecentsActivity(null, 0,
null));
assertSecurityException(expectCallable, () -> mAtm.cancelRecentsAnimation(true));
assertSecurityException(expectCallable, () -> mAtm.stopAppSwitches());
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index d821d38..c10d4fa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -147,7 +147,7 @@
Intent recentsIntent = new Intent().setComponent(mRecentsComponent);
// Null animation indicates to preload.
- mAtm.startRecentsActivity(recentsIntent, null /* assistDataReceiver */,
+ mAtm.startRecentsActivity(recentsIntent, 0 /* eventTime */,
null /* recentsAnimationRunner */);
Task recentsStack = defaultTaskDisplayArea.getStack(WINDOWING_MODE_FULLSCREEN,
@@ -167,7 +167,7 @@
spyOn(recentsActivity);
// Start when the recents activity exists. It should ensure the configuration.
- mAtm.startRecentsActivity(recentsIntent, null /* assistDataReceiver */,
+ mAtm.startRecentsActivity(recentsIntent, 0 /* eventTime */,
null /* recentsAnimationRunner */);
verify(recentsActivity).ensureActivityConfiguration(anyInt() /* globalChanges */,
@@ -381,7 +381,7 @@
Intent recentsIntent = new Intent();
recentsIntent.setComponent(recentsComponent);
- mAtm.startRecentsActivity(recentsIntent, null /* assistDataReceiver */,
+ mAtm.startRecentsActivity(recentsIntent, 0 /* eventTime */,
mock(IRecentsAnimationRunner.class));
return recentsAnimation[0];
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
index d7eedd9..d0a5644 100644
--- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
@@ -147,13 +147,6 @@
}
@Override
- public SurfaceControl.Transaction deferTransactionUntilSurface(SurfaceControl sc,
- Surface barrierSurface,
- long frameNumber) {
- return this;
- }
-
- @Override
public SurfaceControl.Transaction reparentChildren(SurfaceControl sc,
SurfaceControl newParent) {
return this;
diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt
index 69caccb1..3ff48ce 100644
--- a/telephony/api/system-current.txt
+++ b/telephony/api/system-current.txt
@@ -694,6 +694,7 @@
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<java.lang.String> getEquivalentHomePlmns();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index b35b323..c3cd017 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -524,7 +524,7 @@
}
private static String getDefaultSmsPackage(Context context, int userId) {
- return context.getSystemService(RoleManager.class).getDefaultSmsPackage(userId);
+ return context.getSystemService(RoleManager.class).getSmsRoleHolder(userId);
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c60b514..12e56cc 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -85,8 +85,6 @@
import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
import android.telephony.ims.ImsMmTelManager;
import android.telephony.ims.aidl.IImsConfig;
-import android.telephony.ims.aidl.IImsMmTelFeature;
-import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -94,7 +92,6 @@
import android.util.Log;
import android.util.Pair;
-import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.CellNetworkScanResult;
@@ -7384,80 +7381,6 @@
}
/**
- * Returns the {@link IImsMmTelFeature} that corresponds to the given slot Id and MMTel
- * feature or {@link null} if the service is not available. If an MMTelFeature is available, the
- * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
- * @param slotIndex The SIM slot that we are requesting the {@link IImsMmTelFeature} for.
- * @param callback Listener that will send updates to ImsManager when there are updates to
- * ImsServiceController.
- * @return {@link IImsMmTelFeature} interface for the feature specified or {@code null} if
- * it is unavailable.
- * @hide
- */
- public @Nullable IImsMmTelFeature getImsMmTelFeatureAndListen(int slotIndex,
- IImsServiceFeatureCallback callback) {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- return telephony.getMmTelFeatureAndListen(slotIndex, callback);
- }
- } catch (RemoteException e) {
- Rlog.e(TAG, "getImsMmTelFeatureAndListen, RemoteException: "
- + e.getMessage());
- }
- return null;
- }
-
- /**
- * Returns the {@link IImsRcsFeature} that corresponds to the given slot Id and RCS
- * feature for emergency calling or {@link null} if the service is not available. If an
- * RcsFeature is available, the {@link IImsServiceFeatureCallback} callback is registered as a
- * listener for feature updates.
- * @param slotIndex The SIM slot that we are requesting the {@link IImsRcsFeature} for.
- * @param callback Listener that will send updates to ImsManager when there are updates to
- * ImsServiceController.
- * @return {@link IImsRcsFeature} interface for the feature specified or {@code null} if
- * it is unavailable.
- * @hide
- */
- public @Nullable IImsRcsFeature getImsRcsFeatureAndListen(int slotIndex,
- IImsServiceFeatureCallback callback) {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- return telephony.getRcsFeatureAndListen(slotIndex, callback);
- }
- } catch (RemoteException e) {
- Rlog.e(TAG, "getImsRcsFeatureAndListen, RemoteException: "
- + e.getMessage());
- }
- return null;
- }
-
- /**
- * Unregister a IImsServiceFeatureCallback previously associated with an ImsFeature through
- * {@link #getImsMmTelFeatureAndListen(int, IImsServiceFeatureCallback)} or
- * {@link #getImsRcsFeatureAndListen(int, IImsServiceFeatureCallback)}.
- * @param slotIndex The SIM slot associated with the callback.
- * @param featureType The {@link android.telephony.ims.feature.ImsFeature.FeatureType}
- * associated with the callback.
- * @param callback The callback to be unregistered.
- * @hide
- */
- public void unregisterImsFeatureCallback(int slotIndex, int featureType,
- IImsServiceFeatureCallback callback) {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- telephony.unregisterImsFeatureCallback(slotIndex, featureType, callback);
- }
- } catch (RemoteException e) {
- Rlog.e(TAG, "unregisterImsFeatureCallback, RemoteException: "
- + e.getMessage());
- }
- }
-
- /**
* @return the {@IImsRegistration} interface that corresponds with the slot index and feature.
* @param slotIndex The SIM slot corresponding to the ImsService ImsRegistration is active for.
* @param feature An integer indicating the feature that we wish to get the ImsRegistration for.
@@ -13735,4 +13658,38 @@
return true;
}
}
+
+ /**
+ * Returns a list of the equivalent home PLMNs (EF_EHPLMN) from the USIM app.
+ *
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
+ * @return A list of equivalent home PLMNs. Returns an empty list if EF_EHPLMN is empty or
+ * does not exist on the SIM card.
+ *
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ * @throws SecurityException if the caller doesn't have the permission.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ public @NonNull List<String> getEquivalentHomePlmns() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getEquivalentHomePlmns(getSubId(), mContext.getOpPackageName(),
+ getAttributionTag());
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ if (!isSystemProcess()) {
+ ex.rethrowAsRuntimeException();
+ }
+ }
+
+ return Collections.emptyList();
+ }
}
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index f6c14e6..ee2fce7 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -59,6 +59,7 @@
* manager.
*/
public class ImsMmTelManager implements RegistrationManager {
+ private static final String TAG = "ImsMmTelManager";
/**
* @hide
@@ -809,7 +810,7 @@
}
try {
- getITelephony().isMmTelCapabilitySupported(mSubId, new IIntegerConsumer.Stub() {
+ iTelephony.isMmTelCapabilitySupported(mSubId, new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
executor.execute(() -> callback.accept(result == 1));
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index da7311c..8a05bdf 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -16,6 +16,7 @@
package android.telephony.ims;
+import android.annotation.LongDef;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.Service;
@@ -41,6 +42,11 @@
import com.android.ims.internal.IImsFeatureStatusCallback;
import com.android.internal.annotations.VisibleForTesting;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend
* ImsService must register the service in their AndroidManifest to be detected by the framework.
@@ -98,6 +104,32 @@
private static final String LOG_TAG = "ImsService";
/**
+ * This ImsService supports the capability to place emergency calls over MMTEL.
+ * @hide This is encoded into the {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, but we will be
+ * adding other capabilities in a central location, so track this capability here as well.
+ */
+ public static final long CAPABILITY_EMERGENCY_OVER_MMTEL = 1 << 0;
+
+ /**
+ * @hide
+ */
+ @LongDef(flag = true,
+ prefix = "CAPABILITY_",
+ value = {
+ CAPABILITY_EMERGENCY_OVER_MMTEL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ImsServiceCapability {}
+
+ /**
+ * Used for logging purposes, see {@link #getCapabilitiesString(long)}
+ * @hide
+ */
+ private static final Map<Long, String> CAPABILITIES_LOG_MAP = new HashMap<Long, String>() {{
+ put(CAPABILITY_EMERGENCY_OVER_MMTEL, "EMERGENCY_OVER_MMTEL");
+ }};
+
+ /**
* The intent that must be defined as an intent-filter in the AndroidManifest of the ImsService.
* @hide
*/
@@ -409,4 +441,30 @@
public ImsRegistrationImplBase getRegistration(int slotId) {
return new ImsRegistrationImplBase();
}
+
+ /**
+ * @return A string representation of the ImsService capabilties for logging.
+ * @hide
+ */
+ public static String getCapabilitiesString(@ImsServiceCapability long caps) {
+ StringBuffer result = new StringBuffer();
+ result.append("capabilities={ ");
+ // filter incrementally fills 0s from left to right. This is used to keep filtering out
+ // more bits in the long until the remaining leftmost bits are all zero.
+ long filter = 0xFFFFFFFFFFFFFFFFL;
+ // position of iterator to potentially print capability.
+ long i = 0;
+ while ((caps & filter) != 0 && i <= 63) {
+ long bitToCheck = (1L << i);
+ if ((caps & bitToCheck) != 0) {
+ result.append(CAPABILITIES_LOG_MAP.getOrDefault(bitToCheck, bitToCheck + "?"));
+ result.append(" ");
+ }
+ // shift left by one and fill in another 1 on the leftmost bit.
+ filter <<= 1;
+ i++;
+ }
+ result.append("}");
+ return result.toString();
+ }
}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
index 9e46142..e01ea91 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
@@ -22,6 +22,8 @@
import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
import android.telephony.ims.aidl.IImsRegistrationCallback;
+import com.android.ims.ImsFeatureContainer;
+import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.telephony.IIntegerConsumer;
/**
@@ -50,4 +52,8 @@
void setUceSettingEnabled(int subId, boolean isEnabled);
void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c);
void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c);
+
+ // Internal commands that should not be made public
+ void registerRcsFeatureCallback(int slotId, in IImsServiceFeatureCallback callback);
+ void unregisterImsFeatureCallback(in IImsServiceFeatureCallback callback);
}
diff --git a/telephony/java/com/android/ims/ImsFeatureContainer.aidl b/telephony/java/com/android/ims/ImsFeatureContainer.aidl
new file mode 100644
index 0000000..9706f20
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsFeatureContainer.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 com.android.ims;
+
+parcelable ImsFeatureContainer;
\ No newline at end of file
diff --git a/telephony/java/com/android/ims/ImsFeatureContainer.java b/telephony/java/com/android/ims/ImsFeatureContainer.java
new file mode 100644
index 0000000..b259679
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsFeatureContainer.java
@@ -0,0 +1,172 @@
+/*
+ * 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.ims;
+
+import android.annotation.NonNull;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.ims.ImsService;
+import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.feature.ImsFeature;
+
+import java.util.Objects;
+
+/**
+ * Contains an IBinder linking to the appropriate ImsFeature as well as the associated
+ * interfaces.
+ * @hide
+ */
+public final class ImsFeatureContainer implements Parcelable {
+ /**
+ * ImsFeature that is being tracked.
+ */
+ public final IBinder imsFeature;
+
+ /**
+ * IImsConfig interface that should be associated with the ImsFeature.
+ */
+ public final android.telephony.ims.aidl.IImsConfig imsConfig;
+
+ /**
+ * IImsRegistration interface that should be associated with this ImsFeature.
+ */
+ public final IImsRegistration imsRegistration;
+
+ /**
+ * State of the feature that is being tracked.
+ */
+ private @ImsFeature.ImsState int mState = ImsFeature.STATE_UNAVAILABLE;
+
+ /**
+ * Capabilities of this ImsService.
+ */
+ private @ImsService.ImsServiceCapability long mCapabilities;
+ /**
+ * Contains the ImsFeature IBinder as well as the ImsService interfaces associated with
+ * that feature.
+ * @param iFace IBinder connection to the ImsFeature.
+ * @param iConfig IImsConfig interface associated with the ImsFeature.
+ * @param iReg IImsRegistration interface associated with the ImsFeature
+ * @param initialCaps The initial capabilities that the ImsService supports.
+ */
+ public ImsFeatureContainer(@NonNull IBinder iFace, @NonNull IImsConfig iConfig,
+ @NonNull IImsRegistration iReg, long initialCaps) {
+ imsFeature = iFace;
+ imsConfig = iConfig;
+ imsRegistration = iReg;
+ mCapabilities = initialCaps;
+ }
+
+ /**
+ * Create an ImsFeatureContainer from a Parcel.
+ */
+ private ImsFeatureContainer(Parcel in) {
+ imsFeature = in.readStrongBinder();
+ imsConfig = IImsConfig.Stub.asInterface(in.readStrongBinder());
+ imsRegistration = IImsRegistration.Stub.asInterface(in.readStrongBinder());
+ mState = in.readInt();
+ mCapabilities = in.readLong();
+ }
+
+ /**
+ * @return the capabilties that are associated with the ImsService that this ImsFeature
+ * belongs to.
+ */
+ public @ImsService.ImsServiceCapability long getCapabilities() {
+ return mCapabilities;
+ }
+
+ /**
+ * Update the capabilities that are associated with the ImsService that this ImsFeature
+ * belongs to.
+ */
+ public void setCapabilities(@ImsService.ImsServiceCapability long caps) {
+ mCapabilities = caps;
+ }
+
+ /**
+ * @return The state of the ImsFeature.
+ */
+ public @ImsFeature.ImsState int getState() {
+ return mState;
+ }
+
+ /**
+ * Set the state that is associated with the ImsService that this ImsFeature
+ * belongs to.
+ */
+ public void setState(@ImsFeature.ImsState int state) {
+ mState = state;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ImsFeatureContainer that = (ImsFeatureContainer) o;
+ return imsFeature.equals(that.imsFeature) &&
+ imsConfig.equals(that.imsConfig) &&
+ imsRegistration.equals(that.imsRegistration) &&
+ mState == that.getState() &&
+ mCapabilities == that.getCapabilities();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(imsFeature, imsConfig, imsRegistration, mState, mCapabilities);
+ }
+
+ @Override
+ public String toString() {
+ return "FeatureContainer{" +
+ "imsFeature=" + imsFeature +
+ ", imsConfig=" + imsConfig +
+ ", imsRegistration=" + imsRegistration +
+ ", state=" + ImsFeature.STATE_LOG_MAP.get(mState) +
+ ", capabilities = " + ImsService.getCapabilitiesString(mCapabilities) +
+ '}';
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeStrongBinder(imsFeature);
+ dest.writeStrongInterface(imsConfig);
+ dest.writeStrongInterface(imsRegistration);
+ dest.writeInt(mState);
+ dest.writeLong(mCapabilities);
+ }
+
+
+ public static final Creator<ImsFeatureContainer> CREATOR = new Creator<ImsFeatureContainer>() {
+ @Override
+ public ImsFeatureContainer createFromParcel(Parcel source) {
+ return new ImsFeatureContainer(source);
+ }
+
+ @Override
+ public ImsFeatureContainer[] newArray(int size) {
+ return new ImsFeatureContainer[size];
+ }
+ };
+}
diff --git a/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl b/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
index 9a9cf53..f5f67bd 100644
--- a/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
+++ b/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
@@ -16,13 +16,18 @@
package com.android.ims.internal;
+import com.android.ims.ImsFeatureContainer;
/**
- * Interface from ImsResolver to ImsServiceProxy in ImsManager.
- * Callback to ImsManager when a feature changes in the ImsServiceController.
+ * Interface from ImsResolver to FeatureConnections.
+ * Callback to FeatureConnections when a feature's status changes.
* {@hide}
*/
oneway interface IImsServiceFeatureCallback {
- void imsFeatureCreated(int slotId, int feature);
- void imsFeatureRemoved(int slotId, int feature);
- void imsStatusChanged(int slotId, int feature, int status);
+ void imsFeatureCreated(in ImsFeatureContainer feature);
+ // Reason defined in FeatureConnector.UnavailableReason
+ void imsFeatureRemoved(int reason);
+ // Status defined in ImsFeature.ImsState.
+ void imsStatusChanged(int status);
+ //Capabilities defined in ImsService.ImsServiceCapability
+ void updateCapabilities(long capabilities);
}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 02a74ba..53069a1 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -829,22 +829,14 @@
* as well as registering the MmTelFeature for callbacks using the IImsServiceFeatureCallback
* interface.
*/
- IImsMmTelFeature getMmTelFeatureAndListen(int slotId, in IImsServiceFeatureCallback callback);
-
- /**
- * Get IImsRcsFeature binder from ImsResolver that corresponds to the subId and RCS feature
- * as well as registering the RcsFeature for callbacks using the IImsServiceFeatureCallback
- * interface.
- */
- IImsRcsFeature getRcsFeatureAndListen(int slotId, in IImsServiceFeatureCallback callback);
+ void registerMmTelFeatureCallback(int slotId, in IImsServiceFeatureCallback callback);
/**
* Unregister a callback that was previously registered through
- * {@link #getMmTelFeatureAndListen} or {@link #getRcsFeatureAndListen}. This should always be
- * called when the callback is no longer being used.
+ * {@link #registerMmTelFeatureCallback}. This should always be called when the callback is no
+ * longer being used.
*/
- void unregisterImsFeatureCallback(int slotId, int featureType,
- in IImsServiceFeatureCallback callback);
+ void unregisterImsFeatureCallback(in IImsServiceFeatureCallback callback);
/**
* Returns the IImsRegistration associated with the slot and feature specified.
@@ -2228,4 +2220,12 @@
* Whether device can connect to 5G network when two SIMs are active.
*/
boolean canConnectTo5GInDsdsMode();
+
+ /**
+ * Returns a list of the equivalent home PLMNs (EF_EHPLMN) from the USIM app.
+ *
+ * @return A list of equivalent home PLMNs. Returns an empty list if EF_EHPLMN is empty or
+ * does not exist on the SIM card.
+ */
+ List<String> getEquivalentHomePlmns(int subId, String callingPackage, String callingFeatureId);
}
diff --git a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
index 83fd208..8013bd8 100644
--- a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
+++ b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
@@ -130,7 +130,7 @@
when(mTelephonyManager.isSmsCapable()).thenReturn(true);
when(mRoleManager.isRoleAvailable(RoleManager.ROLE_SMS)).thenReturn(true);
- when(mRoleManager.getDefaultSmsPackage(anyInt()))
+ when(mRoleManager.getSmsRoleHolder(anyInt()))
.thenReturn(TEST_COMPONENT_NAME.getPackageName());
for (String opStr : APP_OPS_TO_CHECK) {
diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java
index 030ddd2..3c3076f 100644
--- a/tests/net/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/common/java/android/net/LinkPropertiesTest.java
@@ -32,6 +32,7 @@
import static org.junit.Assert.fail;
import android.net.LinkProperties.ProvisioningChange;
+import android.net.util.LinkPropertiesUtils.CompareResult;
import android.os.Build;
import android.system.OsConstants;
import android.util.ArraySet;
@@ -40,7 +41,6 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
diff --git a/tests/net/java/android/net/MacAddressTest.java b/tests/net/java/android/net/MacAddressTest.java
index 6de31f6..91c9a2a 100644
--- a/tests/net/java/android/net/MacAddressTest.java
+++ b/tests/net/java/android/net/MacAddressTest.java
@@ -22,11 +22,11 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.net.util.MacAddressUtils;
+
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.net.module.util.MacAddressUtils;
-
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/tools/aapt2/dump/DumpManifest.cpp b/tools/aapt2/dump/DumpManifest.cpp
index 71c70da..7497869 100644
--- a/tools/aapt2/dump/DumpManifest.cpp
+++ b/tools/aapt2/dump/DumpManifest.cpp
@@ -79,8 +79,8 @@
ISGAME_ATTR = 0x10103f4,
VERSION_ATTR = 0x01010519,
CERT_DIGEST_ATTR = 0x01010548,
- REQUIRED_FEATURE_ATTR = 0x01010557,
- REQUIRED_NOT_FEATURE_ATTR = 0x01010558,
+ REQUIRED_FEATURE_ATTR = 0x01010554,
+ REQUIRED_NOT_FEATURE_ATTR = 0x01010555,
IS_STATIC_ATTR = 0x0101055a,
REQUIRED_SYSTEM_PROPERTY_NAME_ATTR = 0x01010565,
REQUIRED_SYSTEM_PROPERTY_VALUE_ATTR = 0x01010566,
diff --git a/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.aidl b/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.aidl
index cf2cb4a..57055f7 100644
--- a/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.aidl
+++ b/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.net.wifi.p2p.servicediscovery;
+package android.net.wifi.p2p.nsd;
parcelable WifiP2pServiceInfo;
diff --git a/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.aidl b/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.aidl
index d5a1e8f..e4d28bb 100644
--- a/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.aidl
+++ b/wifi/aidl-export/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.net.wifi.p2p.servicediscovery;
+package android.net.wifi.p2p.nsd;
parcelable WifiP2pServiceRequest;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index a4f802a..fc6c59a 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -29,6 +29,7 @@
import android.net.ProxyInfo;
import android.net.StaticIpConfiguration;
import android.net.Uri;
+import android.net.util.MacAddressUtils;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -40,7 +41,6 @@
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.net.module.util.MacAddressUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
index e2f40cf..dad431c1 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
@@ -17,11 +17,10 @@
package android.net.wifi.p2p.nsd;
import android.compat.annotation.UnsupportedAppUsage;
+import android.net.util.nsd.DnsSdTxtRecord;
import android.os.Build;
import android.text.TextUtils;
-import com.android.net.module.util.DnsSdTxtRecord;
-
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index 6894ba0..8af7500 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -33,14 +33,13 @@
import static org.junit.Assert.assertTrue;
import android.net.MacAddress;
+import android.net.util.MacAddressUtils;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
import android.os.Parcel;
import androidx.test.filters.SmallTest;
-import com.android.net.module.util.MacAddressUtils;
-
import org.junit.Before;
import org.junit.Test;