Merge "Remove @Deprecated && @removed package fields."
diff --git a/Android.bp b/Android.bp
index 8fedc34..1902a5f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -747,7 +747,7 @@
"core/java/android/content/pm/AndroidTestBaseUpdater.java",
],
- no_framework_libs: true,
+ sdk_version: "core_platform",
libs: [
"ext",
"updatable_media_stubs",
@@ -951,7 +951,7 @@
java_library {
name: "ext",
installable: true,
- no_framework_libs: true,
+ sdk_version: "core_platform",
static_libs: [
"libphonenumber-platform",
"nist-sip",
@@ -1175,7 +1175,7 @@
// updated to use hwbinder.stubs.
java_library {
name: "hwbinder",
- no_framework_libs: true,
+ sdk_version: "core_platform",
srcs: [
"core/java/android/os/HidlSupport.java",
@@ -1702,7 +1702,7 @@
"core/java/android/util/AndroidException.java",
],
installable: false,
- no_framework_libs: true,
+ sdk_version: "core_platform",
annotations_enabled: true,
previous_api: ":last-released-public-api",
merge_annotations_dirs: [
diff --git a/api/current.txt b/api/current.txt
index 4715212..28fe8bb 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23977,6 +23977,7 @@
field public static final String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
field public static final String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
field public static final String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
+ field public static final String TAG_THUMBNAIL_ORIENTATION = "ThumbnailOrientation";
field public static final String TAG_TRANSFER_FUNCTION = "TransferFunction";
field public static final String TAG_USER_COMMENT = "UserComment";
field public static final String TAG_WHITE_BALANCE = "WhiteBalance";
diff --git a/api/removed.txt b/api/removed.txt
index 8ed6b68..8ccd2c6 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -1,11 +1,6 @@
// Signature format: 2.0
package android.app {
- public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
- method @Deprecated public boolean enterPictureInPictureMode(@NonNull android.app.PictureInPictureArgs);
- method @Deprecated public void setPictureInPictureArgs(@NonNull android.app.PictureInPictureArgs);
- }
-
public class ActivityManager {
method @Deprecated public static int getMaxNumPictureInPictureActions();
}
@@ -26,24 +21,6 @@
method @Deprecated public android.app.Notification.Builder setTimeout(long);
}
- @Deprecated public final class PictureInPictureArgs implements android.os.Parcelable {
- method public static android.app.PictureInPictureArgs convert(android.app.PictureInPictureParams);
- method public static android.app.PictureInPictureParams convert(android.app.PictureInPictureArgs);
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CONTENTS_FILE_DESCRIPTOR = 1; // 0x1
- field @NonNull public static final android.os.Parcelable.Creator<android.app.PictureInPictureArgs> CREATOR;
- field public static final int PARCELABLE_WRITE_RETURN_VALUE = 1; // 0x1
- }
-
- public static class PictureInPictureArgs.Builder {
- ctor public PictureInPictureArgs.Builder();
- method public android.app.PictureInPictureArgs build();
- method public android.app.PictureInPictureArgs.Builder setActions(java.util.List<android.app.RemoteAction>);
- method public android.app.PictureInPictureArgs.Builder setAspectRatio(android.util.Rational);
- method public android.app.PictureInPictureArgs.Builder setSourceRectHint(android.graphics.Rect);
- }
-
}
package android.app.admin {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index e3665f6..3e26a9b 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -151,11 +151,6 @@
field public static final boolean PERMISSIONS_REVIEW_REQUIRED = true;
}
- public final class PowerManager {
- method @Deprecated public boolean isScreenBrightnessBoosted();
- field @Deprecated public static final String ACTION_SCREEN_BRIGHTNESS_BOOST_CHANGED = "android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED";
- }
-
}
package android.service.notification {
diff --git a/api/test-current.txt b/api/test-current.txt
index c787bfa..0127dfe 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3473,6 +3473,11 @@
method public boolean isInputMethodPickerShown();
}
+ public class InputMethodSystemProperty {
+ ctor public InputMethodSystemProperty();
+ field public static final boolean MULTI_CLIENT_IME_ENABLED;
+ }
+
}
package android.view.inspector {
diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp
index d541169..f925023 100644
--- a/cmds/app_process/Android.bp
+++ b/cmds/app_process/Android.bp
@@ -21,6 +21,7 @@
"libbinder",
"libcutils",
"libdl",
+ "libhidlbase",
"libhwbinder",
"liblog",
"libnativeloader",
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 6bedfcd..2f0dc3c 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -333,7 +333,7 @@
// ==== java proto device library (for test only) ==============================
java_library {
name: "statsdprotolite",
- no_framework_libs: true,
+ sdk_version: "core_platform",
proto: {
type: "lite",
include_dirs: ["external/protobuf/src"],
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index f3f8d68..19374a58 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -303,12 +303,16 @@
ContentCaptureSessionEvents content_capture_session_events = 208;
ContentCaptureFlushed content_capture_flushed = 209;
LocationManagerApiUsageReported location_manager_api_usage_reported = 210;
- ReviewPermissionsFragmentResultReported review_permissions_fragment_result_reported
- = 211 [(log_from_module) = "permissioncontroller"];
+ ReviewPermissionsFragmentResultReported review_permissions_fragment_result_reported =
+ 211 [(log_from_module) = "permissioncontroller"];
+ RuntimePermissionsUpgradeResult runtime_permissions_upgrade_result =
+ 212 [(log_from_module) = "permissioncontroller"];
+ GrantPermissionsActivityButtonActions grant_permissions_activity_button_actions =
+ 213 [(log_from_module) = "permissioncontroller"];
}
// Pulled events will start at field 10000.
- // Next: 10059
+ // Next: 10062
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000;
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
@@ -371,6 +375,7 @@
FaceSettings face_settings = 10058;
CoolingDevice cooling_device = 10059;
AppOps app_ops = 10060;
+ ProcessSystemIonHeapSize process_system_ion_heap_size = 10061;
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -5278,7 +5283,7 @@
// Only valid for event_type = EVENT_RESNSEND.
optional int32 res_nsend_flags = 5;
- optional android.stats.dnsresolver.Transport network_type = 6;
+ optional android.stats.dnsresolver.NetworkType network_type = 6;
// The DNS over TLS mode on a specific netId.
optional android.stats.dnsresolver.PrivateDnsModes private_dns_modes = 7;
@@ -6349,6 +6354,28 @@
optional int64 size_in_bytes = 1;
}
+/*
+ * Logs the per-process size of the system ion heap.
+ *
+ * Pulled from StatsCompanionService.
+ */
+message ProcessSystemIonHeapSize {
+ // The uid if available. -1 means not available.
+ optional int32 uid = 1 [(is_uid) = true];
+
+ // The process name (from /proc/PID/cmdline).
+ optional string process_name = 2;
+
+ // Sum of sizes of all allocations.
+ optional int32 total_size_in_kilobytes = 3;
+
+ // Number of allocations.
+ optional int32 allocation_count = 4;
+
+ // Size of the largest allocation.
+ optional int32 max_size_in_kilobytes = 5;
+}
+
/**
* Push network stack events.
*
@@ -6573,3 +6600,39 @@
// The result of the permission grant
optional bool permission_granted = 5;
}
+
+/**
+* Information about results of permission upgrade by RuntimePermissionsUpgradeController
+* Logged from: RuntimePermissionUpdgradeController
+*/
+message RuntimePermissionsUpgradeResult {
+ // Permission granted as result of upgrade
+ optional string permission_name = 1;
+
+ // UID of package granted permission
+ optional int32 uid = 2 [(is_uid) = true];
+
+ // Name of package granted permission
+ optional string package_name = 3;
+}
+
+/**
+* Information about a buttons presented in GrantPermissionsActivty and choice made by user
+*/
+message GrantPermissionsActivityButtonActions {
+ // Permission granted as result of upgrade
+ optional string permission_group_name = 1;
+
+ // UID of package granted permission
+ optional int32 uid = 2 [(is_uid) = true];
+
+ // Name of package requesting permission
+ optional string package_name = 3;
+
+ // Buttons presented in the dialog - bit flags, bit numbers are in accordance with
+ // LABEL_ constants in GrantPermissionActivity.java
+ optional int32 buttons_presented = 4;
+
+ // Button clicked by user - same as bit flags in buttons_presented with only single bit set
+ optional int32 button_clicked = 5;
+}
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 914d60d..475f18a 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -156,6 +156,9 @@
// system_ion_heap_size
{android::util::SYSTEM_ION_HEAP_SIZE,
{.puller = new StatsCompanionServicePuller(android::util::SYSTEM_ION_HEAP_SIZE)}},
+ // process_system_ion_heap_size
+ {android::util::PROCESS_SYSTEM_ION_HEAP_SIZE,
+ {.puller = new StatsCompanionServicePuller(android::util::PROCESS_SYSTEM_ION_HEAP_SIZE)}},
// temperature
{android::util::TEMPERATURE,
{.puller = new StatsCompanionServicePuller(android::util::TEMPERATURE)}},
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index dc52c52..28d3165 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2682,12 +2682,6 @@
enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
}
- /** @removed */
- @Deprecated
- public boolean enterPictureInPictureMode(@NonNull PictureInPictureArgs args) {
- return enterPictureInPictureMode(PictureInPictureArgs.convert(args));
- }
-
/**
* Puts the activity in picture-in-picture mode if possible in the current system state. The
* set parameters in {@param params} will be combined with the parameters from prior calls to
@@ -2724,12 +2718,6 @@
}
}
- /** @removed */
- @Deprecated
- public void setPictureInPictureArgs(@NonNull PictureInPictureArgs args) {
- setPictureInPictureParams(PictureInPictureArgs.convert(args));
- }
-
/**
* Updates the properties of the picture-in-picture activity, or sets it to be used later when
* {@link #enterPictureInPictureMode()} is called.
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 4db3725..ac8b604 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -108,6 +108,8 @@
ParceledListSlice getNotificationChannelsBypassingDnd(String pkg, int userId);
boolean isPackagePaused(String pkg);
+ void silenceNotificationSound();
+
// TODO: Remove this when callers have been migrated to the equivalent
// INotificationListener method.
@UnsupportedAppUsage
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 2e80375..c1cee77 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1133,6 +1133,25 @@
}
/**
+ * Silences the current notification sound, if ones currently playing.
+ * <p>
+ * It is intended to handle use-cases such as silencing a ringing call
+ * when the user presses the volume button during ringing.
+ * <p>
+ * If this method is called prior to when the notification begins playing, the sound will not be
+ * silenced. As such it is not intended as a means to avoid playing of a sound.
+ * @hide
+ */
+ public void silenceNotificationSound() {
+ INotificationManager service = getService();
+ try {
+ service.silenceNotificationSound();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns whether notifications from this package are temporarily hidden. This
* could be done because the package was marked as distracting to the user via
* {@code PackageManager#setDistractingPackageRestrictions(String[], int)} or because the
diff --git a/core/java/android/app/PictureInPictureArgs.java b/core/java/android/app/PictureInPictureArgs.java
deleted file mode 100644
index 3ee5173..0000000
--- a/core/java/android/app/PictureInPictureArgs.java
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright (C) 2017 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.app;
-
-import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
-import android.graphics.Rect;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Rational;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** @removed */
-@Deprecated
-public final class PictureInPictureArgs implements Parcelable {
-
- /**
- * Builder class for {@link PictureInPictureArgs} objects.
- */
- public static class Builder {
-
- @Nullable
- private Rational mAspectRatio;
-
- @Nullable
- private List<RemoteAction> mUserActions;
-
- @Nullable
- private Rect mSourceRectHint;
-
- /**
- * Sets the aspect ratio. This aspect ratio is defined as the desired width / height, and
- * does not change upon device rotation.
- *
- * @param aspectRatio the new aspect ratio for the activity in picture-in-picture, must be
- * between 2.39:1 and 1:2.39 (inclusive).
- *
- * @return this builder instance.
- */
- public Builder setAspectRatio(Rational aspectRatio) {
- mAspectRatio = aspectRatio;
- return this;
- }
-
- /**
- * Sets the user actions. If there are more than
- * {@link Activity#getMaxNumPictureInPictureActions()} actions, then the input list
- * will be truncated to that number.
- *
- * @param actions the new actions to show in the picture-in-picture menu.
- *
- * @return this builder instance.
- *
- * @see RemoteAction
- */
- public Builder setActions(List<RemoteAction> actions) {
- if (mUserActions != null) {
- mUserActions = null;
- }
- if (actions != null) {
- mUserActions = new ArrayList<>(actions);
- }
- return this;
- }
-
- /**
- * Sets the source bounds hint. These bounds are only used when an activity first enters
- * picture-in-picture, and describe the bounds in window coordinates of activity entering
- * picture-in-picture that will be visible following the transition. For the best effect,
- * these bounds should also match the aspect ratio in the arguments.
- *
- * @param launchBounds window-coordinate bounds indicating the area of the activity that
- * will still be visible following the transition into picture-in-picture (eg. the video
- * view bounds in a video player)
- *
- * @return this builder instance.
- */
- public Builder setSourceRectHint(Rect launchBounds) {
- if (launchBounds == null) {
- mSourceRectHint = null;
- } else {
- mSourceRectHint = new Rect(launchBounds);
- }
- return this;
- }
-
- public PictureInPictureArgs build() {
- PictureInPictureArgs args = new PictureInPictureArgs(mAspectRatio, mUserActions,
- mSourceRectHint);
- return args;
- }
- }
-
- /**
- * The expected aspect ratio of the picture-in-picture.
- */
- @Nullable
- private Rational mAspectRatio;
-
- /**
- * The set of actions that are associated with this activity when in picture-in-picture.
- */
- @Nullable
- private List<RemoteAction> mUserActions;
-
- /**
- * The source bounds hint used when entering picture-in-picture, relative to the window bounds.
- * We can use this internally for the transition into picture-in-picture to ensure that a
- * particular source rect is visible throughout the whole transition.
- */
- @Nullable
- private Rect mSourceRectHint;
-
- /**
- * The content insets that are used with the source hint rect for the transition into PiP where
- * the insets are removed at the beginning of the transition.
- */
- @Nullable
- private Rect mSourceRectHintInsets;
-
- /**
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- public PictureInPictureArgs() {
- }
-
- /**
- * @hide
- */
- @Deprecated
- public PictureInPictureArgs(float aspectRatio, List<RemoteAction> actions) {
- setAspectRatio(aspectRatio);
- setActions(actions);
- }
-
- private PictureInPictureArgs(Parcel in) {
- if (in.readInt() != 0) {
- mAspectRatio = new Rational(in.readInt(), in.readInt());
- }
- if (in.readInt() != 0) {
- mUserActions = new ArrayList<>();
- in.readParcelableList(mUserActions, RemoteAction.class.getClassLoader());
- }
- if (in.readInt() != 0) {
- mSourceRectHint = Rect.CREATOR.createFromParcel(in);
- }
- }
-
- private PictureInPictureArgs(Rational aspectRatio, List<RemoteAction> actions,
- Rect sourceRectHint) {
- mAspectRatio = aspectRatio;
- mUserActions = actions;
- mSourceRectHint = sourceRectHint;
- }
-
- /**
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- public void setAspectRatio(float aspectRatio) {
- // Temporary workaround
- mAspectRatio = new Rational((int) (aspectRatio * 1000000000), 1000000000);
- }
-
- /**
- * @hide
- */
- @Deprecated
- @UnsupportedAppUsage
- public void setActions(List<RemoteAction> actions) {
- if (mUserActions != null) {
- mUserActions = null;
- }
- if (actions != null) {
- mUserActions = new ArrayList<>(actions);
- }
- }
-
- /**
- * @hide
- */
- @Deprecated
- public void setSourceRectHint(Rect launchBounds) {
- if (launchBounds == null) {
- mSourceRectHint = null;
- } else {
- mSourceRectHint = new Rect(launchBounds);
- }
- }
-
- /**
- * Copies the set parameters from the other picture-in-picture args.
- * @hide
- */
- public void copyOnlySet(PictureInPictureArgs otherArgs) {
- if (otherArgs.hasSetAspectRatio()) {
- mAspectRatio = otherArgs.mAspectRatio;
- }
- if (otherArgs.hasSetActions()) {
- mUserActions = otherArgs.mUserActions;
- }
- if (otherArgs.hasSourceBoundsHint()) {
- mSourceRectHint = new Rect(otherArgs.getSourceRectHint());
- }
- }
-
- /**
- * @return the aspect ratio. If none is set, return 0.
- * @hide
- */
- public float getAspectRatio() {
- if (mAspectRatio != null) {
- return mAspectRatio.floatValue();
- }
- return 0f;
- }
-
- /** {@hide} */
- public Rational getAspectRatioRational() {
- return mAspectRatio;
- }
-
- /**
- * @return whether the aspect ratio is set.
- * @hide
- */
- public boolean hasSetAspectRatio() {
- return mAspectRatio != null;
- }
-
- /**
- * @return the set of user actions.
- * @hide
- */
- public List<RemoteAction> getActions() {
- return mUserActions;
- }
-
- /**
- * @return whether the user actions are set.
- * @hide
- */
- public boolean hasSetActions() {
- return mUserActions != null;
- }
-
- /**
- * Truncates the set of actions to the given {@param size}.
- * @hide
- */
- public void truncateActions(int size) {
- if (hasSetActions()) {
- mUserActions = mUserActions.subList(0, Math.min(mUserActions.size(), size));
- }
- }
-
- /**
- * Sets the insets to be used with the source rect hint bounds.
- * @hide
- */
- @Deprecated
- public void setSourceRectHintInsets(Rect insets) {
- if (insets == null) {
- mSourceRectHintInsets = null;
- } else {
- mSourceRectHintInsets = new Rect(insets);
- }
- }
-
- /**
- * @return the source rect hint
- * @hide
- */
- public Rect getSourceRectHint() {
- return mSourceRectHint;
- }
-
- /**
- * @return the source rect hint insets.
- * @hide
- */
- public Rect getSourceRectHintInsets() {
- return mSourceRectHintInsets;
- }
-
- /**
- * @return whether there are launch bounds set
- * @hide
- */
- public boolean hasSourceBoundsHint() {
- return mSourceRectHint != null && !mSourceRectHint.isEmpty();
- }
-
- /**
- * @return whether there are source rect hint insets set
- * @hide
- */
- public boolean hasSourceBoundsHintInsets() {
- return mSourceRectHintInsets != null;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- if (mAspectRatio != null) {
- out.writeInt(1);
- out.writeInt(mAspectRatio.getNumerator());
- out.writeInt(mAspectRatio.getDenominator());
- } else {
- out.writeInt(0);
- }
- if (mUserActions != null) {
- out.writeInt(1);
- out.writeParcelableList(mUserActions, 0);
- } else {
- out.writeInt(0);
- }
- if (mSourceRectHint != null) {
- out.writeInt(1);
- mSourceRectHint.writeToParcel(out, 0);
- } else {
- out.writeInt(0);
- }
- }
-
- public static final @android.annotation.NonNull Creator<PictureInPictureArgs> CREATOR =
- new Creator<PictureInPictureArgs>() {
- public PictureInPictureArgs createFromParcel(Parcel in) {
- return new PictureInPictureArgs(in);
- }
- public PictureInPictureArgs[] newArray(int size) {
- return new PictureInPictureArgs[size];
- }
- };
-
- public static PictureInPictureArgs convert(PictureInPictureParams params) {
- return new PictureInPictureArgs(params.getAspectRatioRational(), params.getActions(),
- params.getSourceRectHint());
- }
-
- public static PictureInPictureParams convert(PictureInPictureArgs args) {
- return new PictureInPictureParams(args.getAspectRatioRational(), args.getActions(),
- args.getSourceRectHint());
- }
-}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index d082f33..4b9aebd 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6396,6 +6396,7 @@
/**
* @hide
*/
+ @UnsupportedAppUsage
public @Nullable ComponentName getProfileOwnerAsUser(final int userId) {
if (mService != null) {
try {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 31bbd16..39d63de 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1028,7 +1028,8 @@
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
@AdapterState
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(publicAlternatives = "Use {@link #getState()} instead to determine "
+ + "whether you can use BLE & BT classic.")
public int getLeState() {
int state = BluetoothAdapter.STATE_OFF;
@@ -1484,7 +1485,8 @@
* @return true if the scan mode was set, false otherwise
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(publicAlternatives = "Use {@link #ACTION_REQUEST_DISCOVERABLE}, which "
+ + "shows UI that confirms the user wants to go into discoverable mode.")
public boolean setScanMode(@ScanMode int mode, int duration) {
if (getState() != STATE_ON) {
return false;
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 388161d..c616044 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1051,7 +1051,7 @@
* @return the Bluetooth alias, or null if no alias or there was a problem
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(publicAlternatives = "Use {@link #getName()} instead.")
public String getAlias() {
final IBluetooth service = sService;
if (service == null) {
@@ -1100,7 +1100,7 @@
* @see #getAlias()
* @see #getName()
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(publicAlternatives = "Use {@link #getName()} instead.")
public String getAliasName() {
String name = getAlias();
if (name == null) {
@@ -1975,7 +1975,8 @@
* permissions.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(publicAlternatives = "Use "
+ + "{@link #createInsecureRfcommSocketToServiceRecord} instead.")
public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException {
if (!isBluetoothEnabled()) {
Log.e(TAG, "Bluetooth is not enabled");
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index c06b837..3a23808 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -77,7 +77,8 @@
private static final String TAG = "BluetoothServerSocket";
private static final boolean DBG = false;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(publicAlternatives = "Use public {@link BluetoothServerSocket} API "
+ + "instead.")
/*package*/ final BluetoothSocket mSocket;
private Handler mHandler;
private int mMessage;
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 3a1e2f5..a6e3153 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -131,7 +131,7 @@
private boolean mExcludeSdp = false; /* when true no SPP SDP record will be created */
private boolean mAuthMitm = false; /* when true Man-in-the-middle protection will be enabled*/
private boolean mMin16DigitPin = false; /* Minimum 16 digit pin for sec mode 2 connections */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(publicAlternatives = "Use {@link BluetoothSocket} public API instead.")
private ParcelFileDescriptor mPfd;
@UnsupportedAppUsage
private LocalSocket mSocket;
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 48588e6..1b31792 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -760,14 +760,20 @@
* </ul>
* <p>For devices at the LIMITED level or above:</p>
* <ul>
- * <li>For YUV_420_888 burst capture use case, this list will always include (<code>min</code>, <code>max</code>)
- * and (<code>max</code>, <code>max</code>) where <code>min</code> <= 15 and <code>max</code> = the maximum output frame rate of the
+ * <li>For devices that advertise NIR color filter arrangement in
+ * {@link CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT android.sensor.info.colorFilterArrangement}, this list will always include
+ * (<code>max</code>, <code>max</code>) where <code>max</code> = the maximum output frame rate of the maximum YUV_420_888
+ * output size.</li>
+ * <li>For devices advertising any color filter arrangement other than NIR, or devices not
+ * advertising color filter arrangement, this list will always include (<code>min</code>, <code>max</code>) and
+ * (<code>max</code>, <code>max</code>) where <code>min</code> <= 15 and <code>max</code> = the maximum output frame rate of the
* maximum YUV_420_888 output size.</li>
* </ul>
* <p><b>Units</b>: Frames per second (FPS)</p>
* <p>This key is available on all devices.</p>
*
* @see CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE
+ * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
*/
@PublicKey
@NonNull
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index fbfbfc0..111a8c4 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -655,7 +655,7 @@
* {@hide}
*/
@Deprecated
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
+ @UnsupportedAppUsage
public static final int TYPE_WIFI_P2P = 13;
/**
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 41efc50..e5f3d26 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -66,7 +66,6 @@
/** Force update of ifaces. */
void forceUpdateIfaces(
in Network[] defaultNetworks,
- in VpnInfo[] vpnArray,
in NetworkState[] networkStates,
in String activeIface);
/** Force update of statistics. */
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index e892b65..6c7aa13 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -18,11 +18,11 @@
import static android.os.Process.CLAT_UID;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
-import android.util.Slog;
import android.util.SparseBooleanArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -36,6 +36,7 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
+import java.util.function.Predicate;
/**
* Collection of active network statistics. Can contain summary details across
@@ -993,23 +994,33 @@
if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) {
return;
}
+ filter(e -> (limitUid == UID_ALL || limitUid == e.uid)
+ && (limitTag == TAG_ALL || limitTag == e.tag)
+ && (limitIfaces == INTERFACES_ALL
+ || ArrayUtils.contains(limitIfaces, e.iface)));
+ }
+ /**
+ * Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}.
+ *
+ * <p>This mutates the original structure in place.
+ */
+ public void filterDebugEntries() {
+ filter(e -> e.set < SET_DEBUG_START);
+ }
+
+ private void filter(Predicate<Entry> predicate) {
Entry entry = new Entry();
int nextOutputEntry = 0;
for (int i = 0; i < size; i++) {
entry = getValues(i, entry);
- final boolean matches =
- (limitUid == UID_ALL || limitUid == entry.uid)
- && (limitTag == TAG_ALL || limitTag == entry.tag)
- && (limitIfaces == INTERFACES_ALL
- || ArrayUtils.contains(limitIfaces, entry.iface));
-
- if (matches) {
- setValues(nextOutputEntry, entry);
+ if (predicate.test(entry)) {
+ if (nextOutputEntry != i) {
+ setValues(nextOutputEntry, entry);
+ }
nextOutputEntry++;
}
}
-
size = nextOutputEntry;
}
@@ -1175,133 +1186,221 @@
/**
* VPN accounting. Move some VPN's underlying traffic to other UIDs that use tun0 iface.
*
- * This method should only be called on delta NetworkStats. Do not call this method on a
- * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may
- * change over time.
+ * <p>This method should only be called on delta NetworkStats. Do not call this method on a
+ * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may change
+ * over time.
*
- * This method performs adjustments for one active VPN package and one VPN iface at a time.
- *
- * It is possible for the VPN software to use multiple underlying networks. This method
- * only migrates traffic for the primary underlying network.
+ * <p>This method performs adjustments for one active VPN package and one VPN iface at a time.
*
* @param tunUid uid of the VPN application
* @param tunIface iface of the vpn tunnel
- * @param underlyingIface the primary underlying network iface used by the VPN application
- * @return true if it successfully adjusts the accounting for VPN, false otherwise
+ * @param underlyingIfaces underlying network ifaces used by the VPN application
*/
- public boolean migrateTun(int tunUid, String tunIface, String underlyingIface) {
- Entry tunIfaceTotal = new Entry();
- Entry underlyingIfaceTotal = new Entry();
+ public void migrateTun(int tunUid, @NonNull String tunIface,
+ @NonNull String[] underlyingIfaces) {
+ // Combined usage by all apps using VPN.
+ final Entry tunIfaceTotal = new Entry();
+ // Usage by VPN, grouped by its {@code underlyingIfaces}.
+ final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.length];
+ // Usage by VPN, summed across all its {@code underlyingIfaces}.
+ final Entry underlyingIfacesTotal = new Entry();
- tunAdjustmentInit(tunUid, tunIface, underlyingIface, tunIfaceTotal, underlyingIfaceTotal);
+ for (int i = 0; i < perInterfaceTotal.length; i++) {
+ perInterfaceTotal[i] = new Entry();
+ }
- // If tunIface < underlyingIface, it leaves the overhead traffic in the VPN app.
- // If tunIface > underlyingIface, the VPN app doesn't get credit for data compression.
+ tunAdjustmentInit(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, perInterfaceTotal,
+ underlyingIfacesTotal);
+
+ // If tunIface < underlyingIfacesTotal, it leaves the overhead traffic in the VPN app.
+ // If tunIface > underlyingIfacesTotal, the VPN app doesn't get credit for data compression.
// Negative stats should be avoided.
- Entry pool = tunGetPool(tunIfaceTotal, underlyingIfaceTotal);
- if (pool.isEmpty()) {
- return true;
- }
- Entry moved =
- addTrafficToApplications(tunUid, tunIface, underlyingIface, tunIfaceTotal, pool);
- deductTrafficFromVpnApp(tunUid, underlyingIface, moved);
-
- if (!moved.isEmpty()) {
- Slog.wtf(TAG, "Failed to deduct underlying network traffic from VPN package. Moved="
- + moved);
- return false;
- }
- return true;
+ final Entry[] moved =
+ addTrafficToApplications(tunUid, tunIface, underlyingIfaces, tunIfaceTotal,
+ perInterfaceTotal, underlyingIfacesTotal);
+ deductTrafficFromVpnApp(tunUid, underlyingIfaces, moved);
}
/**
* Initializes the data used by the migrateTun() method.
*
- * This is the first pass iteration which does the following work:
- * (1) Adds up all the traffic through the tunUid's underlyingIface
- * (both foreground and background).
- * (2) Adds up all the traffic through tun0 excluding traffic from the vpn app itself.
+ * <p>This is the first pass iteration which does the following work:
+ *
+ * <ul>
+ * <li>Adds up all the traffic through the tunUid's underlyingIfaces (both foreground and
+ * background).
+ * <li>Adds up all the traffic through tun0 excluding traffic from the vpn app itself.
+ * </ul>
+ *
+ * @param tunUid uid of the VPN application
+ * @param tunIface iface of the vpn tunnel
+ * @param underlyingIfaces underlying network ifaces used by the VPN application
+ * @param tunIfaceTotal output parameter; combined data usage by all apps using VPN
+ * @param perInterfaceTotal output parameter; data usage by VPN app, grouped by its {@code
+ * underlyingIfaces}
+ * @param underlyingIfacesTotal output parameter; data usage by VPN, summed across all of its
+ * {@code underlyingIfaces}
*/
- private void tunAdjustmentInit(int tunUid, String tunIface, String underlyingIface,
- Entry tunIfaceTotal, Entry underlyingIfaceTotal) {
- Entry recycle = new Entry();
+ private void tunAdjustmentInit(int tunUid, @NonNull String tunIface,
+ @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal,
+ @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) {
+ final Entry recycle = new Entry();
for (int i = 0; i < size; i++) {
getValues(i, recycle);
if (recycle.uid == UID_ALL) {
throw new IllegalStateException(
"Cannot adjust VPN accounting on an iface aggregated NetworkStats.");
- } if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) {
+ }
+ if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) {
throw new IllegalStateException(
"Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*");
}
-
- if (recycle.uid == tunUid && recycle.tag == TAG_NONE
- && Objects.equals(underlyingIface, recycle.iface)) {
- underlyingIfaceTotal.add(recycle);
+ if (recycle.tag != TAG_NONE) {
+ // TODO(b/123666283): Take all tags for tunUid into account.
+ continue;
}
- if (recycle.uid != tunUid && recycle.tag == TAG_NONE
- && Objects.equals(tunIface, recycle.iface)) {
+ if (recycle.uid == tunUid) {
+ // Add up traffic through tunUid's underlying interfaces.
+ for (int j = 0; j < underlyingIfaces.length; j++) {
+ if (Objects.equals(underlyingIfaces[j], recycle.iface)) {
+ perInterfaceTotal[j].add(recycle);
+ underlyingIfacesTotal.add(recycle);
+ break;
+ }
+ }
+ } else if (tunIface.equals(recycle.iface)) {
// Add up all tunIface traffic excluding traffic from the vpn app itself.
tunIfaceTotal.add(recycle);
}
}
}
- private static Entry tunGetPool(Entry tunIfaceTotal, Entry underlyingIfaceTotal) {
- Entry pool = new Entry();
- pool.rxBytes = Math.min(tunIfaceTotal.rxBytes, underlyingIfaceTotal.rxBytes);
- pool.rxPackets = Math.min(tunIfaceTotal.rxPackets, underlyingIfaceTotal.rxPackets);
- pool.txBytes = Math.min(tunIfaceTotal.txBytes, underlyingIfaceTotal.txBytes);
- pool.txPackets = Math.min(tunIfaceTotal.txPackets, underlyingIfaceTotal.txPackets);
- pool.operations = Math.min(tunIfaceTotal.operations, underlyingIfaceTotal.operations);
- return pool;
- }
+ /**
+ * Distributes traffic across apps that are using given {@code tunIface}, and returns the total
+ * traffic that should be moved off of {@code tunUid} grouped by {@code underlyingIfaces}.
+ *
+ * @param tunUid uid of the VPN application
+ * @param tunIface iface of the vpn tunnel
+ * @param underlyingIfaces underlying network ifaces used by the VPN application
+ * @param tunIfaceTotal combined data usage across all apps using {@code tunIface}
+ * @param perInterfaceTotal data usage by VPN app, grouped by its {@code underlyingIfaces}
+ * @param underlyingIfacesTotal data usage by VPN, summed across all of its {@code
+ * underlyingIfaces}
+ */
+ private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface,
+ @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal,
+ @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) {
+ // Traffic that should be moved off of each underlying interface for tunUid (see
+ // deductTrafficFromVpnApp below).
+ final Entry[] moved = new Entry[underlyingIfaces.length];
+ for (int i = 0; i < underlyingIfaces.length; i++) {
+ moved[i] = new Entry();
+ }
- private Entry addTrafficToApplications(int tunUid, String tunIface, String underlyingIface,
- Entry tunIfaceTotal, Entry pool) {
- Entry moved = new Entry();
- Entry tmpEntry = new Entry();
- tmpEntry.iface = underlyingIface;
- for (int i = 0; i < size; i++) {
- // the vpn app is excluded from the redistribution but all moved traffic will be
- // deducted from the vpn app (see deductTrafficFromVpnApp below).
- if (Objects.equals(iface[i], tunIface) && uid[i] != tunUid) {
- if (tunIfaceTotal.rxBytes > 0) {
- tmpEntry.rxBytes = pool.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes;
- } else {
- tmpEntry.rxBytes = 0;
- }
- if (tunIfaceTotal.rxPackets > 0) {
- tmpEntry.rxPackets = pool.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets;
- } else {
- tmpEntry.rxPackets = 0;
- }
- if (tunIfaceTotal.txBytes > 0) {
- tmpEntry.txBytes = pool.txBytes * txBytes[i] / tunIfaceTotal.txBytes;
- } else {
- tmpEntry.txBytes = 0;
- }
- if (tunIfaceTotal.txPackets > 0) {
- tmpEntry.txPackets = pool.txPackets * txPackets[i] / tunIfaceTotal.txPackets;
- } else {
- tmpEntry.txPackets = 0;
- }
- if (tunIfaceTotal.operations > 0) {
- tmpEntry.operations =
- pool.operations * operations[i] / tunIfaceTotal.operations;
- } else {
- tmpEntry.operations = 0;
- }
- tmpEntry.uid = uid[i];
- tmpEntry.tag = tag[i];
+ final Entry tmpEntry = new Entry();
+ final int origSize = size;
+ for (int i = 0; i < origSize; i++) {
+ if (!Objects.equals(iface[i], tunIface)) {
+ // Consider only entries that go onto the VPN interface.
+ continue;
+ }
+ if (uid[i] == tunUid) {
+ // Exclude VPN app from the redistribution, as it can choose to create packet
+ // streams by writing to itself.
+ continue;
+ }
+ tmpEntry.uid = uid[i];
+ tmpEntry.tag = tag[i];
+ tmpEntry.metered = metered[i];
+ tmpEntry.roaming = roaming[i];
+ tmpEntry.defaultNetwork = defaultNetwork[i];
+
+ // In a first pass, compute this entry's total share of data across all
+ // underlyingIfaces. This is computed on the basis of the share of this entry's usage
+ // over tunIface.
+ // TODO: Consider refactoring first pass into a separate helper method.
+ long totalRxBytes = 0;
+ if (tunIfaceTotal.rxBytes > 0) {
+ // Note - The multiplication below should not overflow since NetworkStatsService
+ // processes this every time device has transmitted/received amount equivalent to
+ // global threshold alert (~ 2MB) across all interfaces.
+ final long rxBytesAcrossUnderlyingIfaces =
+ underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes;
+ // app must not be blamed for more than it consumed on tunIface
+ totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces);
+ }
+ long totalRxPackets = 0;
+ if (tunIfaceTotal.rxPackets > 0) {
+ final long rxPacketsAcrossUnderlyingIfaces =
+ underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets;
+ totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces);
+ }
+ long totalTxBytes = 0;
+ if (tunIfaceTotal.txBytes > 0) {
+ final long txBytesAcrossUnderlyingIfaces =
+ underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes;
+ totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces);
+ }
+ long totalTxPackets = 0;
+ if (tunIfaceTotal.txPackets > 0) {
+ final long txPacketsAcrossUnderlyingIfaces =
+ underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets;
+ totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces);
+ }
+ long totalOperations = 0;
+ if (tunIfaceTotal.operations > 0) {
+ final long operationsAcrossUnderlyingIfaces =
+ underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations;
+ totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces);
+ }
+ // In a second pass, distribute these values across interfaces in the proportion that
+ // each interface represents of the total traffic of the underlying interfaces.
+ for (int j = 0; j < underlyingIfaces.length; j++) {
+ tmpEntry.iface = underlyingIfaces[j];
+ tmpEntry.rxBytes = 0;
+ // Reset 'set' to correct value since it gets updated when adding debug info below.
tmpEntry.set = set[i];
- tmpEntry.metered = metered[i];
- tmpEntry.roaming = roaming[i];
- tmpEntry.defaultNetwork = defaultNetwork[i];
+ if (underlyingIfacesTotal.rxBytes > 0) {
+ tmpEntry.rxBytes =
+ totalRxBytes
+ * perInterfaceTotal[j].rxBytes
+ / underlyingIfacesTotal.rxBytes;
+ }
+ tmpEntry.rxPackets = 0;
+ if (underlyingIfacesTotal.rxPackets > 0) {
+ tmpEntry.rxPackets =
+ totalRxPackets
+ * perInterfaceTotal[j].rxPackets
+ / underlyingIfacesTotal.rxPackets;
+ }
+ tmpEntry.txBytes = 0;
+ if (underlyingIfacesTotal.txBytes > 0) {
+ tmpEntry.txBytes =
+ totalTxBytes
+ * perInterfaceTotal[j].txBytes
+ / underlyingIfacesTotal.txBytes;
+ }
+ tmpEntry.txPackets = 0;
+ if (underlyingIfacesTotal.txPackets > 0) {
+ tmpEntry.txPackets =
+ totalTxPackets
+ * perInterfaceTotal[j].txPackets
+ / underlyingIfacesTotal.txPackets;
+ }
+ tmpEntry.operations = 0;
+ if (underlyingIfacesTotal.operations > 0) {
+ tmpEntry.operations =
+ totalOperations
+ * perInterfaceTotal[j].operations
+ / underlyingIfacesTotal.operations;
+ }
+ // tmpEntry now contains the migrated data of the i-th entry for the j-th underlying
+ // interface. Add that data usage to this object.
combineValues(tmpEntry);
if (tag[i] == TAG_NONE) {
- moved.add(tmpEntry);
+ // Add the migrated data to moved so it is deducted from the VPN app later.
+ moved[j].add(tmpEntry);
// Add debug info
tmpEntry.set = SET_DBG_VPN_IN;
combineValues(tmpEntry);
@@ -1311,38 +1410,45 @@
return moved;
}
- private void deductTrafficFromVpnApp(int tunUid, String underlyingIface, Entry moved) {
- // Add debug info
- moved.uid = tunUid;
- moved.set = SET_DBG_VPN_OUT;
- moved.tag = TAG_NONE;
- moved.iface = underlyingIface;
- moved.metered = METERED_ALL;
- moved.roaming = ROAMING_ALL;
- moved.defaultNetwork = DEFAULT_NETWORK_ALL;
- combineValues(moved);
+ private void deductTrafficFromVpnApp(
+ int tunUid,
+ @NonNull String[] underlyingIfaces,
+ @NonNull Entry[] moved) {
+ for (int i = 0; i < underlyingIfaces.length; i++) {
+ moved[i].uid = tunUid;
+ // Add debug info
+ moved[i].set = SET_DBG_VPN_OUT;
+ moved[i].tag = TAG_NONE;
+ moved[i].iface = underlyingIfaces[i];
+ moved[i].metered = METERED_ALL;
+ moved[i].roaming = ROAMING_ALL;
+ moved[i].defaultNetwork = DEFAULT_NETWORK_ALL;
+ combineValues(moved[i]);
- // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
- // the TAG_NONE traffic.
- //
- // Relies on the fact that the underlying traffic only has state ROAMING_NO and METERED_NO,
- // which should be the case as it comes directly from the /proc file. We only blend in the
- // roaming data after applying these adjustments, by checking the NetworkIdentity of the
- // underlying iface.
- int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE,
- METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
- if (idxVpnBackground != -1) {
- tunSubtract(idxVpnBackground, this, moved);
- }
+ // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
+ // the TAG_NONE traffic.
+ //
+ // Relies on the fact that the underlying traffic only has state ROAMING_NO and
+ // METERED_NO, which should be the case as it comes directly from the /proc file.
+ // We only blend in the roaming data after applying these adjustments, by checking the
+ // NetworkIdentity of the underlying iface.
+ final int idxVpnBackground = findIndex(underlyingIfaces[i], tunUid, SET_DEFAULT,
+ TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
+ if (idxVpnBackground != -1) {
+ // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed
+ // from foreground usage.
+ tunSubtract(idxVpnBackground, this, moved[i]);
+ }
- int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE,
- METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
- if (idxVpnForeground != -1) {
- tunSubtract(idxVpnForeground, this, moved);
+ final int idxVpnForeground = findIndex(underlyingIfaces[i], tunUid, SET_FOREGROUND,
+ TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
+ if (idxVpnForeground != -1) {
+ tunSubtract(idxVpnForeground, this, moved[i]);
+ }
}
}
- private static void tunSubtract(int i, NetworkStats left, Entry right) {
+ private static void tunSubtract(int i, @NonNull NetworkStats left, @NonNull Entry right) {
long rxBytes = Math.min(left.rxBytes[i], right.rxBytes);
left.rxBytes[i] -= rxBytes;
right.rxBytes -= rxBytes;
diff --git a/core/java/android/net/SocketKeepalive.java b/core/java/android/net/SocketKeepalive.java
index 46eddde..ec73866 100644
--- a/core/java/android/net/SocketKeepalive.java
+++ b/core/java/android/net/SocketKeepalive.java
@@ -44,9 +44,11 @@
* {@link SocketKeepalive.Callback#onStopped} if the operation was successful or
* {@link SocketKeepalive.Callback#onError} if an error occurred.
*
- * The device SHOULD support keepalive offload. If it does not, it MUST reply with
+ * For cellular, the device MUST support at least 1 keepalive slot.
+ *
+ * For WiFi, the device SHOULD support keepalive offload. If it does not, it MUST reply with
* {@link SocketKeepalive.Callback#onError} with {@code ERROR_UNSUPPORTED} to any keepalive offload
- * request. If it does, it MUST support at least 3 concurrent keepalive slots per transport.
+ * request. If it does, it MUST support at least 3 concurrent keepalive slots.
*/
public abstract class SocketKeepalive implements AutoCloseable {
static final String TAG = "SocketKeepalive";
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 8cf182b4..44d977a 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -1983,13 +1983,9 @@
*/
static abstract class AbstractPart {
- /**
- * Enum which indicates which representation of a given part we have.
- */
- static class Representation {
- static final int ENCODED = 1;
- static final int DECODED = 2;
- }
+ // Possible values of mCanonicalRepresentation.
+ static final int REPRESENTATION_ENCODED = 1;
+ static final int REPRESENTATION_DECODED = 2;
volatile String encoded;
volatile String decoded;
@@ -1997,11 +1993,11 @@
AbstractPart(String encoded, String decoded) {
if (encoded != NOT_CACHED) {
- this.mCanonicalRepresentation = Representation.ENCODED;
+ this.mCanonicalRepresentation = REPRESENTATION_ENCODED;
this.encoded = encoded;
this.decoded = NOT_CACHED;
} else if (decoded != NOT_CACHED) {
- this.mCanonicalRepresentation = Representation.DECODED;
+ this.mCanonicalRepresentation = REPRESENTATION_DECODED;
this.encoded = NOT_CACHED;
this.decoded = decoded;
} else {
@@ -2019,9 +2015,9 @@
final void writeTo(Parcel parcel) {
final String canonicalValue;
- if (mCanonicalRepresentation == Representation.ENCODED) {
+ if (mCanonicalRepresentation == REPRESENTATION_ENCODED) {
canonicalValue = encoded;
- } else if (mCanonicalRepresentation == Representation.DECODED) {
+ } else if (mCanonicalRepresentation == REPRESENTATION_DECODED) {
canonicalValue = decoded;
} else {
throw new IllegalArgumentException("Unknown representation: "
@@ -2066,9 +2062,9 @@
int representation = parcel.readInt();
String value = parcel.readString();
switch (representation) {
- case Representation.ENCODED:
+ case REPRESENTATION_ENCODED:
return fromEncoded(value);
- case Representation.DECODED:
+ case REPRESENTATION_DECODED:
return fromDecoded(value);
default:
throw new IllegalArgumentException("Unknown representation: "
@@ -2254,9 +2250,9 @@
static PathPart readFrom(Parcel parcel) {
int representation = parcel.readInt();
switch (representation) {
- case Representation.ENCODED:
+ case REPRESENTATION_ENCODED:
return fromEncoded(parcel.readString());
- case Representation.DECODED:
+ case REPRESENTATION_DECODED:
return fromDecoded(parcel.readString());
default:
throw new IllegalArgumentException("Unknown representation: " + representation);
diff --git a/core/java/android/net/util/KeepaliveUtils.java b/core/java/android/net/util/KeepaliveUtils.java
index 569fed1..bfc4563 100644
--- a/core/java/android/net/util/KeepaliveUtils.java
+++ b/core/java/android/net/util/KeepaliveUtils.java
@@ -34,9 +34,6 @@
public static final String TAG = "KeepaliveUtils";
- // Minimum supported keepalive count per transport if the network supports keepalive.
- public static final int MIN_SUPPORTED_KEEPALIVE_COUNT = 3;
-
public static class KeepaliveDeviceConfigurationException extends AndroidRuntimeException {
public KeepaliveDeviceConfigurationException(final String msg) {
super(msg);
@@ -84,10 +81,7 @@
throw new KeepaliveDeviceConfigurationException("Invalid transport " + transport);
}
- // Customized values should be either 0 to indicate the network doesn't support
- // keepalive offload, or a positive value that is at least
- // MIN_SUPPORTED_KEEPALIVE_COUNT if supported.
- if (supported != 0 && supported < MIN_SUPPORTED_KEEPALIVE_COUNT) {
+ if (supported < 0) {
throw new KeepaliveDeviceConfigurationException(
"Invalid supported count " + supported + " for "
+ NetworkCapabilities.transportNameOf(transport));
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 2fff595..535d887 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1289,20 +1289,6 @@
}
}
- /**
- * Returns whether the screen brightness is currently boosted to maximum, caused by a call
- * to {@link #boostScreenBrightness(long)}.
- * @return {@code True} if the screen brightness is currently boosted. {@code False} otherwise.
- *
- * @deprecated This call is rarely used and will be phased out soon.
- * @hide
- * @removed
- */
- @SystemApi @Deprecated
- public boolean isScreenBrightnessBoosted() {
- return false;
- }
-
/**
* Returns true if the specified wake lock level is supported.
*
@@ -2031,18 +2017,6 @@
public static final String EXTRA_POWER_SAVE_MODE = "mode";
/**
- * Intent that is broadcast when the state of {@link #isScreenBrightnessBoosted()} has changed.
- * This broadcast is only sent to registered receivers.
- *
- * @deprecated This intent is rarely used and will be phased out soon.
- * @hide
- * @removed
- **/
- @SystemApi @Deprecated
- public static final String ACTION_SCREEN_BRIGHTNESS_BOOST_CHANGED
- = "android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED";
-
- /**
* Constant for PreIdleTimeout normal mode (default mode, not short nor extend timeout) .
* @hide
*/
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 8512a0b..905c781 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -20,6 +20,7 @@
import android.annotation.UnsupportedAppUsage;
import android.app.Notification;
import android.app.NotificationManager;
+import android.app.Person;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -32,6 +33,8 @@
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import java.util.ArrayList;
+
/**
* Class encapsulating a Notification. Sent by the NotificationManagerService to clients including
* the status bar and any {@link android.service.notification.NotificationListenerService}s.
@@ -166,6 +169,7 @@
/**
* Returns true if application asked that this notification be part of a group.
+ *
* @hide
*/
public boolean isAppGroup() {
@@ -203,18 +207,16 @@
return 0;
}
- public static final @android.annotation.NonNull Parcelable.Creator<StatusBarNotification> CREATOR
- = new Parcelable.Creator<StatusBarNotification>()
- {
- public StatusBarNotification createFromParcel(Parcel parcel)
- {
- return new StatusBarNotification(parcel);
- }
+ public static final @android.annotation.NonNull
+ Parcelable.Creator<StatusBarNotification> CREATOR =
+ new Parcelable.Creator<StatusBarNotification>() {
+ public StatusBarNotification createFromParcel(Parcel parcel) {
+ return new StatusBarNotification(parcel);
+ }
- public StatusBarNotification[] newArray(int size)
- {
- return new StatusBarNotification[size];
- }
+ public StatusBarNotification[] newArray(int size) {
+ return new StatusBarNotification[size];
+ }
};
/**
@@ -243,14 +245,16 @@
this.key, this.notification);
}
- /** Convenience method to check the notification's flags for
+ /**
+ * Convenience method to check the notification's flags for
* {@link Notification#FLAG_ONGOING_EVENT}.
*/
public boolean isOngoing() {
return (notification.flags & Notification.FLAG_ONGOING_EVENT) != 0;
}
- /** Convenience method to check the notification's flags for
+ /**
+ * Convenience method to check the notification's flags for
* either {@link Notification#FLAG_ONGOING_EVENT} or
* {@link Notification#FLAG_NO_CLEAR}.
*/
@@ -274,13 +278,15 @@
return pkg;
}
- /** The id supplied to {@link android.app.NotificationManager#notify(int,Notification)}. */
+ /** The id supplied to {@link android.app.NotificationManager#notify(int, Notification)}. */
public int getId() {
return id;
}
- /** The tag supplied to {@link android.app.NotificationManager#notify(int,Notification)},
- * or null if no tag was specified. */
+ /**
+ * The tag supplied to {@link android.app.NotificationManager#notify(int, Notification)},
+ * or null if no tag was specified.
+ */
public String getTag() {
return tag;
}
@@ -307,8 +313,10 @@
return initialPid;
}
- /** The {@link android.app.Notification} supplied to
- * {@link android.app.NotificationManager#notify(int,Notification)}. */
+ /**
+ * The {@link android.app.Notification} supplied to
+ * {@link android.app.NotificationManager#notify(int, Notification)}.
+ */
public Notification getNotification() {
return notification;
}
@@ -320,7 +328,8 @@
return user;
}
- /** The time (in {@link System#currentTimeMillis} time) the notification was posted,
+ /**
+ * The time (in {@link System#currentTimeMillis} time) the notification was posted,
* which may be different than {@link android.app.Notification#when}.
*/
public long getPostTime() {
@@ -343,6 +352,7 @@
/**
* The ID passed to setGroup(), or the override, or null.
+ *
* @hide
*/
public String getGroup() {
@@ -398,10 +408,11 @@
/**
* Returns a LogMaker that contains all basic information of the notification.
+ *
* @hide
*/
public LogMaker getLogMaker() {
- return new LogMaker(MetricsEvent.VIEW_UNKNOWN).setPackageName(getPackageName())
+ LogMaker logMaker = new LogMaker(MetricsEvent.VIEW_UNKNOWN).setPackageName(getPackageName())
.addTaggedData(MetricsEvent.NOTIFICATION_ID, getId())
.addTaggedData(MetricsEvent.NOTIFICATION_TAG, getTag())
.addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID, getChannelIdLogTag())
@@ -410,6 +421,21 @@
getNotification().isGroupSummary() ? 1 : 0)
.addTaggedData(MetricsProto.MetricsEvent.FIELD_NOTIFICATION_CATEGORY,
getNotification().category);
+ if (getNotification().extras != null) {
+ // Log the style used, if present. We only log the hash here, as notification log
+ // events are frequent, while there are few styles (hence low chance of collisions).
+ String template = getNotification().extras.getString(Notification.EXTRA_TEMPLATE);
+ if (template != null && !template.isEmpty()) {
+ logMaker.addTaggedData(MetricsEvent.FIELD_NOTIFICATION_STYLE,
+ template.hashCode());
+ }
+ ArrayList<Person> people = getNotification().extras.getParcelableArrayList(
+ Notification.EXTRA_PEOPLE_LIST);
+ if (people != null && !people.isEmpty()) {
+ logMaker.addTaggedData(MetricsEvent.FIELD_NOTIFICATION_PEOPLE, people.size());
+ }
+ }
+ return logMaker;
}
private String getGroupLogTag() {
@@ -433,6 +459,6 @@
}
String hash = Integer.toHexString(logTag.hashCode());
return logTag.substring(0, MAX_LOG_TAG_LENGTH - hash.length() - 1) + "-"
- + hash;
+ + hash;
}
}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index d645e3f..60dbf84 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -105,7 +105,7 @@
static final String TAG = "WallpaperService";
static final boolean DEBUG = false;
-
+
private static final int DO_ATTACH = 10;
private static final int DO_DETACH = 20;
private static final int DO_SET_DESIRED_SIZE = 30;
@@ -126,7 +126,7 @@
private final ArrayList<Engine> mActiveEngines
= new ArrayList<Engine>();
-
+
static final class WallpaperCommand {
String action;
int x;
@@ -145,7 +145,7 @@
*/
public class Engine {
IWallpaperEngineWrapper mIWallpaperEngine;
-
+
// Copies from mIWallpaperEngine.
HandlerCaller mCaller;
IWallpaperConnection mConnection;
@@ -155,7 +155,7 @@
boolean mVisible;
boolean mReportedVisible;
boolean mDestroyed;
-
+
// Current window state.
boolean mCreated;
boolean mSurfaceCreated;
@@ -258,7 +258,7 @@
}
super.setFixedSize(width, height);
}
-
+
public void setKeepScreenOn(boolean screenOn) {
throw new UnsupportedOperationException(
"Wallpapers do not support keep screen on");
@@ -403,14 +403,14 @@
mClockFunction = clockFunction;
mHandler = handler;
}
-
+
/**
* Provides access to the surface in which this wallpaper is drawn.
*/
public SurfaceHolder getSurfaceHolder() {
return mSurfaceHolder;
}
-
+
/**
* Convenience for {@link WallpaperManager#getDesiredMinimumWidth()
* WallpaperManager.getDesiredMinimumWidth()}, returning the width
@@ -419,7 +419,7 @@
public int getDesiredMinimumWidth() {
return mIWallpaperEngine.mReqWidth;
}
-
+
/**
* Convenience for {@link WallpaperManager#getDesiredMinimumHeight()
* WallpaperManager.getDesiredMinimumHeight()}, returning the height
@@ -437,7 +437,7 @@
public boolean isVisible() {
return mReportedVisible;
}
-
+
/**
* Returns true if this engine is running in preview mode -- that is,
* it is being shown to the user before they select it as the actual
@@ -456,7 +456,7 @@
public boolean isInAmbientMode() {
return mIsInAmbientMode;
}
-
+
/**
* Control whether this wallpaper will receive raw touch events
* from the window manager as the user interacts with the window
@@ -557,7 +557,7 @@
* {@link WallpaperManager#sendWallpaperCommand}.
* The default implementation does nothing, and always returns null
* as the result.
- *
+ *
* @param action The name of the command to perform. This tells you
* what to do and how to interpret the rest of the arguments.
* @param x Generic integer parameter.
@@ -794,7 +794,7 @@
}
mLayout.format = mFormat;
-
+
mCurWindowFlags = mWindowFlags;
mLayout.flags = mWindowFlags
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
@@ -1020,7 +1020,7 @@
mIsCreating = false;
mSurfaceCreated = true;
if (redrawNeeded) {
- mSession.finishDrawing(mWindow);
+ mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
}
mIWallpaperEngine.reportShown();
}
@@ -1045,7 +1045,7 @@
mSurfaceHolder.setSizeFromLayout();
mInitializing = true;
mSession = WindowManagerGlobal.getWindowSession();
-
+
mWindow.setSession(mSession);
mLayout.packageName = getPackageName();
@@ -1149,7 +1149,7 @@
}
}
}
-
+
void doOffsetsChanged(boolean always) {
if (mDestroyed) {
return;
@@ -1187,7 +1187,7 @@
mOffsetsChanged = true;
}
}
-
+
if (sync) {
try {
if (DEBUG) Log.v(TAG, "Reporting offsets change complete");
@@ -1196,7 +1196,7 @@
}
}
}
-
+
void doCommand(WallpaperCommand cmd) {
Bundle result;
if (!mDestroyed) {
@@ -1213,7 +1213,7 @@
}
}
}
-
+
void reportSurfaceDestroyed() {
if (mSurfaceCreated) {
mSurfaceCreated = false;
@@ -1229,12 +1229,12 @@
onSurfaceDestroyed(mSurfaceHolder);
}
}
-
+
void detach() {
if (mDestroyed) {
return;
}
-
+
mDestroyed = true;
if (mIWallpaperEngine.mDisplayManager != null) {
@@ -1246,9 +1246,9 @@
if (DEBUG) Log.v(TAG, "onVisibilityChanged(false): " + this);
onVisibilityChanged(false);
}
-
+
reportSurfaceDestroyed();
-
+
if (DEBUG) Log.v(TAG, "onDestroy(): " + this);
onDestroy();
@@ -1256,18 +1256,18 @@
try {
if (DEBUG) Log.v(TAG, "Removing window and destroying surface "
+ mSurfaceHolder.getSurface() + " of: " + this);
-
+
if (mInputEventReceiver != null) {
mInputEventReceiver.dispose();
mInputEventReceiver = null;
}
-
+
mSession.remove(mWindow);
} catch (RemoteException e) {
}
mSurfaceHolder.mSurface.release();
mCreated = false;
-
+
// Dispose the input channel after removing the window so the Window Manager
// doesn't interpret the input channel being closed as an abnormal termination.
if (mInputChannel != null) {
diff --git a/core/java/android/util/TimingsTraceLog.java b/core/java/android/util/TimingsTraceLog.java
index 3e6f09b..bc21722 100644
--- a/core/java/android/util/TimingsTraceLog.java
+++ b/core/java/android/util/TimingsTraceLog.java
@@ -16,16 +16,22 @@
package android.util;
+import android.annotation.NonNull;
import android.os.Build;
import android.os.SystemClock;
import android.os.Trace;
import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.Deque;
+import java.util.List;
/**
* Helper class for reporting boot and shutdown timing metrics.
- * <p>Note: This class is not thread-safe. Use a separate copy for other threads</p>
+ *
+ * <p><b>NOTE:</b> This class is not thread-safe. Use a separate copy for other threads.
+ *
* @hide
*/
public class TimingsTraceLog {
@@ -88,4 +94,21 @@
public void logDuration(String name, long timeMs) {
Slog.d(mTag, name + " took to complete: " + timeMs + "ms");
}
+
+ /**
+ * Gets the names of the traces that {@link #traceBegin(String) have begun} but
+ * {@link #traceEnd() have not finished} yet.
+ *
+ * <p><b>NOTE:</b> this method is expensive and it should not be used in "production" - it
+ * should only be used for debugging purposes during development (and/or guarded by
+ * static {@code DEBUG} constants that are {@code false}).
+ */
+ @NonNull
+ public final List<String> getUnfinishedTracesForDebug() {
+ if (mStartTimes == null || mStartTimes.isEmpty()) return Collections.emptyList();
+
+ final ArrayList<String> stack = new ArrayList<>(mStartTimes.size());
+ mStartTimes.descendingIterator().forEachRemaining((pair) -> stack.add(pair.first));
+ return stack;
+ }
}
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index caab00c..37b6f13 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -2,15 +2,15 @@
**
** 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
+** 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
+** 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.
+** 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.
*/
@@ -31,6 +31,7 @@
import android.view.InsetsState;
import android.view.Surface;
import android.view.SurfaceControl;
+import android.view.Transaction;
import java.util.List;
@@ -57,7 +58,7 @@
* position should be ignored) and surface of the window. The surface
* will be invalid if the window is currently hidden, else you can use it
* to draw the window's contents.
- *
+ *
* @param window The window being modified.
* @param seq Ordering sequence number.
* @param attrs If non-null, new attributes to apply to the window.
@@ -147,8 +148,15 @@
*/
void getDisplayFrame(IWindow window, out Rect outDisplayFrame);
+ /**
+ * Called when the client has finished drawing the surface, if needed.
+ *
+ * @param postDrawTransaction transaction filled by the client that can be
+ * used to synchronize any post draw transactions with the server. Transaction
+ * is null if there is no sync required.
+ */
@UnsupportedAppUsage
- void finishDrawing(IWindow window);
+ void finishDrawing(IWindow window, in Transaction postDrawTransaction);
@UnsupportedAppUsage
void setInTouchMode(boolean showFocus);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index bb169e0..c1633ae5 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -2693,6 +2693,14 @@
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.
+ *
+ * @param dest parcel to write the transaction to
+ * @param flags
+ */
@Override
public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) {
if (mNativeObject == 0) {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 3535447..4891b43c 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -98,7 +98,8 @@
* artifacts may occur on previous versions of the platform when its window is
* positioned asynchronously.</p>
*/
-public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback {
+public class SurfaceView extends View
+ implements ViewRootImpl.WindowStoppedCallback, ViewRootImpl.SurfaceChangedCallback {
private static final String TAG = "SurfaceView";
private static final boolean DEBUG = false;
@@ -120,7 +121,7 @@
boolean mDrawFinished = false;
final Rect mScreenRect = new Rect();
- SurfaceSession mSurfaceSession;
+ final SurfaceSession mSurfaceSession = new SurfaceSession();
SurfaceControl mSurfaceControl;
// In the case of format changes we switch out the surface in-place
@@ -266,11 +267,22 @@
updateSurface();
}
+ /** @hide */
+ @Override
+ public void surfaceChangedCallback(SurfaceControl.Transaction transaction) {
+ if (getViewRootImpl() != null && mBackgroundControl != null && mSurfaceControl != null) {
+ SurfaceControl sc = getViewRootImpl().getSurfaceControl();
+ transaction.setRelativeLayer(mBackgroundControl, sc, Integer.MIN_VALUE);
+ transaction.setRelativeLayer(mSurfaceControl, sc, mSubLayer);
+ }
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getViewRootImpl().addWindowStoppedCallback(this);
+ getViewRootImpl().addSurfaceChangedCallback(this);
mWindowStopped = false;
mViewVisibility = getVisibility() == VISIBLE;
@@ -356,6 +368,7 @@
// the SurfaceHolder forward, most live wallpapers do it.
if (viewRoot != null) {
viewRoot.removeWindowStoppedCallback(this);
+ viewRoot.removeSurfaceChangedCallback(this);
}
mAttachedToWindow = false;
@@ -637,21 +650,34 @@
mScreenRect.offset(surfaceInsets.left, surfaceInsets.top);
if (creating) {
- viewRoot.createBoundsSurface(mSubLayer);
- mSurfaceSession = new SurfaceSession();
mDeferredDestroySurfaceControl = mSurfaceControl;
updateOpaqueFlag();
+ // SurfaceView hierarchy
+ // ViewRootImpl surface
+ // - bounds layer (crops all child surfaces to parent surface insets)
+ // - SurfaceView surface (drawn relative to ViewRootImpl surface)
+ // - Background color layer (drawn behind all SurfaceView surfaces)
+ //
+ // The bounds layer is used to crop the surface view so it does not draw into
+ // the parent surface inset region. Since there can be multiple surface views
+ // below or above the parent surface, one option is to create multiple bounds
+ // layer for each z order. The other option, the one implement is to create
+ // a single bounds layer and set z order for each child surface relative to the
+ // parent surface.
+ // When creating the surface view, we parent it to the bounds layer and then
+ // set the relative z order. When the parent surface changes, we have to
+ // make sure to update the relative z via ViewRootImpl.SurfaceChangedCallback.
final String name = "SurfaceView - " + viewRoot.getTitle().toString();
-
- mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
- .setName(name)
- .setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0)
- .setBufferSize(mSurfaceWidth, mSurfaceHeight)
- .setFormat(mFormat)
- .setParent(viewRoot.getSurfaceControl())
- .setFlags(mSurfaceFlags)
- .build();
+ mSurfaceControl =
+ new SurfaceControl.Builder(mSurfaceSession)
+ .setName(name)
+ .setOpaque((mSurfaceFlags & SurfaceControl.OPAQUE) != 0)
+ .setBufferSize(mSurfaceWidth, mSurfaceHeight)
+ .setFormat(mFormat)
+ .setParent(viewRoot.getBoundsLayer())
+ .setFlags(mSurfaceFlags)
+ .build();
mBackgroundControl = new SurfaceControl.Builder(mSurfaceSession)
.setName("Background for -" + name)
.setOpaque(true)
@@ -674,7 +700,7 @@
SurfaceControl.openTransaction();
try {
- mSurfaceControl.setLayer(mSubLayer);
+ mSurfaceControl.setRelativeLayer(viewRoot.getSurfaceControl(), mSubLayer);
if (mViewVisibility) {
mSurfaceControl.show();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index dfb7e89..16de906 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -68,6 +68,7 @@
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
@@ -476,17 +477,19 @@
@UnsupportedAppUsage
public final Surface mSurface = new Surface();
private final SurfaceControl mSurfaceControl = new SurfaceControl();
+ private IBinder mPreviousSurfaceControlHandle = null;
+
+ private final Transaction mChangeSurfaceTransaction = new Transaction();
+ private final SurfaceSession mSurfaceSession = new SurfaceSession();
/**
- * Child surface of {@code mSurface} with the same bounds as its parent, and crop bounds
- * are set to the parent's bounds adjusted for surface insets. This surface is created when
- * {@link ViewRootImpl#createBoundsSurface(int)} is called.
- * By parenting to this bounds surface, child surfaces can ensure they do not draw into the
- * surface inset regions set by the parent window.
+ * Child container layer of {@code mSurface} with the same bounds as its parent, and cropped to
+ * the surface insets. This surface is created only if a client requests it via {@link
+ * #getBoundsLayer()}. By parenting to this bounds surface, child surfaces can ensure they do
+ * not draw into the surface inset regions set by the parent window.
*/
- public final Surface mBoundsSurface = new Surface();
- private SurfaceSession mSurfaceSession;
- private SurfaceControl mBoundsSurfaceControl;
+ private SurfaceControl mBoundsLayer;
+
private final Transaction mTransaction = new Transaction();
@UnsupportedAppUsage
@@ -1576,65 +1579,76 @@
}
}
- /**
- * Creates a surface as a child of {@code mSurface} with the same bounds as its parent and
- * crop bounds set to the parent's bounds adjusted for surface insets.
- *
- * @param zOrderLayer Z order relative to the parent surface.
- */
- public void createBoundsSurface(int zOrderLayer) {
- if (mSurfaceSession == null) {
- mSurfaceSession = new SurfaceSession();
- }
- if (mBoundsSurfaceControl != null && mBoundsSurface.isValid()) {
- return; // surface control for bounds surface already exists.
- }
+ /** Register callback to be notified when the ViewRootImpl surface changes. */
+ interface SurfaceChangedCallback {
+ void surfaceChangedCallback(SurfaceControl.Transaction transaction);
+ }
- mBoundsSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
+ private final ArrayList<SurfaceChangedCallback> mSurfaceChangedCallbacks = new ArrayList<>();
+ void addSurfaceChangedCallback(SurfaceChangedCallback c) {
+ mSurfaceChangedCallbacks.add(c);
+ }
+
+ void removeSurfaceChangedCallback(SurfaceChangedCallback c) {
+ mSurfaceChangedCallbacks.remove(c);
+ }
+
+ private void notifySurfaceChanged(SurfaceControl.Transaction transaction) {
+ for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) {
+ mSurfaceChangedCallbacks.get(i).surfaceChangedCallback(transaction);
+ }
+ }
+
+ /**
+ * Returns a child layer with the same bounds as its parent {@code mSurface} and cropped to the
+ * surface insets. If the layer does not exist, it is created.
+ *
+ * <p>Parenting to this layer will ensure that its children are cropped by the view's surface
+ * insets.
+ */
+ public SurfaceControl getBoundsLayer() {
+ if (mBoundsLayer == null) {
+ mBoundsLayer = new SurfaceControl.Builder(mSurfaceSession)
+ .setContainerLayer()
.setName("Bounds for - " + getTitle().toString())
.setParent(mSurfaceControl)
.build();
- setBoundsSurfaceCrop();
- mTransaction.setLayer(mBoundsSurfaceControl, zOrderLayer)
- .show(mBoundsSurfaceControl)
- .apply();
- mBoundsSurface.copyFrom(mBoundsSurfaceControl);
+ setBoundsLayerCrop(mTransaction);
+ mTransaction.show(mBoundsLayer).apply();
+ }
+ return mBoundsLayer;
}
- private void setBoundsSurfaceCrop() {
+ private void setBoundsLayerCrop(Transaction t) {
// mWinFrame is already adjusted for surface insets. So offset it and use it as
// the cropping bounds.
mTempBoundsRect.set(mWinFrame);
mTempBoundsRect.offsetTo(mWindowAttributes.surfaceInsets.left,
mWindowAttributes.surfaceInsets.top);
- mTransaction.setWindowCrop(mBoundsSurfaceControl, mTempBoundsRect);
+ t.setWindowCrop(mBoundsLayer, mTempBoundsRect);
}
/**
- * Called after window layout to update the bounds surface. If the surface insets have
- * changed or the surface has resized, update the bounds surface.
+ * Called after window layout to update the bounds surface. If the surface insets have changed
+ * or the surface has resized, update the bounds surface.
*/
- private void updateBoundsSurface() {
- if (mBoundsSurfaceControl != null && mSurface.isValid()) {
- setBoundsSurfaceCrop();
- mTransaction.deferTransactionUntilSurface(mBoundsSurfaceControl,
+ private void updateBoundsLayer() {
+ if (mBoundsLayer != null) {
+ setBoundsLayerCrop(mTransaction);
+ mTransaction.deferTransactionUntilSurface(mBoundsLayer,
mSurface, mSurface.getNextFrameNumber())
.apply();
}
}
private void destroySurface() {
+ if (mBoundsLayer != null) {
+ mBoundsLayer.release();
+ mBoundsLayer = null;
+ }
mSurface.release();
mSurfaceControl.release();
-
- mSurfaceSession = null;
-
- if (mBoundsSurfaceControl != null) {
- mBoundsSurfaceControl.remove();
- mBoundsSurface.release();
- mBoundsSurfaceControl = null;
- }
}
/**
@@ -2026,18 +2040,9 @@
mDisplay.getRealSize(size);
desiredWindowWidth = size.x;
desiredWindowHeight = size.y;
- } else if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
- || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
- // For wrap content, we have to remeasure later on anyways. Use size consistent with
- // below so we get best use of the measure cache.
- desiredWindowWidth = dipToPx(config.screenWidthDp);
- desiredWindowHeight = dipToPx(config.screenHeightDp);
} else {
- // After addToDisplay, the frame contains the frameHint from window manager, which
- // for most windows is going to be the same size as the result of relayoutWindow.
- // Using this here allows us to avoid remeasuring after relayoutWindow
- desiredWindowWidth = frame.width();
- desiredWindowHeight = frame.height();
+ desiredWindowWidth = mWinFrame.width();
+ desiredWindowHeight = mWinFrame.height();
}
// We used to use the following condition to choose 32 bits drawing caches:
@@ -2607,7 +2612,7 @@
}
if (surfaceSizeChanged) {
- updateBoundsSurface();
+ updateBoundsLayer();
}
final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
@@ -3447,7 +3452,9 @@
private void reportDrawFinished() {
try {
mDrawsNeededToReport = 0;
- mWindowSession.finishDrawing(mWindow);
+ if (mSurfaceControl.isValid()) {
+ mWindowSession.finishDrawing(mWindow, mChangeSurfaceTransaction);
+ }
} catch (RemoteException e) {
// Have fun!
}
@@ -7098,6 +7105,9 @@
frameNumber = mSurface.getNextFrameNumber();
}
+ mPreviousSurfaceControlHandle = mSurfaceControl.isValid()
+ ? mSurfaceControl.getHandle() : null;
+
int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params,
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
@@ -7111,6 +7121,11 @@
destroySurface();
}
+ if (mPreviousSurfaceControlHandle != null && mSurfaceControl.isValid()
+ && mPreviousSurfaceControlHandle != mSurfaceControl.getHandle()) {
+ notifySurfaceChanged(mChangeSurfaceTransaction);
+ }
+
mPendingAlwaysConsumeSystemBars =
(relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS) != 0;
@@ -7335,7 +7350,8 @@
try {
if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
& WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
- mWindowSession.finishDrawing(mWindow);
+ mWindowSession.finishDrawing(
+ mWindow, null /* postDrawTransaction */);
}
} catch (RemoteException e) {
}
diff --git a/core/java/android/view/inputmethod/InputMethodSystemProperty.java b/core/java/android/view/inputmethod/InputMethodSystemProperty.java
index 7c79d44..05143a1 100644
--- a/core/java/android/view/inputmethod/InputMethodSystemProperty.java
+++ b/core/java/android/view/inputmethod/InputMethodSystemProperty.java
@@ -17,6 +17,7 @@
package android.view.inputmethod;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.content.ComponentName;
import android.os.Build;
import android.os.SystemProperties;
@@ -26,6 +27,7 @@
*
* @hide
*/
+@TestApi
public class InputMethodSystemProperty {
/**
* System property key for the production use. The value must be either empty or a valid
@@ -87,6 +89,7 @@
*
* @hide
*/
+ @TestApi
public static final boolean MULTI_CLIENT_IME_ENABLED = (sMultiClientImeComponentName != null);
/**
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 1719015..ccafa64 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -277,7 +277,7 @@
mWindowElevation, mWindowCornerRadius,
mOverlay != null ? mOverlay : new ColorDrawable(Color.TRANSPARENT),
Handler.getMain() /* draw the magnifier on the UI thread */, mLock,
- mDestroyLock, mCallback);
+ mCallback);
}
}
performPixelCopy(startX, startY, true /* update window position */);
@@ -306,11 +306,9 @@
*/
public void dismiss() {
if (mWindow != null) {
- synchronized (mDestroyLock) {
- synchronized (mLock) {
- mWindow.destroy();
- mWindow = null;
- }
+ synchronized (mLock) {
+ mWindow.destroy();
+ mWindow = null;
}
mPrevShowSourceCoords.x = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
mPrevShowSourceCoords.y = NONEXISTENT_PREVIOUS_CONFIG_VALUE;
@@ -835,24 +833,16 @@
private int mWindowPositionY;
private boolean mPendingWindowPositionUpdate;
- // The lock used to synchronize the UI and render threads when a #destroy
- // is performed on the UI thread and a frame callback on the render thread.
- // When both mLock and mDestroyLock need to be held at the same time,
- // mDestroyLock should be acquired before mLock in order to avoid deadlocks.
- private final Object mDestroyLock;
-
// The current content of the magnifier. It is mBitmap + mOverlay, only used for testing.
private Bitmap mCurrentContent;
InternalPopupWindow(final Context context, final Display display,
final SurfaceControl parentSurfaceControl, final int width, final int height,
final float elevation, final float cornerRadius, final Drawable overlay,
- final Handler handler, final Object lock, final Object destroyLock,
- final Callback callback) {
+ final Handler handler, final Object lock, final Callback callback) {
mDisplay = display;
mOverlay = overlay;
mLock = lock;
- mDestroyLock = destroyLock;
mCallback = callback;
mContentWidth = width;
@@ -1039,20 +1029,17 @@
}
/**
- * Destroys this instance.
+ * Destroys this instance. The method has to be called in a context holding {@link #mLock}.
*/
public void destroy() {
- synchronized (mDestroyLock) {
- mSurface.destroy();
- }
- synchronized (mLock) {
- mRenderer.destroy();
- mSurfaceControl.remove();
- mSurfaceSession.kill();
- mHandler.removeCallbacks(mMagnifierUpdater);
- if (mBitmap != null) {
- mBitmap.recycle();
- }
+ // Destroy the renderer. This will not proceed until pending frame callbacks complete.
+ mRenderer.destroy();
+ mSurface.destroy();
+ mSurfaceControl.remove();
+ mSurfaceSession.kill();
+ mHandler.removeCallbacks(mMagnifierUpdater);
+ if (mBitmap != null) {
+ mBitmap.recycle();
}
}
@@ -1090,24 +1077,20 @@
final int pendingY = mWindowPositionY;
callback = frame -> {
- synchronized (mDestroyLock) {
- if (!mSurface.isValid()) {
- return;
- }
- synchronized (mLock) {
- // Show or move the window at the content draw frame.
- SurfaceControl.openTransaction();
- mSurfaceControl.deferTransactionUntil(mSurface, frame);
- if (updateWindowPosition) {
- mSurfaceControl.setPosition(pendingX, pendingY);
- }
- if (firstDraw) {
- mSurfaceControl.setLayer(SURFACE_Z);
- mSurfaceControl.show();
- }
- SurfaceControl.closeTransaction();
- }
+ if (!mSurface.isValid()) {
+ return;
}
+ // Show or move the window at the content draw frame.
+ SurfaceControl.openTransaction();
+ mSurfaceControl.deferTransactionUntil(mSurface, frame);
+ if (updateWindowPosition) {
+ mSurfaceControl.setPosition(pendingX, pendingY);
+ }
+ if (firstDraw) {
+ mSurfaceControl.setLayer(SURFACE_Z);
+ mSurfaceControl.show();
+ }
+ SurfaceControl.closeTransaction();
};
mRenderer.setLightCenter(mDisplay, pendingX, pendingY);
} else {
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 3475b61..55c24eb 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -113,7 +113,7 @@
*/
public static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";
- // Flags related to Assistant Handles
+ // Flags related to Assistant
/**
* (String) Which behavior mode for the Assistant Handles to use.
@@ -190,5 +190,10 @@
public static final String ASSIST_HANDLES_SUPPRESS_ON_APPS =
"assist_handles_suppress_on_apps";
+ /**
+ * Allow touch passthrough above assist area during a session.
+ */
+ public static final String ASSIST_TAP_PASSTHROUGH = "assist_tap_passthrough";
+
private SystemUiDeviceConfigFlags() { }
}
diff --git a/core/java/com/android/internal/net/VpnInfo.java b/core/java/com/android/internal/net/VpnInfo.java
index b1a41287..e74af5e 100644
--- a/core/java/com/android/internal/net/VpnInfo.java
+++ b/core/java/com/android/internal/net/VpnInfo.java
@@ -19,6 +19,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.Arrays;
+
/**
* A lightweight container used to carry information of the ongoing VPN.
* Internal use only..
@@ -28,14 +30,14 @@
public class VpnInfo implements Parcelable {
public int ownerUid;
public String vpnIface;
- public String primaryUnderlyingIface;
+ public String[] underlyingIfaces;
@Override
public String toString() {
return "VpnInfo{"
+ "ownerUid=" + ownerUid
+ ", vpnIface='" + vpnIface + '\''
- + ", primaryUnderlyingIface='" + primaryUnderlyingIface + '\''
+ + ", underlyingIfaces='" + Arrays.toString(underlyingIfaces) + '\''
+ '}';
}
@@ -48,7 +50,7 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(ownerUid);
dest.writeString(vpnIface);
- dest.writeString(primaryUnderlyingIface);
+ dest.writeStringArray(underlyingIfaces);
}
public static final Parcelable.Creator<VpnInfo> CREATOR = new Parcelable.Creator<VpnInfo>() {
@@ -57,7 +59,7 @@
VpnInfo info = new VpnInfo();
info.ownerUid = source.readInt();
info.vpnIface = source.readString();
- info.primaryUnderlyingIface = source.readString();
+ info.underlyingIfaces = source.readStringArray();
return info;
}
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index f9cdf3d..dfd6f95 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -49,7 +49,7 @@
DisplayCutout.ParcelableWrapper displayCutout) {
if (reportDraw) {
try {
- mSession.finishDrawing(this);
+ mSession.finishDrawing(this, null /* postDrawTransaction */);
} catch (RemoteException e) {
}
}
diff --git a/core/jni/LayoutlibLoader.cpp b/core/jni/LayoutlibLoader.cpp
index b0dbb68..94064c1 100644
--- a/core/jni/LayoutlibLoader.cpp
+++ b/core/jni/LayoutlibLoader.cpp
@@ -174,7 +174,8 @@
}
// Get the names of classes that have to delegate their native methods
- jclass createInfo = FindClassOrDie(env, "com/android/tools/layoutlib/create/CreateInfo");
+
+ jclass createInfo = FindClassOrDie(env, "com/android/tools/layoutlib/create/NativeConfig");
jfieldID arrayId = GetStaticFieldIDOrDie(env, createInfo,
"DELEGATE_CLASS_NATIVES_TO_NATIVES", "[Ljava/lang/String;");
jobjectArray array = (jobjectArray) env->GetStaticObjectField(createInfo, arrayId);
@@ -194,11 +195,15 @@
}
// Set the location of ICU data
- jclass bridge = FindClassOrDie(env, "com/android/layoutlib/bridge/Bridge");
- jstring stringPath = (jstring) env->CallStaticObjectMethod(bridge,
- GetStaticMethodIDOrDie(env, bridge, "getIcuDataPath", "()Ljava/lang/String;"));
+ jclass system = FindClassOrDie(env, "java/lang/System");
+ jmethodID getPropertyMethod = GetStaticMethodIDOrDie(env, system, "getProperty",
+ "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+ jstring stringPath = (jstring) (jstring) env->CallStaticObjectMethod(system,
+ getPropertyMethod, env->NewStringUTF("icu.dir"),
+ env->NewStringUTF(""));
const char* path = env->GetStringUTFChars(stringPath, 0);
u_setDataDirectory(path);
env->ReleaseStringUTFChars(stringPath, path);
return JNI_VERSION_1_6;
}
+
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index ccadc7d..0a7bc30 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -485,7 +485,7 @@
static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
- nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
+ nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
UiFrameInfoBuilder(proxy->frameInfo())
.setVsync(vsync, vsync)
.addFlag(FrameInfoFlags::SurfaceCanvas);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index f55f81d..f55077a 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -1266,6 +1266,7 @@
reinterpret_cast<SurfaceComposerClient::Transaction *>(nativeObject);
if (self != nullptr) {
self->writeToParcel(parcel);
+ self->clear();
}
}
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index f7e9b24..84c3b3a 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -957,7 +957,7 @@
// to all 0s.
proxy.setLightAlpha(0, 0);
proxy.setLightGeometry((Vector3){0, 0, 0}, 0);
- nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
+ nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
UiFrameInfoBuilder(proxy.frameInfo())
.setVsync(vsync, vsync)
.addFlag(FrameInfoFlags::SurfaceCanvas);
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 0cd3dbf..834dd03 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -292,6 +292,7 @@
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.
enum MountExternalKind {
MOUNT_EXTERNAL_NONE = 0,
MOUNT_EXTERNAL_DEFAULT = 1,
@@ -300,6 +301,18 @@
MOUNT_EXTERNAL_LEGACY = 4,
MOUNT_EXTERNAL_INSTALLER = 5,
MOUNT_EXTERNAL_FULL = 6,
+ MOUNT_EXTERNAL_COUNT = 7
+};
+
+// 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
};
// Must match values in com.android.internal.os.Zygote.
@@ -633,6 +646,23 @@
return 0;
}
+static void CreateDir(const std::string& dir, mode_t mode, uid_t uid, gid_t gid,
+ fail_fn_t fail_fn) {
+ if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) {
+ fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s: %s",
+ dir.c_str(), strerror(errno)));
+ }
+}
+
+static void BindMount(const std::string& source_dir, const std::string& target_dir,
+ fail_fn_t fail_fn) {
+ if (TEMP_FAILURE_RETRY(mount(source_dir.c_str(), target_dir.c_str(), nullptr,
+ MS_BIND | MS_REC, nullptr)) == -1) {
+ fail_fn(CREATE_ERROR("Failed to mount %s to %s: %s",
+ source_dir.c_str(), target_dir.c_str(), strerror(errno)));
+ }
+}
+
// Create a private mount namespace and bind mount appropriate emulated
// storage for the given user.
static void MountEmulatedStorage(uid_t uid, jint mount_mode,
@@ -641,18 +671,11 @@
// See storage config details at http://source.android.com/tech/storage/
ATRACE_CALL();
- String8 storage_source;
- if (mount_mode == MOUNT_EXTERNAL_DEFAULT) {
- storage_source = "/mnt/runtime/default";
- } else if (mount_mode == MOUNT_EXTERNAL_READ) {
- storage_source = "/mnt/runtime/read";
- } else if (mount_mode == MOUNT_EXTERNAL_WRITE
- || mount_mode == MOUNT_EXTERNAL_LEGACY
- || mount_mode == MOUNT_EXTERNAL_INSTALLER) {
- storage_source = "/mnt/runtime/write";
- } else if (mount_mode == MOUNT_EXTERNAL_FULL) {
- storage_source = "/mnt/runtime/full";
- } else if (mount_mode == MOUNT_EXTERNAL_NONE && !force_mount_namespace) {
+ if (mount_mode < 0 || mount_mode >= MOUNT_EXTERNAL_COUNT) {
+ fail_fn(CREATE_ERROR("Unknown mount_mode: %d", mount_mode));
+ }
+
+ if (mount_mode == MOUNT_EXTERNAL_NONE && !force_mount_namespace) {
// Sane default of no storage visible
return;
}
@@ -667,26 +690,15 @@
return;
}
- if (TEMP_FAILURE_RETRY(mount(storage_source.string(), "/storage", nullptr,
- MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
- fail_fn(CREATE_ERROR("Failed to mount %s to /storage: %s",
- storage_source.string(),
- strerror(errno)));
- }
+ const std::string& storage_source = ExternalStorageViews[mount_mode];
+
+ BindMount(storage_source, "/storage", fail_fn);
// Mount user-specific symlink helper into place
userid_t user_id = multiuser_get_user_id(uid);
- const String8 user_source(String8::format("/mnt/user/%d", user_id));
- if (fs_prepare_dir(user_source.string(), 0751, 0, 0) == -1) {
- fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s",
- user_source.string()));
- }
-
- if (TEMP_FAILURE_RETRY(mount(user_source.string(), "/storage/self",
- nullptr, MS_BIND, nullptr)) == -1) {
- fail_fn(CREATE_ERROR("Failed to mount %s to /storage/self: %s",
- user_source.string(), strerror(errno)));
- }
+ const std::string user_source = StringPrintf("/mnt/user/%d", user_id);
+ CreateDir(user_source, 0751, AID_ROOT, AID_ROOT, fail_fn);
+ BindMount(user_source, "/storage/self", fail_fn);
}
static bool NeedsNoRandomizeWorkaround() {
diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp
index 5cca0fd..c2a5ee43 100644
--- a/core/jni/com_android_internal_os_ZygoteInit.cpp
+++ b/core/jni/com_android_internal_os_ZygoteInit.cpp
@@ -19,7 +19,6 @@
#include <EGL/egl.h>
#include <Properties.h>
#include <ui/GraphicBufferMapper.h>
-#include <vulkan/vulkan.h>
#include "core_jni_helpers.h"
@@ -67,9 +66,6 @@
ScopedSCSExit x;
if (Properties::peekRenderPipelineType() == RenderPipelineType::SkiaGL) {
eglGetDisplay(EGL_DEFAULT_DISPLAY);
- } else {
- uint32_t count = 0;
- vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
}
}
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 4874c41..4b6a6de 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2380,6 +2380,11 @@
// Note: Only shows up on first time toggle
DIALOG_DARK_UI_INFO = 1740;
+ // OPEN: Settings > About phone > Legal information > Google Play system update licenses
+ // CATEGORY: SETTINGS
+ // OS: Q
+ MODULE_LICENSES_DASHBOARD = 1746;
+
// OPEN: Settings > System > Gestures > Global Actions Panel
// CATEGORY: SETTINGS
// OS: Q
diff --git a/core/proto/android/server/connectivity/Android.bp b/core/proto/android/server/connectivity/Android.bp
index c0ac2cb..4136239 100644
--- a/core/proto/android/server/connectivity/Android.bp
+++ b/core/proto/android/server/connectivity/Android.bp
@@ -21,5 +21,4 @@
"data_stall_event.proto",
],
sdk_version: "system_current",
- no_framework_libs: true,
-}
\ No newline at end of file
+}
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index e6ae226..7779025 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -45,6 +45,7 @@
optional bool display_frozen = 6;
optional int32 rotation = 7;
optional int32 last_orientation = 8;
+ optional int32 focused_display_id = 9;
}
/* represents RootWindowContainer object */
diff --git a/core/proto/android/stats/connectivity/Android.bp b/core/proto/android/stats/connectivity/Android.bp
index 5aa4ddb..5d642d38 100644
--- a/core/proto/android/stats/connectivity/Android.bp
+++ b/core/proto/android/stats/connectivity/Android.bp
@@ -21,5 +21,4 @@
"network_stack.proto",
],
sdk_version: "system_current",
- no_framework_libs: true,
-}
\ No newline at end of file
+}
diff --git a/core/proto/android/stats/devicepolicy/Android.bp b/core/proto/android/stats/devicepolicy/Android.bp
index 6ae54e2..5fb278a 100644
--- a/core/proto/android/stats/devicepolicy/Android.bp
+++ b/core/proto/android/stats/devicepolicy/Android.bp
@@ -29,5 +29,5 @@
static_libs: ["libprotobuf-java-nano"],
}
},
- no_framework_libs: true,
+ sdk_version: "core_platform",
}
diff --git a/core/proto/android/stats/dnsresolver/Android.bp b/core/proto/android/stats/dnsresolver/Android.bp
index 0b5aa86..1e8c763 100644
--- a/core/proto/android/stats/dnsresolver/Android.bp
+++ b/core/proto/android/stats/dnsresolver/Android.bp
@@ -21,5 +21,4 @@
"dns_resolver.proto",
],
sdk_version: "system_current",
- no_framework_libs: true,
}
diff --git a/core/proto/android/stats/dnsresolver/dns_resolver.proto b/core/proto/android/stats/dnsresolver/dns_resolver.proto
index af6fea0..b7bf384 100644
--- a/core/proto/android/stats/dnsresolver/dns_resolver.proto
+++ b/core/proto/android/stats/dnsresolver/dns_resolver.proto
@@ -1,214 +1,216 @@
-/*
- * 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.
- */
-syntax = "proto2";
-package android.stats.dnsresolver;
-
-enum EventType {
- EVENT_UNKNOWN = 0;
- EVENT_GETADDRINFO = 1;
- EVENT_GETHOSTBYNAME = 2;
- EVENT_GETHOSTBYADDR = 3;
- EVENT_RES_NSEND = 4;
-}
-
-// The return value of the DNS resolver for each DNS lookups.
-// bionic/libc/include/netdb.h
-// system/netd/resolv/include/netd_resolv/resolv.h
-enum ReturnCode {
- RC_EAI_NO_ERROR = 0;
- RC_EAI_ADDRFAMILY = 1;
- RC_EAI_AGAIN = 2;
- RC_EAI_BADFLAGS = 3;
- RC_EAI_FAIL = 4;
- RC_EAI_FAMILY = 5;
- RC_EAI_MEMORY = 6;
- RC_EAI_NODATA = 7;
- RC_EAI_NONAME = 8;
- RC_EAI_SERVICE = 9;
- RC_EAI_SOCKTYPE = 10;
- RC_EAI_SYSTEM = 11;
- RC_EAI_BADHINTS = 12;
- RC_EAI_PROTOCOL = 13;
- RC_EAI_OVERFLOW = 14;
- RC_RESOLV_TIMEOUT = 255;
- RC_EAI_MAX = 256;
-}
-
-enum NsRcode {
- NS_R_NO_ERROR = 0; // No error occurred.
- NS_R_FORMERR = 1; // Format error.
- NS_R_SERVFAIL = 2; // Server failure.
- NS_R_NXDOMAIN = 3; // Name error.
- NS_R_NOTIMPL = 4; // Unimplemented.
- NS_R_REFUSED = 5; // Operation refused.
- // these are for BIND_UPDATE
- NS_R_YXDOMAIN = 6; // Name exists
- NS_R_YXRRSET = 7; // RRset exists
- NS_R_NXRRSET = 8; // RRset does not exist
- NS_R_NOTAUTH = 9; // Not authoritative for zone
- NS_R_NOTZONE = 10; // Zone of record different from zone section
- NS_R_MAX = 11;
- // The following are EDNS extended rcodes
- NS_R_BADVERS = 16;
- // The following are TSIG errors
- // NS_R_BADSIG = 16,
- NS_R_BADKEY = 17;
- NS_R_BADTIME = 18;
-}
-
-// Currently defined type values for resources and queries.
-enum NsType {
- NS_T_INVALID = 0; // Cookie.
- NS_T_A = 1; // Host address.
- NS_T_NS = 2; // Authoritative server.
- NS_T_MD = 3; // Mail destination.
- NS_T_MF = 4; // Mail forwarder.
- NS_T_CNAME = 5; // Canonical name.
- NS_T_SOA = 6; // Start of authority zone.
- NS_T_MB = 7; // Mailbox domain name.
- NS_T_MG = 8; // Mail group member.
- NS_T_MR = 9; // Mail rename name.
- NS_T_NULL = 10; // Null resource record.
- NS_T_WKS = 11; // Well known service.
- NS_T_PTR = 12; // Domain name pointer.
- NS_T_HINFO = 13; // Host information.
- NS_T_MINFO = 14; // Mailbox information.
- NS_T_MX = 15; // Mail routing information.
- NS_T_TXT = 16; // Text strings.
- NS_T_RP = 17; // Responsible person.
- NS_T_AFSDB = 18; // AFS cell database.
- NS_T_X25 = 19; // X_25 calling address.
- NS_T_ISDN = 20; // ISDN calling address.
- NS_T_RT = 21; // Router.
- NS_T_NSAP = 22; // NSAP address.
- NS_T_NSAP_PTR = 23; // Reverse NSAP lookup (deprecated).
- NS_T_SIG = 24; // Security signature.
- NS_T_KEY = 25; // Security key.
- NS_T_PX = 26; // X.400 mail mapping.
- NS_T_GPOS = 27; // Geographical position (withdrawn).
- NS_T_AAAA = 28; // IPv6 Address.
- NS_T_LOC = 29; // Location Information.
- NS_T_NXT = 30; // Next domain (security).
- NS_T_EID = 31; // Endpoint identifier.
- NS_T_NIMLOC = 32; // Nimrod Locator.
- NS_T_SRV = 33; // Server Selection.
- NS_T_ATMA = 34; // ATM Address
- NS_T_NAPTR = 35; // Naming Authority PoinTeR
- NS_T_KX = 36; // Key Exchange
- NS_T_CERT = 37; // Certification record
- NS_T_A6 = 38; // IPv6 address (experimental)
- NS_T_DNAME = 39; // Non-terminal DNAME
- NS_T_SINK = 40; // Kitchen sink (experimentatl)
- NS_T_OPT = 41; // EDNS0 option (meta-RR)
- NS_T_APL = 42; // Address prefix list (RFC 3123)
- NS_T_DS = 43; // Delegation Signer
- NS_T_SSHFP = 44; // SSH Fingerprint
- NS_T_IPSECKEY = 45; // IPSEC Key
- NS_T_RRSIG = 46; // RRset Signature
- NS_T_NSEC = 47; // Negative security
- NS_T_DNSKEY = 48; // DNS Key
- NS_T_DHCID = 49; // Dynamic host configuratin identifier
- NS_T_NSEC3 = 50; // Negative security type 3
- NS_T_NSEC3PARAM = 51; // Negative security type 3 parameters
- NS_T_HIP = 55; // Host Identity Protocol
- NS_T_SPF = 99; // Sender Policy Framework
- NS_T_TKEY = 249; // Transaction key
- NS_T_TSIG = 250; // Transaction signature.
- NS_T_IXFR = 251; // Incremental zone transfer.
- NS_T_AXFR = 252; // Transfer zone of authority.
- NS_T_MAILB = 253; // Transfer mailbox records.
- NS_T_MAILA = 254; // Transfer mail agent records.
- NS_T_ANY = 255; // Wildcard match.
- NS_T_ZXFR = 256; // BIND-specific, nonstandard.
- NS_T_DLV = 32769; // DNSSEC look-aside validatation.
- NS_T_MAX = 65536;
-}
-
-enum IpVersion {
- IV_UNKNOWN = 0;
- IV_IPV4 = 1;
- IV_IPV6 = 2;
-}
-
-enum TransportType {
- TT_UNKNOWN = 0;
- TT_UDP = 1;
- TT_TCP = 2;
- TT_DOT = 3;
-}
-
-enum PrivateDnsModes {
- PDM_UNKNOWN = 0;
- PDM_OFF = 1;
- PDM_OPPORTUNISTIC = 2;
- PDM_STRICT = 3;
-}
-
-enum Transport {
- // Indicates this network uses a Cellular transport.
- TRANSPORT_DEFAULT = 0; // TRANSPORT_CELLULAR
- // Indicates this network uses a Wi-Fi transport.
- TRANSPORT_WIFI = 1;
- // Indicates this network uses a Bluetooth transport.
- TRANSPORT_BLUETOOTH = 2;
- // Indicates this network uses an Ethernet transport.
- TRANSPORT_ETHERNET = 3;
- // Indicates this network uses a VPN transport.
- TRANSPORT_VPN = 4;
- // Indicates this network uses a Wi-Fi Aware transport.
- TRANSPORT_WIFI_AWARE = 5;
- // Indicates this network uses a LoWPAN transport.
- TRANSPORT_LOWPAN = 6;
-}
-
-enum CacheStatus{
- // the cache can't handle that kind of queries.
- // or the answer buffer is too small.
- CS_UNSUPPORTED = 0;
- // the cache doesn't know about this query.
- CS_NOTFOUND = 1;
- // the cache found the answer.
- CS_FOUND = 2;
- // Don't do anything on cache.
- CS_SKIP = 3;
-}
-
-message DnsQueryEvent {
- optional android.stats.dnsresolver.NsRcode rcode = 1;
-
- optional android.stats.dnsresolver.NsType type = 2;
-
- optional android.stats.dnsresolver.CacheStatus cache_hit = 3;
-
- optional android.stats.dnsresolver.IpVersion ip_version = 4;
-
- optional android.stats.dnsresolver.TransportType transport = 5;
-
- // Number of DNS query retry times
- optional int32 retry_times = 6;
-
- // Ordinal number of name server.
- optional int32 dns_server_count = 7;
-
- // Used only by TCP and DOT. True for new connections.
- optional bool connected = 8;
-
- optional int32 latency_micros = 9;
-}
-
-message DnsQueryEvents {
- repeated DnsQueryEvent dns_query_event = 1;
-}
+/*
+ * 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.
+ */
+syntax = "proto2";
+package android.stats.dnsresolver;
+
+enum EventType {
+ EVENT_UNKNOWN = 0;
+ EVENT_GETADDRINFO = 1;
+ EVENT_GETHOSTBYNAME = 2;
+ EVENT_GETHOSTBYADDR = 3;
+ EVENT_RES_NSEND = 4;
+}
+
+// The return value of the DNS resolver for each DNS lookups.
+// bionic/libc/include/netdb.h
+// system/netd/resolv/include/netd_resolv/resolv.h
+enum ReturnCode {
+ RC_EAI_NO_ERROR = 0;
+ RC_EAI_ADDRFAMILY = 1;
+ RC_EAI_AGAIN = 2;
+ RC_EAI_BADFLAGS = 3;
+ RC_EAI_FAIL = 4;
+ RC_EAI_FAMILY = 5;
+ RC_EAI_MEMORY = 6;
+ RC_EAI_NODATA = 7;
+ RC_EAI_NONAME = 8;
+ RC_EAI_SERVICE = 9;
+ RC_EAI_SOCKTYPE = 10;
+ RC_EAI_SYSTEM = 11;
+ RC_EAI_BADHINTS = 12;
+ RC_EAI_PROTOCOL = 13;
+ RC_EAI_OVERFLOW = 14;
+ RC_RESOLV_TIMEOUT = 255;
+ RC_EAI_MAX = 256;
+}
+
+enum NsRcode {
+ NS_R_NO_ERROR = 0; // No error occurred.
+ NS_R_FORMERR = 1; // Format error.
+ NS_R_SERVFAIL = 2; // Server failure.
+ NS_R_NXDOMAIN = 3; // Name error.
+ NS_R_NOTIMPL = 4; // Unimplemented.
+ NS_R_REFUSED = 5; // Operation refused.
+ // these are for BIND_UPDATE
+ NS_R_YXDOMAIN = 6; // Name exists
+ NS_R_YXRRSET = 7; // RRset exists
+ NS_R_NXRRSET = 8; // RRset does not exist
+ NS_R_NOTAUTH = 9; // Not authoritative for zone
+ NS_R_NOTZONE = 10; // Zone of record different from zone section
+ NS_R_MAX = 11;
+ // The following are EDNS extended rcodes
+ NS_R_BADVERS = 16;
+ // The following are TSIG errors
+ // NS_R_BADSIG = 16,
+ NS_R_BADKEY = 17;
+ NS_R_BADTIME = 18;
+ NS_R_TIMEOUT = 255;
+}
+
+// Currently defined type values for resources and queries.
+enum NsType {
+ NS_T_INVALID = 0; // Cookie.
+ NS_T_A = 1; // Host address.
+ NS_T_NS = 2; // Authoritative server.
+ NS_T_MD = 3; // Mail destination.
+ NS_T_MF = 4; // Mail forwarder.
+ NS_T_CNAME = 5; // Canonical name.
+ NS_T_SOA = 6; // Start of authority zone.
+ NS_T_MB = 7; // Mailbox domain name.
+ NS_T_MG = 8; // Mail group member.
+ NS_T_MR = 9; // Mail rename name.
+ NS_T_NULL = 10; // Null resource record.
+ NS_T_WKS = 11; // Well known service.
+ NS_T_PTR = 12; // Domain name pointer.
+ NS_T_HINFO = 13; // Host information.
+ NS_T_MINFO = 14; // Mailbox information.
+ NS_T_MX = 15; // Mail routing information.
+ NS_T_TXT = 16; // Text strings.
+ NS_T_RP = 17; // Responsible person.
+ NS_T_AFSDB = 18; // AFS cell database.
+ NS_T_X25 = 19; // X_25 calling address.
+ NS_T_ISDN = 20; // ISDN calling address.
+ NS_T_RT = 21; // Router.
+ NS_T_NSAP = 22; // NSAP address.
+ NS_T_NSAP_PTR = 23; // Reverse NSAP lookup (deprecated).
+ NS_T_SIG = 24; // Security signature.
+ NS_T_KEY = 25; // Security key.
+ NS_T_PX = 26; // X.400 mail mapping.
+ NS_T_GPOS = 27; // Geographical position (withdrawn).
+ NS_T_AAAA = 28; // IPv6 Address.
+ NS_T_LOC = 29; // Location Information.
+ NS_T_NXT = 30; // Next domain (security).
+ NS_T_EID = 31; // Endpoint identifier.
+ NS_T_NIMLOC = 32; // Nimrod Locator.
+ NS_T_SRV = 33; // Server Selection.
+ NS_T_ATMA = 34; // ATM Address
+ NS_T_NAPTR = 35; // Naming Authority PoinTeR
+ NS_T_KX = 36; // Key Exchange
+ NS_T_CERT = 37; // Certification record
+ NS_T_A6 = 38; // IPv6 address (experimental)
+ NS_T_DNAME = 39; // Non-terminal DNAME
+ NS_T_SINK = 40; // Kitchen sink (experimentatl)
+ NS_T_OPT = 41; // EDNS0 option (meta-RR)
+ NS_T_APL = 42; // Address prefix list (RFC 3123)
+ NS_T_DS = 43; // Delegation Signer
+ NS_T_SSHFP = 44; // SSH Fingerprint
+ NS_T_IPSECKEY = 45; // IPSEC Key
+ NS_T_RRSIG = 46; // RRset Signature
+ NS_T_NSEC = 47; // Negative security
+ NS_T_DNSKEY = 48; // DNS Key
+ NS_T_DHCID = 49; // Dynamic host configuratin identifier
+ NS_T_NSEC3 = 50; // Negative security type 3
+ NS_T_NSEC3PARAM = 51; // Negative security type 3 parameters
+ NS_T_HIP = 55; // Host Identity Protocol
+ NS_T_SPF = 99; // Sender Policy Framework
+ NS_T_TKEY = 249; // Transaction key
+ NS_T_TSIG = 250; // Transaction signature.
+ NS_T_IXFR = 251; // Incremental zone transfer.
+ NS_T_AXFR = 252; // Transfer zone of authority.
+ NS_T_MAILB = 253; // Transfer mailbox records.
+ NS_T_MAILA = 254; // Transfer mail agent records.
+ NS_T_ANY = 255; // Wildcard match.
+ NS_T_ZXFR = 256; // BIND-specific, nonstandard.
+ NS_T_DLV = 32769; // DNSSEC look-aside validatation.
+ NS_T_MAX = 65536;
+}
+
+enum IpVersion {
+ IV_UNKNOWN = 0;
+ IV_IPV4 = 1;
+ IV_IPV6 = 2;
+}
+
+enum Protocol {
+ PROTO_UNKNOWN = 0;
+ PROTO_UDP = 1;
+ PROTO_TCP = 2;
+ PROTO_DOT = 3;
+}
+
+enum PrivateDnsModes {
+ PDM_UNKNOWN = 0;
+ PDM_OFF = 1;
+ PDM_OPPORTUNISTIC = 2;
+ PDM_STRICT = 3;
+}
+
+enum NetworkType {
+ NT_UNKNOWN = 0;
+ // Indicates this network uses a Cellular transport.
+ NT_CELLULAR = 1;
+ // Indicates this network uses a Wi-Fi transport.
+ NT_WIFI = 2;
+ // Indicates this network uses a Bluetooth transport.
+ NT_BLUETOOTH = 3;
+ // Indicates this network uses an Ethernet transport.
+ NT_ETHERNET = 4;
+ // Indicates this network uses a VPN transport.
+ NT_VPN = 5;
+ // Indicates this network uses a Wi-Fi Aware transport.
+ NT_WIFI_AWARE = 6;
+ // Indicates this network uses a LoWPAN transport.
+ NT_LOWPAN = 7;
+}
+
+enum CacheStatus{
+ // the cache can't handle that kind of queries.
+ // or the answer buffer is too small.
+ CS_UNSUPPORTED = 0;
+ // the cache doesn't know about this query.
+ CS_NOTFOUND = 1;
+ // the cache found the answer.
+ CS_FOUND = 2;
+ // Don't do anything on cache.
+ CS_SKIP = 3;
+}
+
+message DnsQueryEvent {
+ optional android.stats.dnsresolver.NsRcode rcode = 1;
+
+ optional android.stats.dnsresolver.NsType type = 2;
+
+ optional android.stats.dnsresolver.CacheStatus cache_hit = 3;
+
+ optional android.stats.dnsresolver.IpVersion ip_version = 4;
+
+ optional android.stats.dnsresolver.Protocol protocol = 5;
+
+ // Number of DNS query retry times
+ optional int32 retry_times = 6;
+
+ // Ordinal number of name server.
+ optional int32 dns_server_index = 7;
+
+ // Used only by TCP and DOT. True for new connections.
+ optional bool connected = 8;
+
+ optional int32 latency_micros = 9;
+}
+
+message DnsQueryEvents {
+ repeated DnsQueryEvent dns_query_event = 1;
+}
diff --git a/core/res/Android.bp b/core/res/Android.bp
index 4e60f8c..3402033 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -16,7 +16,7 @@
android_app {
name: "framework-res",
- no_framework_libs: true,
+ sdk_version: "core_platform",
certificate: "platform",
// Soong special-cases framework-res to install this alongside
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 10484d1..3ae4f29 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1532,7 +1532,7 @@
recommendations and scores from the NetworkScoreService.
<p>Not for use by third-party applications. @hide -->
<permission android:name="android.permission.REQUEST_NETWORK_SCORES"
- android:protectionLevel="signature|setup" />
+ android:protectionLevel="signature|setup|privileged" />
<!-- Allows network stack services (Connectivity and Wifi) to coordinate
<p>Not for use by third-party or privileged applications.
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 9fad33d..9791033 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Draai jou kop \'n bietjie minder."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Draai jou kop \'n bietjie minder."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Verwyder enigiets wat jou gesig versteek."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Maak die sensor op die skerm se borand skoon."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Maak die bokant van jou skerm skoon, insluitend die swart balk"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Kan nie gesig verifieer nie. Hardeware nie beskikbaar nie."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 84f1072..83ee9ed 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ጭንቅላትዎን ትንሽ ብቻ ያዙሩት።"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ጭንቅላትዎን ትንሽ ብቻ ያዙሩት።"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"የእርስዎን ፊት የሚደብቀውን ሁሉንም ነገር በማስወገድ ላይ"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"በማያ ገጹ ላይኛው ጫፍ ላይ ዳሳሹን ያጽዱ።"</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"መልክን ማረጋገጥ አይቻልም። ሃርድዌር የለም።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 06c1197..ac083d1 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -309,7 +309,7 @@
<string name="permgrouprequest_storage" msgid="7885942926944299560">"هل تريد السماح لتطبيق <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> بالوصول إلى الصور والوسائط والملفات على جهازك؟"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"الميكروفون"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"تسجيل الصوت"</string>
- <string name="permgrouprequest_microphone" msgid="9167492350681916038">"هل تريد السماح لتطبيق <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> بتسجيل الصوت؟"</string>
+ <string name="permgrouprequest_microphone" msgid="9167492350681916038">"هل تريد السماح لـ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> بتسجيل الصوت؟"</string>
<string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"النشاط البدني"</string>
<string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"الوصول إلى بيانات نشاطك البدني"</string>
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"هل تريد السماح للتطبيق <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> بالوصول إلى بيانات نشاطك البدني؟"</string>
@@ -321,7 +321,7 @@
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"هل تريد السماح لتطبيق <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> بالوصول إلى سجلّ مكالماتك الهاتفية؟"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"الهاتف"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"إجراء مكالمات هاتفية وإدارتها"</string>
- <string name="permgrouprequest_phone" msgid="9166979577750581037">"هل تريد السماح لتطبيق <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> بإجراء المكالمات الهاتفية وإدارتها؟"</string>
+ <string name="permgrouprequest_phone" msgid="9166979577750581037">"هل تريد السماح لـ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> بإجراء المكالمات الهاتفية وإدارتها؟"</string>
<string name="permgrouplab_sensors" msgid="4838614103153567532">"أجهزة استشعار الجسم"</string>
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"الوصول إلى بيانات المستشعر حول علاماتك الحيوية"</string>
<string name="permgrouprequest_sensors" msgid="6349806962814556786">"هل تريد السماح لتطبيق <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> بالدخول إلى بيانات المستشعر حول علاماتك الحيوية؟"</string>
@@ -589,7 +589,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"حرّك رأسك قليلاً نحو الأمام مباشرة."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"حرّك رأسك قليلاً نحو الوسط."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"عليك بإزالة أي شيء يُخفي وجهك."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"نظِّف المستشعر أعلى الشاشة."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"يُرجى تنظيف الجزء العلوي من الشاشة، بما في ذلك الشريط الخلفي."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"يتعذّر التحقُّق من الوجه. الجهاز غير مُتاح."</string>
@@ -2123,7 +2123,7 @@
<string name="harmful_app_warning_title" msgid="8982527462829423432">"تم العثور على تطبيق ضار"</string>
<string name="slices_permission_request" msgid="8484943441501672932">"يريد تطبيق <xliff:g id="APP_0">%1$s</xliff:g> عرض شرائح تطبيق <xliff:g id="APP_2">%2$s</xliff:g>."</string>
<string name="screenshot_edit" msgid="7867478911006447565">"تعديل"</string>
- <string name="volume_dialog_ringer_guidance_vibrate" msgid="8902050240801159042">"سيهتز الهاتف عند تلقي المكالمات والإشعارات"</string>
+ <string name="volume_dialog_ringer_guidance_vibrate" msgid="8902050240801159042">"سيهتز الهاتف عند تلقّي المكالمات والإشعارات"</string>
<string name="volume_dialog_ringer_guidance_silent" msgid="2128975224280276122">"سيتم كتم صوت الهاتف عند تلقي المكالمات والإشعارات"</string>
<string name="notification_channel_system_changes" msgid="5072715579030948646">"تغييرات النظام"</string>
<string name="notification_channel_do_not_disturb" msgid="6766940333105743037">"عدم الإزعاج"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 246e819..97a061f 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -131,8 +131,7 @@
<!-- no translation found for wfcSpnFormat_spn (4998685024207291232) -->
<skip />
<string name="wfcSpnFormat_spn_wifi_calling" msgid="136001023263502280">"<xliff:g id="SPN">%s</xliff:g> ৱাই- ফাই কলিং"</string>
- <!-- no translation found for wfcSpnFormat_spn_wifi_calling_vo_hyphen (1730997175789582756) -->
- <skip />
+ <string name="wfcSpnFormat_spn_wifi_calling_vo_hyphen" msgid="1730997175789582756">"<xliff:g id="SPN">%s</xliff:g> ৱাই-ফাই কলিং"</string>
<string name="wfcSpnFormat_wlan_call" msgid="2533371081782489793">"WLAN কল"</string>
<string name="wfcSpnFormat_spn_wlan_call" msgid="2315240198303197168">"<xliff:g id="SPN">%s</xliff:g> WLAN কল"</string>
<string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> ৱাই-ফাই"</string>
@@ -258,8 +257,7 @@
<string name="notification_channel_car_mode" msgid="3553380307619874564">"গাড়ী ম\'ড"</string>
<string name="notification_channel_account" msgid="7577959168463122027">"একাউণ্টৰ স্থিতি"</string>
<string name="notification_channel_developer" msgid="7579606426860206060">"বিকাশকৰ্তাৰ বাৰ্তাসমূহ"</string>
- <!-- no translation found for notification_channel_developer_important (5251192042281632002) -->
- <skip />
+ <string name="notification_channel_developer_important" msgid="5251192042281632002">"বিকাশকৰ্তাৰ জৰুৰী বাৰ্তা"</string>
<string name="notification_channel_updates" msgid="4794517569035110397">"আপডেটবোৰ"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"নেটৱৰ্কৰ স্থিতি"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"নেটৱৰ্ক সম্পৰ্কীয় সতৰ্কবাণী"</string>
@@ -579,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"আপোনাৰ মূৰটো সামান্য কমকৈ ঘূৰাওক।"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"আপোনাৰ মূৰটো সামান্য কমকৈ ঘূৰাওক।"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"আপোনাৰ মুখখন ঢাকি ৰখা বস্তুবোৰ আঁতৰাওক।"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"স্ক্ৰীণৰ একেবাৰে ওপৰৰ কাষত থকা ছেন্সৰটো চাফা কৰক।"</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"মুখমণ্ডল সত্যাপন কৰিব পৰা নগ’ল। হাৰ্ডৱেৰ নাই।"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 100c90c..cc5ed49 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Başınızı bir az döndərin."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Başınızı bir az döndərin."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Üzünüzü gizlədən maneələri kənarlaşdırın."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Ekranın yuxarı küncündəki sensoru təmizləyin."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Qara panel daxil olmaqla, ekranın yuxarısını təmizləyin"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Üz doğrulanmadı. Avadanlıq əlçatan deyil."</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 9cd61a7..54b1989 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -580,7 +580,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Malo manje pomerite glavu."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Malo manje pomerite glavu."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Uklonite sve što vam zaklanja lice."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Očistite senzor na gornjoj ivici ekrana."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Očistite gornji deo ekrana, uključujući crnu traku"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Provera lica nije uspela. Hardver nije dostupan."</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 41f2e9e..06f5587 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -583,7 +583,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Галава не ў цэнтры."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Вы занадта моцна павярнулі галаву."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Прыміце ўсё, што закрывае ваш твар."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Ачысціце датчык уверсе экрана."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Твар не спраўджаны. Абсталяванне недаступнае."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index ae59cf6..4720402 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Не завъртайте главата си толкова много."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Не завъртайте главата си толкова много."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Премахнете всичко, което закрива лицето ви."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Изчистете сензора в горния край на екрана."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Почистете горната част на екрана си, включително черната лента"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Лицето не може да се потвърди. Хардуерът не е налице."</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index c53027c..858b1de 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"আপনার মাথাটি নিচের দিকে সামান্য নামান।"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"আপনার মাথাটি সামান্য ঘোরান।"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"আপনার ফেসকে আড়াল করে এমন সব কিছু সরিয়ে দিন।"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"স্ক্রিনের উপরের প্রান্তের সেন্সর মুছুন।"</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ফেস যাচাই করা যায়নি। হার্ডওয়্যার উপলভ্য নেই।"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 57f655a..1f0de44 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -580,7 +580,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Malo manje zakrenite glavu."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Malo manje zakrenite glavu."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Uklonite prepreke koje blokiraju vaše lice."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Očistite senzor na gornjem rubu ekrana."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Očistite vrh ekrana, uključujući crnu traku"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Nije moguće potvrditi lice. Hardver nije dostupan."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 8eb341b..93fcacd 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Inclina el cap una mica menys."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"No inclinis tant el cap."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Suprimeix qualsevol cosa que amagui la teva cara."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Neteja el sensor de l\'extrem superior."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Neteja la part superior de la pantalla, inclosa la barra negra"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"No es pot verificar la cara. Maquinari no disponible."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 9d526c9..28a8679 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -583,7 +583,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Natočte hlavu o něco méně."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Natočte hlavu o něco méně."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Odstraňte vše, co vám zakrývá obličej."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Vyčistěte snímač u horního okraje obrazovky."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Očistěte horní část obrazovky včetně černé části"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Obličej nelze ověřit. Hardware není dostupný."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index f221de3..8965982 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Sørg for, at hovedet ikke er bøjet for meget."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Sørg for, at dit hoved ikke er drejet for meget."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Hvis noget skjuler dit ansigt, skal du fjerne det."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Rens sensoren ved skærmens øverste kant."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Ansigt ikke bekræftet. Hardware ikke tilgængelig."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 40f364f..09f48a9 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Neig den Kopf etwas weniger stark."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Neig den Kopf etwas weniger stark."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Entferne alles, was dein Gesicht verdeckt."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Reinige den Sensor am oberen Rand des Bildschirms."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Gesicht nicht erkannt. Hardware nicht verfügbar."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index bc780c0..b22dc9c 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Στρέψτε λιγότερο το κεφάλι σας."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Στρέψτε λιγότερο το κεφάλι σας."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Απομακρύνετε οτιδήποτε κρύβει το πρόσωπό σας."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Καθαρίστε τον αισθητήρα επάνω στην οθόνη."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Καθαρίστε το επάνω μέρος της οθόνης σας, συμπεριλαμβανομένης της μαύρης γραμμής"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Αδύν. επαλήθ. προσώπου. Μη διαθέσιμος εξοπλισμός."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 3ca5363..5423fec 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Turn your head a little less."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Turn your head a little less."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Remove anything hiding your face."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Clean the sensor at the top edge of the screen."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Clean the top of your screen, including the black bar"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Can’t verify face. Hardware not available."</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index d8f21a7..4cbbe14 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Turn your head a little less."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Turn your head a little less."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Remove anything hiding your face."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Clean the sensor at the top edge of the screen."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Clean the top of your screen, including the black bar"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Can’t verify face. Hardware not available."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 3ca5363..5423fec 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Turn your head a little less."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Turn your head a little less."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Remove anything hiding your face."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Clean the sensor at the top edge of the screen."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Clean the top of your screen, including the black bar"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Can’t verify face. Hardware not available."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 3ca5363..5423fec 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Turn your head a little less."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Turn your head a little less."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Remove anything hiding your face."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Clean the sensor at the top edge of the screen."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Clean the top of your screen, including the black bar"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Can’t verify face. Hardware not available."</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index c037b11..ffbe69e 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Turn your head a little less."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Turn your head a little less."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Remove anything hiding your face."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Clean the sensor at the top edge of the screen."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Clean the top of your screen, including the black bar"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Can’t verify face. Hardware not available."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index fad63c2..5b2cd98 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Gira la cabeza un poco menos."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Gira la cabeza un poco menos."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Quítate cualquier objeto que te cubra el rostro."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Limpiar sensor del borde superior de la pantalla."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"No se verificó el rostro. Hardware no disponible."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 8c76192..c47ce73 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Gira la cabeza un poco menos."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"No gires tanto la cabeza."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Retira cualquier objeto que te tape la cara."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Limpia el sensor situado en la parte superior."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"No se puede verificar. Hardware no disponible."</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 465a257..3453825 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Pöörake oma pead veidi vähem."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Pöörake oma pead veidi vähem."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Eemaldage kõik, mis varjab teie nägu."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Puhastage ekraani ülaservas olev andur."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Nägu ei saa kinnitada. Riistvara pole saadaval."</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 816e8c2..142f04b 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Biratu burua pixka bat gutxiago."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Biratu burua pixka bat gutxiago."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Kendu aurpegia estaltzen dizuten gauzak."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Garbitu pantailaren goiko ertzeko sentsorea."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Ezin da egiaztatu aurpegia. Hardwarea ez dago erabilgarri."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 8d392a9..89e15ba 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -42,11 +42,11 @@
<string name="serviceErased" msgid="1288584695297200972">"پاک کردن با موفقیت انجام شد."</string>
<string name="passwordIncorrect" msgid="7612208839450128715">"گذرواژه اشتباه است."</string>
<string name="mmiComplete" msgid="8232527495411698359">"MMI کامل شد."</string>
- <string name="badPin" msgid="9015277645546710014">"پین قدیمی که نوشتهاید صحیح نیست."</string>
+ <string name="badPin" msgid="9015277645546710014">"این پین قدیمی که نوشتید صحیح نیست."</string>
<string name="badPuk" msgid="5487257647081132201">"PUK که نوشتهاید صحیح نیست."</string>
<string name="mismatchPin" msgid="609379054496863419">"پینهایی که وارد کردهاید با یکدیگر مطابقت ندارند."</string>
- <string name="invalidPin" msgid="3850018445187475377">"یک پین بنویسید که 4 تا 8 رقم باشد."</string>
- <string name="invalidPuk" msgid="8761456210898036513">"یک PUK با 8 رقم یا بیشتر تایپ کنید."</string>
+ <string name="invalidPin" msgid="3850018445187475377">"یک پین بنویسید که ۴ تا ۸ رقم باشد."</string>
+ <string name="invalidPuk" msgid="8761456210898036513">"یک PUK با ۸ رقم یا بیشتر تایپ کنید."</string>
<string name="needPuk" msgid="919668385956251611">"سیم کارت شما با PUK قفل شده است. کد PUK را برای بازگشایی آن بنویسید."</string>
<string name="needPuk2" msgid="4526033371987193070">"PUK2 را برای بازگشایی قفل سیم کارت بنویسید."</string>
<string name="enablePin" msgid="209412020907207950">"ناموفق بود، قفل سیم/RUIM را فعال کنید."</string>
@@ -73,8 +73,8 @@
<string name="DndMmi" msgid="1265478932418334331">"مزاحم نشوید"</string>
<string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"پیشفرض شناسه تماسگیرنده روی محدود است. تماس بعدی: محدود"</string>
<string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"پیشفرض شناسه تماسگیرنده روی محدود است. تماس بعدی: بدون محدودیت"</string>
- <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"پیشفرض شناسه تماسگیرنده روی غیر محدود است. تماس بعدی: محدود"</string>
- <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"پیشفرض شناسه تماسگیرنده روی غیر محدود است. تماس بعدی: بدون محدودیت"</string>
+ <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"پیشفرض شناسه تماسگیرنده روی غیرمحدود است. تماس بعدی: محدود"</string>
+ <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"پیشفرض شناسه تماسگیرنده روی غیرمحدود است. تماس بعدی: بدون محدودیت"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"سرویس دارای مجوز نیست."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"شما میتوانید تنظیم شناسه تماسگیرنده را تغییر دهید."</string>
<string name="RestrictedOnDataTitle" msgid="5221736429761078014">"بدون سرویس داده تلفن همراه"</string>
@@ -103,7 +103,7 @@
<string name="serviceClassData" msgid="872456782077937893">"داده"</string>
<string name="serviceClassFAX" msgid="5566624998840486475">"نمابر"</string>
<string name="serviceClassSMS" msgid="2015460373701527489">"پیامک"</string>
- <string name="serviceClassDataAsync" msgid="4523454783498551468">"غیر همگام"</string>
+ <string name="serviceClassDataAsync" msgid="4523454783498551468">"ناهمگام"</string>
<string name="serviceClassDataSync" msgid="7530000519646054776">"همگامسازی"</string>
<string name="serviceClassPacket" msgid="6991006557993423453">"بسته"</string>
<string name="serviceClassPAD" msgid="3235259085648271037">"PAD"</string>
@@ -154,7 +154,7 @@
<string name="fcError" msgid="3327560126588500777">"مشکل در اتصال یا کد ویژگی نامعتبر."</string>
<string name="httpErrorOk" msgid="1191919378083472204">"تأیید"</string>
<string name="httpError" msgid="7956392511146698522">"خطایی در شبکه وجود داشت."</string>
- <string name="httpErrorLookup" msgid="4711687456111963163">"URL پیدا نشد."</string>
+ <string name="httpErrorLookup" msgid="4711687456111963163">"نشانی اینترنتی پیدا نشد."</string>
<string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"طرح کلی احراز هویت سایت پشتیبانی نمیشود."</string>
<string name="httpErrorAuth" msgid="1435065629438044534">"راستیآزمایی ناموفق بود."</string>
<string name="httpErrorProxyAuth" msgid="1788207010559081331">"احراز هویت از طریق سرور پروکسی انجام نشد."</string>
@@ -164,10 +164,10 @@
<string name="httpErrorRedirectLoop" msgid="8679596090392779516">"این صفحه دارای تعداد بسیار زیادی تغییر مسیر سرور است."</string>
<string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"پروتکل پشتیبانی نمیشود."</string>
<string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"اتصال امن ایجاد نشد."</string>
- <string name="httpErrorBadUrl" msgid="3636929722728881972">"بدلیل نامعتبر بودن URL، باز کردن صفحه ممکن نیست."</string>
+ <string name="httpErrorBadUrl" msgid="3636929722728881972">"بهدلیل نامعتبر بودن نشانی اینترنتی، صفحه باز نمیشود."</string>
<string name="httpErrorFile" msgid="2170788515052558676">"دسترسی به فایل انجام نشد."</string>
<string name="httpErrorFileNotFound" msgid="6203856612042655084">"فایل درخواستی پیدا نشد."</string>
- <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"درخواستهای زیادی در حال پردازش است. بعداً دوباره امتحان کنید."</string>
+ <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"درخواستهای زیادی درحال پردازش است. بعداً دوباره امتحان کنید."</string>
<string name="notification_title" msgid="8967710025036163822">"خطای ورود به سیستم برای <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
<string name="contentServiceSync" msgid="8353523060269335667">"همگامسازی"</string>
<string name="contentServiceSyncNotificationTitle" msgid="7036196943673524858">"همگامسازی نشد"</string>
@@ -210,7 +210,7 @@
<string name="reboot_to_update_reboot" msgid="6428441000951565185">"در حال راهاندازی مجدد…"</string>
<string name="reboot_to_reset_title" msgid="4142355915340627490">"بازنشانی دادههای کارخانه"</string>
<string name="reboot_to_reset_message" msgid="2432077491101416345">"در حال راهاندازی مجدد…"</string>
- <string name="shutdown_progress" msgid="2281079257329981203">"در حال خاموش شدن…"</string>
+ <string name="shutdown_progress" msgid="2281079257329981203">"درحال خاموش شدن…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"رایانهٔ لوحی شما خاموش میشود."</string>
<string name="shutdown_confirm" product="tv" msgid="476672373995075359">"تلویزیون شما خاموش خواهد شد."</string>
<string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"ساعت شما خاموش میشود."</string>
@@ -400,7 +400,7 @@
<string name="permlab_readCallLog" msgid="3478133184624102739">"خواندن گزارش تماس"</string>
<string name="permdesc_readCallLog" msgid="3204122446463552146">"این برنامه میتواند سابقه تماس شما را بخواند."</string>
<string name="permlab_writeCallLog" msgid="8552045664743499354">"نوشتن گزارش تماس"</string>
- <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"به برنامه اجازه میدهد گزارشات تماس رایانهٔ لوحی شما، از جمله دادههایی درمورد تماسهای ورودی و خروجی را تغییر دهد. برنامههای مخرب ممکن است از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند."</string>
+ <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"به برنامه اجازه میدهد گزارشهای تماس رایانهٔ لوحی شما، از جمله دادههایی درباره تماسهای ورودی و خروجی را تغییر دهد. برنامههای مخرب ممکن است از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند."</string>
<string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"به برنامه اجازه میدهد گزارشات تماس تلویزیون شما، از جمله دادههایی درمورد تماسهای ورودی و خروجی را تغییر دهد. برنامههای مخرب شاید از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند."</string>
<string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"به برنامه اجازه میدهد گزارشات تماس تلفنی شما، از جمله دادههایی درمورد تماسهای ورودی و خروجی را تغییر دهد. برنامههای مخرب ممکن است از این ویژگی برای پاک کردن یا تغییر گزارش تماس شما استفاده کنند."</string>
<string name="permlab_bodySensors" msgid="4683341291818520277">"دسترسی به حسگرهای بدن (مانند پایشگرهای ضربان قلب)"</string>
@@ -502,7 +502,7 @@
<string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"به برنامه اجازه میدهد تا پیکربندی بلوتوث را در تلویزیون مشاهده کند و اتصالات را با دستگاههای مرتبطشده ایجاد کند و بپذیرد."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"به برنامه اجازه میدهد تا پیکربندی بلوتوث در تلفن را مشاهده کند، و اتصالات دستگاههای مرتبط را برقرار کرده و بپذیرد."</string>
<string name="permlab_nfc" msgid="4423351274757876953">"کنترل ارتباط راه نزدیک"</string>
- <string name="permdesc_nfc" msgid="7120611819401789907">"به برنامه اجازه میدهد تا با تگهای ارتباط میدان نزدیک (NFC)، کارتها و فایل خوان ارتباط برقرار کند."</string>
+ <string name="permdesc_nfc" msgid="7120611819401789907">"به برنامه اجازه میدهد تا با تگهای «ارتباط میدان نزدیک» (NFC)، کارتها و فایلخوان ارتباط برقرار کند."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"غیرفعال کردن قفل صفحه شما"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"به برنامه امکان میدهد قفل کلید و هر گونه امنیت گذرواژه مرتبط را غیرفعال کند. بهعنوان مثال تلفن هنگام دریافت یک تماس تلفنی ورودی قفل کلید را غیرفعال میکند و بعد از پایان تماس، قفل کلید را دوباره فعال میکند."</string>
<string name="permlab_requestPasswordComplexity" msgid="202650535669249674">"درخواست پیچیدگی قفل صفحه"</string>
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"سرتان را کمی پایین آورید."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"سرتان را کمی پایین آورید."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"هرچیزی را که حائل چهرهتان است بردارید."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"حسگر واقع در لبه بالای صفحه را تمیز کنید."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"چهره تأیید نشد. سختافزار در دسترس نیست."</string>
@@ -657,7 +658,7 @@
<string name="policylab_watchLogin" msgid="5091404125971980158">"پایش تلاشهای باز کردن قفل صفحه"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"تعداد گذرواژههای نادرست تایپ شده را هنگام بازکردن قفل صفحه کنترل میکند، و اگر دفعات زیادی گذرواژه نادرست وارد شود رایانهٔ لوحی را قفل میکند و همه دادههای رایانهٔ لوحی را پاک میکند."</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"بر تعداد گذرواژههای نادرست تایپشده در زمان باز کردن قفل صفحه نظارت کنید و اگر تعدا زیادی گذرواژههای اشتباه تایپ شده است، تلویزیون را قفل کنید یا همه دادههای تلویزیون را پاک کنید."</string>
- <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"تعداد گذرواژههای نادرست تایپ شده را هنگام بازکردن قفل صفحه کنترل میکند. اگر دفعات زیادی گذرواژه نادرست وارد شود، تلفن را قفل میکند یا همه دادههای تلفن را پاک میکند."</string>
+ <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"تعداد گذرواژههای نادرست تایپشده را هنگام بازکردن قفل صفحه کنترل میکند و اگر چندین بار گذرواژههای نادرست وارد شود، تلفن را قفل میکند یا همه دادههای تلفن را پاک میکند."</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"بر تعداد گذرواژههای نادرستی که هنگام باز کردن قفل صفحه تایپ شده، نظارت میکند، و اگر تعداد گذرواژههای تایپ شده نادرست بیش از حد بود، رایانه لوحی را قفل میکند یا کلیه دادههای کاربر را پاک میکند."</string>
<string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"بر تعداد گذرواژههای نادرستی که هنگام باز کردن قفل صفحه تایپ شده، نظارت میکند، و اگر تعداد گذرواژههای تایپ شده نادرست بیش از حد بود، تلویزیون را قفل میکند یا کلیه دادههای کاربر را پاک میکند."</string>
<string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"بر تعداد گذرواژههای نادرستی که هنگام باز کردن قفل صفحه تایپ شده، نظارت میکند، و اگر تعداد گذرواژههای تایپ شده نادرست بیش از حد بود، تلفن را قفل میکند یا کلیه دادههای کاربر را پاک میکند."</string>
@@ -679,7 +680,7 @@
<string name="policydesc_expirePassword" msgid="5367525762204416046">"تغییر تعداد دفعاتی که گذرواژه، پین یا الگوی قفل صفحه باید تغییر کند."</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"تنظیم رمزگذاری حافظه"</string>
<string name="policydesc_encryptedStorage" msgid="2637732115325316992">"اطلاعات ذخیره شده برنامه باید رمزگذاری شود."</string>
- <string name="policylab_disableCamera" msgid="6395301023152297826">"غیر فعال کردن دوربین ها"</string>
+ <string name="policylab_disableCamera" msgid="6395301023152297826">"غیرفعال کردن دوربینها"</string>
<string name="policydesc_disableCamera" msgid="2306349042834754597">"جلوگیری از استفاده از همه دوربینهای دستگاه."</string>
<string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"غیرفعال کردن ویژگیهای قفل صفحه"</string>
<string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"مانع استفاده از برخی ویژگیهای قفل صفحه میشود."</string>
@@ -839,7 +840,7 @@
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"سیم کارت با PUK قفل شده است."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"لطفاً به راهنمای کاربر مراجعه کرده یا با مرکز پشتیبانی از مشتریان تماس بگیرید."</string>
<string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"سیم کارت قفل شد."</string>
- <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"بازگشایی قفل سیم کارت..."</string>
+ <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"بازگشایی قفل سیم کارت…"</string>
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیدهاید. \n\nپس از <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"گذرواژهٔ خود را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه تایپ کردهاید. \n\nپس از <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"پین را<xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه تایپ کردهاید. \n\nپس از <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
@@ -851,7 +852,7 @@
<string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"شما به اشتباه <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اقدام به باز کردن قفل تلفن کردهاید. پس از<xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق دیگر، تلفن به پیشفرض کارخانه بازنشانی میشود و تمام دادههای کاربر از دست خواهد رفت."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"شما به اشتباه اقدام به باز کردن قفل <xliff:g id="NUMBER">%d</xliff:g> رایانهٔ لوحی کردهاید. رایانهٔ لوحی در حال حاضر به پیشفرض کارخانه بازنشانی میشود."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"<xliff:g id="NUMBER">%d</xliff:g> دفعه به صورت نادرست سعی کردهاید قفل تلویزیون را باز کنید. اکنون تلویزیون به تنظیمات پیشفرض کارخانه بازنشانی خواهد شد."</string>
- <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"شما به اشتباه <xliff:g id="NUMBER">%d</xliff:g> بار اقدام به باز کردن قفل تلفن کردهاید. این تلفن در حال حاضر به پیشفرض کارخانه بازنشانی میشود."</string>
+ <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"بهاشتباه <xliff:g id="NUMBER">%d</xliff:g> بار اقدام به باز کردن قفل تلفن کردهاید. این تلفن دیگر به پیشفرض کارخانه بازنشانی میشود."</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"پس از <xliff:g id="NUMBER">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
<string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"الگو را فراموش کردهاید؟"</string>
<string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"بازگشایی قفل حساب"</string>
@@ -862,7 +863,7 @@
<string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"ورود به سیستم"</string>
<string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"نام کاربر یا گذرواژه نامعتبر است."</string>
<string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"نام کاربری یا گذرواژهٔ خود را فراموش کردید؟\nاز "<b>"google.com/accounts/recovery"</b>" بازدید کنید."</string>
- <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"در حال بررسی..."</string>
+ <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"درحال بررسی…"</string>
<string name="lockscreen_unlock_label" msgid="737440483220667054">"بازگشایی قفل"</string>
<string name="lockscreen_sound_on_label" msgid="9068877576513425970">"صدا روشن"</string>
<string name="lockscreen_sound_off_label" msgid="996822825154319026">"صدا خاموش"</string>
@@ -1078,7 +1079,7 @@
<string name="failed_to_copy_to_clipboard" msgid="1833662432489814471">"در بریدهدان کپی نشد"</string>
<string name="paste" msgid="5629880836805036433">"جایگذاری"</string>
<string name="paste_as_plain_text" msgid="5427792741908010675">"جایگذاری به عنوان متن ساده"</string>
- <string name="replace" msgid="5781686059063148930">"جایگزین شود..."</string>
+ <string name="replace" msgid="5781686059063148930">"جایگزین شود…"</string>
<string name="delete" msgid="6098684844021697789">"حذف"</string>
<string name="copyUrl" msgid="2538211579596067402">"کپی URL"</string>
<string name="selectTextMode" msgid="1018691815143165326">"انتخاب متن"</string>
@@ -1122,7 +1123,7 @@
<string name="yes" msgid="5362982303337969312">"تأیید"</string>
<string name="no" msgid="5141531044935541497">"لغو"</string>
<string name="dialog_alert_title" msgid="2049658708609043103">"توجه"</string>
- <string name="loading" msgid="7933681260296021180">"در حال بارکردن…"</string>
+ <string name="loading" msgid="7933681260296021180">"درحال بارکردن…"</string>
<string name="capital_on" msgid="1544682755514494298">"روشن"</string>
<string name="capital_off" msgid="6815870386972805832">"خاموش"</string>
<string name="whichApplication" msgid="4533185947064773386">"تکمیل عملکرد با استفاده از"</string>
@@ -1199,8 +1200,8 @@
<string name="app_upgrading_toast" msgid="3008139776215597053">"<xliff:g id="APPLICATION">%1$s</xliff:g> درحال ارتقا است...."</string>
<string name="android_upgrading_apk" msgid="7904042682111526169">"در حال بهینهسازی برنامهٔ <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"آمادهسازی <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
- <string name="android_upgrading_starting_apps" msgid="451464516346926713">"در حال آغاز برنامهها."</string>
- <string name="android_upgrading_complete" msgid="1405954754112999229">"در حال اتمام راهاندازی."</string>
+ <string name="android_upgrading_starting_apps" msgid="451464516346926713">"درحال آغاز کردن برنامهها."</string>
+ <string name="android_upgrading_complete" msgid="1405954754112999229">"درحال اتمام راهاندازی."</string>
<string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> در حال اجرا"</string>
<string name="heavy_weight_notification_detail" msgid="2304833848484424985">"برای برگشت به بازی، ضربه بزنید"</string>
<string name="heavy_weight_switcher_title" msgid="387882830435195342">"انتخاب بازی"</string>
@@ -1307,8 +1308,8 @@
<string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="3087858235069421128">"در حالی که تلویزیون به <xliff:g id="DEVICE_NAME">%1$s</xliff:g> متصل است، ارتباط آن به صورت موقت از Wi-Fi قطع خواهد شد."</string>
<string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"این گوشی بهطور موقت از Wi-Fi قطع خواهد شد، در حالی که به <xliff:g id="DEVICE_NAME">%1$s</xliff:g> وصل است"</string>
<string name="select_character" msgid="3365550120617701745">"درج نویسه"</string>
- <string name="sms_control_title" msgid="7296612781128917719">"ارسال پیامک ها"</string>
- <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> در حال ارسال تعداد زیادی پیامک است. آیا اجازه میدهید این برنامه همچنان پیامک ارسال کند؟"</string>
+ <string name="sms_control_title" msgid="7296612781128917719">"درحال ارسال پیامکها"</string>
+ <string name="sms_control_message" msgid="3867899169651496433">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> درحال ارسال تعداد زیادی پیامک است. آیا اجازه میدهید این برنامه همچنان پیامک ارسال کند؟"</string>
<string name="sms_control_yes" msgid="3663725993855816807">"مجاز است"</string>
<string name="sms_control_no" msgid="625438561395534982">"اجازه ندارد"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> مایل است پیامی به <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b> ارسال کند."</string>
@@ -1460,7 +1461,7 @@
<string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ارائهدهنده وضعیت"</string>
<string name="notification_ranker_binding_label" msgid="774540592299064747">"سرویس رتبهبندی اعلان"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN فعال شد"</string>
- <string name="vpn_title_long" msgid="6400714798049252294">"VPN توسط <xliff:g id="APP">%s</xliff:g> فعال شده است"</string>
+ <string name="vpn_title_long" msgid="6400714798049252294">"VPN را <xliff:g id="APP">%s</xliff:g> فعال کرده است"</string>
<string name="vpn_text" msgid="1610714069627824309">"برای مدیریت شبکه ضربه بزنید."</string>
<string name="vpn_text_long" msgid="4907843483284977618">"به <xliff:g id="SESSION">%s</xliff:g> متصل شد. برای مدیریت شبکه ضربه بزنید."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"در حال اتصال VPN همیشه فعال…"</string>
@@ -1496,11 +1497,11 @@
<string name="find_previous" msgid="2196723669388360506">"یافتن قبلی"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"درخواست مکان از <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="gpsNotifTitle" msgid="5446858717157416839">"درخواست مکان"</string>
- <string name="gpsNotifMessage" msgid="1374718023224000702">"درخواست شده توسط <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
+ <string name="gpsNotifMessage" msgid="1374718023224000702">"درخواستکننده <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
<string name="gpsVerifYes" msgid="2346566072867213563">"بله"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"نه"</string>
<string name="sync_too_many_deletes" msgid="5296321850662746890">"از حد مجاز حذف فراتر رفت"</string>
- <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"<xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> مورد حذف شده برای <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>، حساب <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> وجود دارد. میخواهید چه کاری انجام دهید؟"</string>
+ <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"<xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> مورد حذفشده برای <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>، حساب <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> وجود دارد. میخواهید چه کار بکنید؟"</string>
<string name="sync_really_delete" msgid="2572600103122596243">"حذف موارد"</string>
<string name="sync_undo_deletes" msgid="2941317360600338602">"واگرد موارد حذف شده"</string>
<string name="sync_do_nothing" msgid="3743764740430821845">"اکنون کاری انجام نشود"</string>
@@ -1565,11 +1566,11 @@
<string name="data_usage_rapid_app_body" msgid="5396680996784142544">"<xliff:g id="APP">%s</xliff:g> بیش از معمول داده مصرف کرده است"</string>
<string name="ssl_certificate" msgid="6510040486049237639">"گواهی امنیتی"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"این گواهی معتبر است."</string>
- <string name="issued_to" msgid="454239480274921032">"صادر شده برای:"</string>
+ <string name="issued_to" msgid="454239480274921032">"صادرشده برای:"</string>
<string name="common_name" msgid="2233209299434172646">"نام معمولی:"</string>
<string name="org_name" msgid="6973561190762085236">"سازمان:"</string>
<string name="org_unit" msgid="7265981890422070383">"واحد سازمانی:"</string>
- <string name="issued_by" msgid="2647584988057481566">"صادر شده توسط:"</string>
+ <string name="issued_by" msgid="2647584988057481566">"صادرکننده:"</string>
<string name="validity_period" msgid="8818886137545983110">"اعتبار:"</string>
<string name="issued_on" msgid="5895017404361397232">"صادر شده در:"</string>
<string name="expires_on" msgid="3676242949915959821">"تاریخ انقضا:"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 901f02c..bfab176 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Käännä päätä vähän vähemmän."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Käännä päätä vähän vähemmän."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Poista esteet kasvojesi edestä."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Puhdista näytön yläreunassa oleva anturi."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Kasvoja ei voi vahvistaa. Laitteisto ei käytettäv."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index ee49b2e..8aab360 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -309,7 +309,7 @@
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"Autoriser <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> à accéder à vos journaux d\'appels?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Téléphone"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"faire et gérer des appels téléphoniques"</string>
- <string name="permgrouprequest_phone" msgid="9166979577750581037">"Autoriser <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> à faire et à gérer les appels téléphoniques?"</string>
+ <string name="permgrouprequest_phone" msgid="9166979577750581037">"Autoriser <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> à faire et à gérer des appels téléphoniques?"</string>
<string name="permgrouplab_sensors" msgid="4838614103153567532">"Capteurs corporels"</string>
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"accéder aux données des capteurs sur vos signes vitaux"</string>
<string name="permgrouprequest_sensors" msgid="6349806962814556786">"Autoriser « <xliff:g id="APP_NAME">%1$s</xliff:g> » à accéder aux données des capteurs pour vos signes vitaux?"</string>
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Tournez un peu moins votre tête."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Tournez un peu moins votre tête."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Retirez tout ce qui pourrait couvrir votre visage."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Nettoyez le capteur dans le haut de l\'écran."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Imposs. de vérif. visage. Matériel non accessible."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 5ba3e29..c629207 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Tournez un peu moins la tête."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Tournez un peu moins la tête."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Retirez tout ce qui cache votre visage."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Nettoyez le capteur en haut de l\'écran."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Imposs. valider visage. Matériel non disponible."</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index e25f1e73..b66380e 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Xira a cabeza un pouco menos."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Xira a cabeza un pouco menos."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Quita todo o que oculte a túa cara."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Limpa o sensor na parte superior da pantalla."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Sen verificar a cara. Hardware non dispoñible."</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 647e6c9..0e5e530 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"તમારું માથું થોડું ફેરવો."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"તમારું માથું થોડું ઓછું ફેરવો."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"તમારા ચહેરાને છુપાવતી કંઈપણ વસ્તુ દૂર કરો."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"સ્ક્રીનની ટોચની ધાર પરના સેન્સરને સાફ કરો."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ચહેરો ચકાસી શકાતો નથી. હાર્ડવેર ઉપલબ્ધ નથી."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 190d805..b142420 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -116,7 +116,7 @@
<string name="roamingText6" msgid="2059440825782871513">"रोमिंग - उपलब्ध सिस्टम"</string>
<string name="roamingText7" msgid="7112078724097233605">"रोमिंग - गठबंधन सहयोगी"</string>
<string name="roamingText8" msgid="5989569778604089291">"रोमिंग - प्रीमियम सहयोगी"</string>
- <string name="roamingText9" msgid="7969296811355152491">"रोमिंग - पूर्ण सेवा काम की क्षमता"</string>
+ <string name="roamingText9" msgid="7969296811355152491">"रोमिंग - पूरी सेवा काम की क्षमता"</string>
<string name="roamingText10" msgid="3992906999815316417">"रोमिंग - आंशिक सेवा काम की क्षमता"</string>
<string name="roamingText11" msgid="4154476854426920970">"रोमिंग बैनर चालू"</string>
<string name="roamingText12" msgid="1189071119992726320">"रोमिंग बैनर बंद"</string>
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"अपना सिर थोड़ा कम घुमाएं."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"अपना सिर थोड़ा कम घुमाएं."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"आपके चेहरे को छिपाने वाली सभी चीज़ों को हटाएं."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"स्क्रीन के ऊपरी किनारे पर मौजूद सेंसर को साफ करें."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"चेहरा नहीं पहचान पा रहे. हार्डवेयर उपलब्ध नहीं है."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index a47593f..0c9d499 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -580,7 +580,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Nagnite glavu malo manje."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Nagnite glavu malo manje."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Uklonite sve što vam zakriva lice."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Očistite senzor na gornjem rubu zaslona."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Očistite vrh zaslona, uključujući crnu traku"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Lice nije potvrđeno. Hardver nije dostupan."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 4afa745..120f5f0 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Kicsit kevésbé fordítsa el a fejét."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Kicsit kevésbé fordítsa el a fejét."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Távolítson el mindent, ami takarja az arcát."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Tisztítsa meg a képernyő tetején lévő érzékelőt."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Sikertelen arcellenőrzés. A hardver nem érhető el."</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 1f6634e..58072eb 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Գլուխն ուղիղ պահեք։"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Գլուխն ուղիղ պահեք։"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Հեռացրեք այն ամենը, ինչը թաքցնում է ձեր երեսը:"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Մաքրեք էկրանի վերևի անկյունում գտնվող տվիչը:"</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Չհաջողվեց հաստատել դեմքը։ Սարքն անհասանելի է:"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 3c7903d..b959865 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Putar sedikit kepala Anda."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Putar sedikit kepala Anda."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Singkirkan apa saja yang menutupi wajah Anda."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Bersihkan sensor di tepi atas layar."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Bersihkan bagian atas layar, termasuk kotak hitam"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Tidak dapat memverifikasi wajah. Hardware tidak tersedia."</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index b86db25..fe41f79 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Hallaðu höfðinu aðeins minna."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Snúðu höfðinu aðeins minna."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Fjarlægðu það sem kann að hylja andlitið."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Hreinsaðu skynjarann á efri brún skjásins."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Hreinsaðu efsta hluta skjásins þíns, þ.m.t. svörtu stikuna"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Andlit ekki staðfest. Vélbúnaður er ekki tiltækur."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index b9e478b..beddb80 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Gira un po\' meno la testa."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Gira un po\' meno la testa."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Rimuovi tutto ciò che ti nasconde il viso."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Pulisci sensore sul bordo superiore dello schermo."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Pulisci la parte superiore dello schermo, inclusa la barra nera"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Imposs. verificare volto. Hardware non disponibile."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 6fa93c3..1d5d5b7 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -583,7 +583,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"עליך ליישר קצת את הראש."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"עליך ליישר קצת את הראש."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"יש להסיר כל דבר שמסתיר את הפנים."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"יש לנקות את החיישן שבקצה העליון של המסך."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"לא ניתן לאמת את הפנים. החומרה לא זמינה."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 3385614..20834e7 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"顔の向きを少し戻してください。"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"顔の向きを少し戻してください。"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"顔を隠しているものをすべて外してください"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"画面の上端にあるセンサーの汚れを落としてください。"</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"顔を確認できません。ハードウェアを利用できません。"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index a4d7ce7..3b57d20 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"თავი ცოტა ნაკლებად მიაბრუნეთ."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"თავი ცოტა ნაკლებად მიაბრუნეთ."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"მოაშორეთ ყველაფერი, რაც სახეს გიფარავთ."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"გაწმინდეთ სენსორი ეკრანის ზედა კიდეზე."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"გაწმინდეთ ეკრანის ზედა ნაწილი, შავი ზოლის ჩათვლით."</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"სახე ვერ დასტურდება. აპარატი მიუწვდომელია."</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 256db93..b024f35 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Басыңызды түзурек ұстаңыз."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Басыңызды кішкене бұрыңыз."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Бетіңізді жауып тұрған нәрсені алып тастаңыз."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Экранның жоғарғы жиегіндегі датчикті тазалаңыз."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Бетті тану мүмкін емес. Жабдық қолжетімді емес."</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 24f0c3d..5ff1e4d 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ងាកក្បាលរបស់អ្នកបន្តិចទៀត។"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ងាកក្បាលរបស់អ្នកបន្តិចទៀត។"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"យកអ្វីដែលបាំងមុខរបស់អ្នកចេញ។"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"សម្អាតឧបករណ៍ចាប់សញ្ញានៅគែមខាងលើនៃអេក្រង់។"</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"មិនអាចផ្ទៀងផ្ទាត់មុខបានទេ។ មិនមានហាតវែរទេ។"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 9281c5e..5d4862c 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ನಿಮ್ಮ ತಲೆಯನ್ನು ಹೆಚ್ಚು ತಿರುಗಿಸಬೇಡಿ."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ನಿಮ್ಮ ತಲೆಯನ್ನು ಸ್ವಲ್ಪ ಕಡಿಮೆ ತಿರುಗಿಸಿ."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"ನಿಮ್ಮ ಮುಖವನ್ನು ಮರೆಮಾಡುವ ಯಾವುದನ್ನಾದರೂ ತೆಗೆದುಹಾಕಿ."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"ಸ್ಕ್ರೀನ್ ಮೇಲ್ಬಾಗದ ಅಂಚಿನಲ್ಲಿನ ಸೆನ್ಸರ್ ಸ್ವಚ್ಚಗೊಳಿಸಿ."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ಮುಖ ದೃಢೀಕರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಹಾರ್ಡ್ವೇರ್ ಲಭ್ಯವಿಲ್ಲ."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 47146d8..9658468 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"고개를 조금 덜 돌려 보세요."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"고개를 조금 덜 돌려 보세요."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"얼굴이 가려지지 않도록 해 주세요."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"화면 상단 가장자리의 센서를 깨끗하게 닦아 주세요."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"얼굴을 확인할 수 없습니다. 하드웨어를 사용할 수 없습니다."</string>
@@ -903,7 +904,7 @@
<string name="granularity_label_link" msgid="5815508880782488267">"링크"</string>
<string name="granularity_label_line" msgid="5764267235026120888">"행"</string>
<string name="factorytest_failed" msgid="5410270329114212041">"출고 테스트 불합격"</string>
- <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST 작업은 /system/app 디렉토리에 설치된 패키지에 대해서만 지원됩니다."</string>
+ <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST 작업은 /system/app 디렉터리에 설치된 패키지에 대해서만 지원됩니다."</string>
<string name="factorytest_no_action" msgid="872991874799998561">"FACTORY_TEST 작업을 제공하는 패키지가 없습니다."</string>
<string name="factorytest_reboot" msgid="6320168203050791643">"다시 부팅"</string>
<string name="js_dialog_title" msgid="1987483977834603872">"\'<xliff:g id="TITLE">%s</xliff:g>\' 페이지 내용:"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 20b695e..d72c5dd 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Башыңызды бир аз гана эңкейтиңиз."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Башыңызды бир аз гана эңкейтиңиз."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Жүзүңүздү жашырып турган нерселерди алып салыңыз."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Экрандын жогору жагындагы сенсорду тазалаңыз."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Жүз ырасталбай жатат. Аппараттык камсыздоо жеткиликсиз."</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 4752fd4..f2670ad 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ອຽງຫົວຂອງທ່ານໜ້ອຍໜຶ່ງ."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ອຽງຫົວຂອງທ່ານໜ້ອຍໜຶ່ງ."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"ນຳສິ່ງທີ່ກີດຂວາງໃບໜ້າທ່ານອອກ."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"ທຳຄວາມສະອາດເຊັນເຊີຢູ່ເທິງສຸດຂອງຂອບຈໍ."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ບໍ່ສາມາດຢັ້ງຢືນໃບໜ້າໄດ້. ບໍ່ມີຮາດແວໃຫ້ໃຊ້."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 7fb7567..9aecc80 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -583,7 +583,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Nesukite tiek galvos."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Nesukite tiek galvos."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Patraukite viską, kas užstoja jūsų veidą."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Nuvalykite jutiklį, esantį ekrano viršuje."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Išvalykite ekrano viršų, įskaitant juodą juostą"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Nepavyko patv. veido. Aparatinė įranga negalima."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 9bc137e..8cd7d10 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -580,7 +580,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Pagrieziet galvu nedaudz mazāk."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Pagrieziet galvu nedaudz mazāk."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Noņemiet visu, kas aizsedz jūsu seju."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Notīriet sensoru ekrāna augšējā malā."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Nevar verificēt seju. Aparatūra nav pieejama."</string>
diff --git a/core/res/res/values-mcc310-mnc280-or/strings.xml b/core/res/res/values-mcc310-mnc280-or/strings.xml
new file mode 100644
index 0000000..05eeac1
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc280-or/strings.xml
@@ -0,0 +1,26 @@
+<?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_imsi_unknown_in_hlr" msgid="6638755728961013003">"SIM କାର୍ଡ ପ୍ରସ୍ତୁତ କରାଯାଇନାହିଁ MM#2"</string>
+ <string name="mmcc_illegal_ms" msgid="5562215652599183258">"SIM କାର୍ଡର ଅନୁମତି ନାହିଁ MM#3"</string>
+ <string name="mmcc_illegal_me" msgid="822496463303720579">"ଫୋନ୍ର ଅନୁମତି ନାହିଁ MM#6"</string>
+</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index ab5ad57..30493d71 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Не вртете ја главата толку многу."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Не вртете ја главата толку многу."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Отстранете ги работите што ви го покриваат лицето."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Исчистете го сензорот на горниот врв од екранот."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Исчистете го врвот на екранот, вклучувајќи ја црната лента"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Ликот не може да се потврди. Хардвер - недостапен."</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 9dbfe83..9b52aa5 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"നിങ്ങളുടെ തല ഇത്ര തിരിക്കേണ്ട."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"നിങ്ങളുടെ തല ഇത്ര തിരിക്കേണ്ട."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"നിങ്ങളുടെ മുഖം മറയ്ക്കുന്നത് എല്ലാം നീക്കം ചെയ്യൂ."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"സ്ക്രീനിന്റെ മുകളിലെ സെൻസർ വൃത്തിയാക്കുക."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"മുഖം പരിശോധിക്കാൻ കഴിയില്ല. ഹാർഡ്വെയർ ലഭ്യമല്ല."</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index bfdde47..bca7717 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Толгойгоо арай багаар эргүүлнэ үү."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Толгойгоо арай багаар эргүүлнэ үү."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Таны нүүрийг далдалж буй аливаа зүйлийг хасна уу."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Дэлгэцийн дээд ирмэгт байрлах мэдрэгчийг цэвэрлэнэ үү."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Царайг бататгаж чадсангүй. Техник хангамж боломжгүй байна."</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index b4da1bd..c02e32b 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"तुमचे डोके थोडे कमी फिरवा."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"तुमचे डोके थोडे कमी फिरवा."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"तुमचा चहेरा लपवणारे काहीही काढून टाका."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"स्क्रीनच्या वरील उजव्या कडेवरील सेन्सर साफ करा."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"चेहरा पडताळू शकत नाही. हार्डवेअर उपलब्ध नाही."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 8aebd9e..e421d7818 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Pusingkan kepala anda kurang sedikit."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Pusingkan kepala anda kurang sedikit."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Alih keluar apa saja yang melindungi wajah anda."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Bersihkan penderia di tepi bahagian atas skrin."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Tdk dpt sahkan wajah. Perkakasan tidak tersedia."</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 2f79c86..55b3879 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -297,7 +297,7 @@
<string name="permgrouprequest_storage" msgid="7885942926944299560">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> အား သင့်ဖုန်းရှိ ဓာတ်ပုံများ၊ မီဒီယာနှင့် ဖိုင်များ ဝင်သုံးခွင့်ပေးလိုပါသလား။"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"မိုက်ခရိုဖုန်း"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"အသံဖမ်းခြင်း"</string>
- <string name="permgrouprequest_microphone" msgid="9167492350681916038">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> အား အသံဖမ်းယူခွင့် ပေးလိုပါသလား။"</string>
+ <string name="permgrouprequest_microphone" msgid="9167492350681916038">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ကို အသံဖမ်းယူခွင့် ပေးလိုပါသလား။"</string>
<string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"ကိုယ်လက်လှုပ်ရှားမှု"</string>
<string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"သင့်ကိုယ်လက်လှုပ်ရှားမှုကို ဝင်ကြည့်ရန်"</string>
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> အား သင့်ကိုယ်လက်လှုပ်ရှားမှုကို ဝင်ကြည့်ခွင့် ပေးလိုပါသလား။"</string>
@@ -309,7 +309,7 @@
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> အား သင်၏ခေါ်ဆိုထားသော မှတ်တမ်းများကို သုံးခွင့်ပေးလိုပါသလား။"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"ဖုန်း"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"ဖုန်းခေါ်ဆိုမှုများ ပြုလုပ်ရန်နှင့် စီမံရန်"</string>
- <string name="permgrouprequest_phone" msgid="9166979577750581037">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> အား ဖုန်းခေါ်ဆိုမှုများ ပြုလုပ်ခွင့်နှင့် စီမံခွင့်ပေးလိုပါသလား။"</string>
+ <string name="permgrouprequest_phone" msgid="9166979577750581037">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ကို ဖုန်းခေါ်ဆိုမှုများ ပြုလုပ်ခွင့်နှင့် စီမံခွင့်ပေးလိုပါသလား။"</string>
<string name="permgrouplab_sensors" msgid="4838614103153567532">"စက်၏ အာရုံခံစနစ်များ"</string>
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"သင်၏ အဓိကကျသော လက္ခဏာများအကြောင်း အာရုံခံကိရိယာဒေတာကို ရယူသုံးစွဲရန်"</string>
<string name="permgrouprequest_sensors" msgid="6349806962814556786">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> အား သင်၏ အရေးကြီးသောလက္ခဏာ အာရုံခံကိရိယာ ဒေတာများကို သုံးခွင့်ပေးလိုပါသလား။"</string>
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ခေါင်းကို သိပ်မလှည့်ပါနှင့်။"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ခေါင်းကို သိပ်မလှည့်ပါနှင့်။"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"သင့်မျက်နှာကို ကွယ်နေသည့်အရာအားလုံး ဖယ်ပါ။"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"မျက်နှာပြင်ထိပ်ရှိ အာရုံခံဆင်ဆာကို သန့်ရှင်းပါ။"</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"အနက်ရောင်ဘားအပါအဝင် သင့်ဖန်သားပြင်ထိပ်ကို သန့်ရှင်းရေး လုပ်ပါ"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"မျက်နှာကို အတည်ပြု၍ မရပါ။ ဟာ့ဒ်ဝဲ မရနိုင်ပါ။"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 70775b0..0fb17732 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Vri hodet ditt litt mindre."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Vri hodet ditt litt mindre."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Fjern alt som skjuler ansiktet ditt."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Rengjør sensoren på toppkanten av skjermen."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Kan ikke bekrefte ansikt. Utilgjengelig maskinvare."</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 747f4b0..757e4e6 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"आफ्नो टाउको अलि थोरै घुमाउनुहोस्।"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"आफ्नो टाउको अलि थोरै घुमाउनुहोस्।"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"तपाईंको अनुहार लुकाउने सबै कुरा लुकाउनुहोस्।"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"स्क्रिनको शीर्ष कुनामा रहेको सेन्सर सफा गर्नुहोस्।"</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"अनुहार पुष्टि गर्न सकिएन। हार्डवेयर उपलब्ध छैन।"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index b7676aa..32ae904 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Draai je hoofd iets minder."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Draai je hoofd iets minder."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Zorg dat je gezicht volledig zichtbaar is."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Maak de sensor bovenaan het scherm schoon."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Reinig de bovenkant van je scherm, inclusief de zwarte balk"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Kan gezicht niet verifiëren. Hardware niet beschikbaar."</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 6db2e87..ab3ca0e 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ଆପଣଙ୍କର ମୁଣ୍ଡକୁ ଟିକିଏ ବୁଲାନ୍ତୁ।"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ଆପଣଙ୍କର ମୁଣ୍ଡକୁ ଟିକିଏ ବୁଲାନ୍ତୁ।"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"ଆପଣଙ୍କର ମୁହଁ ଲୁଚାଉଥିବା ଜିନିଷକୁ କାଢ଼ି ଦିଅନ୍ତୁ।"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"ସ୍କ୍ରିନ୍ର ଉପର ପ୍ରାନ୍ତରେ ଥିବା ସେନ୍ସର୍କୁ ଖାଲି କରନ୍ତୁ।"</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ମୁହଁ ଚିହ୍ନଟ କରିପାରିଲା ନାହିଁ। ହାର୍ଡୱେୟାର୍ ଉପଲବ୍ଧ ନାହିଁ।"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 86d6f80..afcfad8 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ਆਪਣਾ ਸਿਰ ਥੋੜਾ ਜਿਹਾ ਝੁਕਾਓ।"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ਆਪਣਾ ਸਿਰ ਥੋੜਾ ਜਿਹਾ ਝੁਕਾਓ।"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"ਤੁਹਾਡਾ ਚਿਹਰਾ ਲੁਕਾਉਣ ਵਾਲੀ ਕੋਈ ਵੀ ਚੀਜ਼ ਹਟਾਓ।"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"ਸਕ੍ਰੀਨ ਦੇ ਸਿਖਰਲੇ ਕਿਨਾਰੇ ਦਾ ਸੈਂਸਰ ਸਾਫ਼ ਕਰੋ।"</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ਚਿਹਰੇ ਦੀ ਪੁਸ਼ਟੀ ਨਹੀਂ ਹੋ ਸਕੀ। ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ।"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 0d85333..b8cbe19 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -583,7 +583,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Trochę mniej obróć głowę."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Trochę mniej obróć głowę."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Usuń wszystko, co zasłania Ci twarz."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Wyczyść czujnik na górnej krawędzi ekranu."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Nie można zweryfikować twarzy. Sprzęt niedostępny."</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 0d4689c..7205ca4 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Incline a cabeça um pouco menos."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Incline a cabeça um pouco menos."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Remova tudo que esteja ocultando seu rosto."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Limpe o sensor na borda superior da tela."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Limpe a parte superior da tela, inclusive a barra preta"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Impossível verificar rosto. Hardware indisponível."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 398c2f7..f2b785b 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Rode a cabeça um pouco menos."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Rode a cabeça um pouco menos."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Remova tudo o que esteja a ocultar o seu rosto."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Limpe o sensor na extremidade superior do ecrã."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Não pode validar o rosto. Hardware não disponível."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 0d4689c..7205ca4 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Incline a cabeça um pouco menos."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Incline a cabeça um pouco menos."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Remova tudo que esteja ocultando seu rosto."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Limpe o sensor na borda superior da tela."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Limpe a parte superior da tela, inclusive a barra preta"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Impossível verificar rosto. Hardware indisponível."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 2c5bb2b..5111f02 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -580,7 +580,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Întoarceți capul mai puțin."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Întoarceți capul mai puțin."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Eliminați orice vă ascunde chipul."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Curățați senzorul de la marginea de sus a ecranului."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Nu se poate confirma fața. Hardware-ul nu este disponibil."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 721defa..c674ea3 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -583,7 +583,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Держите голову ровнее."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Держите голову ровнее."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Ваше лицо плохо видно."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Очистите сканер в верхней части экрана."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Не удалось распознать лицо. Сканер недоступен."</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 74bc175..f68b55f 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"ඔබේ හිස ටිකක් අඩුවෙන් කරකවන්න."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"ඔබේ හිස ටිකක් අඩුවෙන් කරකවන්න."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"ඔබේ මුහුණ සඟවන කිසිවක් ඉවත් කරන්න."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"තිරයේ ඉහළ කෙළවරේ සංවේදකය පිරිසිදු කරන්න."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"කලු තීරුව ඇතුළුව, ඔබේ තිරයෙහි මුදුන පිරිසිදු කරන්න"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"මුහුණ සත්යාපනය කළ නොහැක. දෘඩාංගය නොමැත."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index fc383906..ea9f96c 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -583,7 +583,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Otočte hlavu o niečo menej."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Otočte hlavu o niečo menej."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Odstráňte všetko, čo vám zakrýva tvár."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Vyčistite senzor v hornom okraji obrazovky."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Tvár sa nedá overiť. Hardvér nie je k dispozícii."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index b426a97..23b1721 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -583,7 +583,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Malce manj nagnite glavo."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Glejte malce bolj naravnost."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Umaknite vse, kar vam morda zakriva obraz."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Očistite tipalo na zgornjem robu zaslona."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Obraza ni mogoče preveriti. Str. opr. ni na voljo."</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 29617d9..e6edb11 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Ktheje kokën pak më pak."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Ktheje kokën pak më pak."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Hiq gjithçka që fsheh fytyrën tënde."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Pastro sensorin në anën e sipërme të ekranit."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Pastro kreun e ekranit, duke përfshirë shiritin e zi"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Fytyra s\'mund të verifikohet. Hardueri nuk ofrohet."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index be10829..744377c 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -580,7 +580,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Мало мање померите главу."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Мало мање померите главу."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Уклоните све што вам заклања лице."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Очистите сензор на горњој ивици екрана."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Очистите горњи део екрана, укључујући црну траку"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Провера лица није успела. Хардвер није доступан."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 570d8cd..95da549 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -577,7 +577,7 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Vrid mindre på huvudet."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Vrid mindre på huvudet."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Ta bort allt som täcker ansiktet."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Rengör sensorn på skärmens överkant."</string>
+ <string name="face_acquired_sensor_dirty" msgid="7905138627046865579">"Rengör skärmens överkant, inklusive det svarta fältet"</string>
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Ansiktsverifiering går ej. Otillgänglig maskinvara."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index f7ca58e..5676566 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -309,7 +309,7 @@
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"Ungependa kuiruhusu <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ifikie rekodi zako za nambari za simu?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Simu"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"piga na udhibiti simu"</string>
- <string name="permgrouprequest_phone" msgid="9166979577750581037">"Ungependa kuiruhusu <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ipige na kudhibiti simu?"</string>
+ <string name="permgrouprequest_phone" msgid="9166979577750581037">"Ungependa kuruhusu <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> kupiga na kudhibiti simu?"</string>
<string name="permgrouplab_sensors" msgid="4838614103153567532">"Vihisi vya mwili"</string>
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"fikia data ya kitambuzi kuhusu alama zako muhimu"</string>
<string name="permgrouprequest_sensors" msgid="6349806962814556786">"Ungependa kuiruhusu <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ifikie data ya vitambuzi kuhusu viashiria muhimu vya mwili wako?"</string>
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Geuza kichwa chako kidogo."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Geuza kichwa chako kidogo."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Ondoa kitu chochote kinachoficha uso wako."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Safisha kitambuzi kwenye ukingo wa juu wa skrini."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Imeshindwa kuthibitisha uso. Maunzi hayapatikani."</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 093db49..0ec7216 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -131,8 +131,7 @@
<!-- no translation found for wfcSpnFormat_spn (4998685024207291232) -->
<skip />
<string name="wfcSpnFormat_spn_wifi_calling" msgid="136001023263502280">"<xliff:g id="SPN">%s</xliff:g> வைஃபை அழைப்பு"</string>
- <!-- no translation found for wfcSpnFormat_spn_wifi_calling_vo_hyphen (1730997175789582756) -->
- <skip />
+ <string name="wfcSpnFormat_spn_wifi_calling_vo_hyphen" msgid="1730997175789582756">"<xliff:g id="SPN">%s</xliff:g> வைஃபை அழைப்பு"</string>
<string name="wfcSpnFormat_wlan_call" msgid="2533371081782489793">"WLAN அழைப்பு"</string>
<string name="wfcSpnFormat_spn_wlan_call" msgid="2315240198303197168">"<xliff:g id="SPN">%s</xliff:g> WLAN அழைப்பு"</string>
<string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> வைஃபை"</string>
@@ -258,8 +257,7 @@
<string name="notification_channel_car_mode" msgid="3553380307619874564">"கார் பயன்முறை"</string>
<string name="notification_channel_account" msgid="7577959168463122027">"கணக்கின் நிலை"</string>
<string name="notification_channel_developer" msgid="7579606426860206060">"டெவெலப்பர் செய்திகள்"</string>
- <!-- no translation found for notification_channel_developer_important (5251192042281632002) -->
- <skip />
+ <string name="notification_channel_developer_important" msgid="5251192042281632002">"டெவெலப்பருக்கான முக்கிய தகவல்கள்"</string>
<string name="notification_channel_updates" msgid="4794517569035110397">"புதுப்பிப்புகள்"</string>
<string name="notification_channel_network_status" msgid="5025648583129035447">"நெட்வொர்க்கின் நிலை"</string>
<string name="notification_channel_network_alerts" msgid="2895141221414156525">"நெட்வொர்க் விழிப்பூட்டல்கள்"</string>
@@ -579,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"தலையை லேசாகத் திருப்பவும்."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"உங்கள் தலையைச் சற்றுத் திருப்பவும்."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"உங்கள் முகத்தை மறைக்கும் அனைத்தையும் நீக்குக."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"திரையின் மேல்முனையிலுள்ள சென்சாரைச் சுத்தம் செய்க."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"முகத்தைச் சரிபார்க்க இயலவில்லை. வன்பொருள் இல்லை."</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index f035d0e..113ea54 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"మీ తలను ఇంకాస్త తక్కువ తిప్పండి."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"మీ తలను ఎడమ/కుడి వైపుగా ఇంకాస్త తిప్పండి."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"మీ ముఖానికి అడ్డుగా ఉన్నవాటిని తీసివేస్తుంది."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"స్క్రీన్ ఎగువన ఉన్న సెన్సార్ను శుభ్రం చేస్తుంది."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ముఖం ధృవీకరించలేరు. హార్డ్వేర్ అందుబాటులో లేదు."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index e632ec6..2132216 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"จัดตำแหน่งศีรษะให้ตรง"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"จัดตำแหน่งศีรษะให้ตรง"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"เอาสิ่งที่ปิดบังใบหน้าออก"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"ทำความสะอาดเซ็นเซอร์ที่ขอบด้านบนของหน้าจอ"</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"ยืนยันใบหน้าไม่ได้ ฮาร์ดแวร์ไม่พร้อมใช้งาน"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 2c8fc8b..14fa1f8 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Huwag masyadong tumingala o yumuko."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Huwag masyadong lumingon."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Alisin ang anumang humaharang sa iyong mukha."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Linisinin ang sensor sa itaas na gilid ng screen."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Di ma-verify ang mukha. Di available ang hardware."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 4155920..2a88e74 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Başınızı biraz daha az çevirin."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Başınızı biraz daha az çevirin."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Yüzünüzün görünmesini engelleyen şeyleri kaldırın."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Ekranın üst kenarındaki sensörü temizleyin."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Yüz doğrulanamıyor. Donanım kullanılamıyor."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 101b526..961f577 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -583,7 +583,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Трохи перемістіть обличчя."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Трохи поверніть обличчя."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Приберіть об’єкти, які затуляють ваше обличчя."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Очистьте датчик угорі екрана."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Не вдається перевірити обличчя. Апаратне забезпечення недоступне."</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index fa2a194..69b6107 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"اپنا سر تھوڑا کم کریں۔"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"اپنا سر تھوڑا کم کریں۔"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"آپ کے چہرہ کو چھپانے والی ہر چیز کو ہٹائیں۔"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"اسکرین کے بالائی کنارے پر سنسر کو صاف کریں۔"</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"چہرے کی توثیق نہیں کی جا سکی۔ ہارڈ ویئر دستیاب نہیں ہے۔"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 21a8931..d7e4e5c 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Boshingizni asta buring."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Boshingizni asta buring."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Yuzingizni berkitayotgan narsalarni olib tashlang."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Ekranning tepasidagi sensorni tozalang."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Yuzingiz tasdiqlanmadi. Qurilma ishlamayapti."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 1363160..cdafd02 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Hãy bớt di chuyển đầu."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Hãy bớt di chuyển đầu."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Hãy loại bỏ mọi thứ che khuất khuôn mặt bạn."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Hãy lau sạch cảm biến ở cạnh trên của màn hình."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Không thể xác minh khuôn mặt. Phần cứng không có sẵn."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 12df563..f3283cb 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"请将您的头稍微上下倾斜。"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"请将您的头稍微左右旋转。"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"请移除所有遮挡您面部的物体。"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"请将屏幕顶部边缘的传感器擦拭干净。"</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"无法验证人脸。硬件无法使用。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index a484ec2d..f13e60f 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"減少頭部上下轉動幅度。"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"減少頭部左右轉動幅度。"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"移除遮住您臉孔的任何東西。"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"請清潔螢幕頂部邊緣的感應器。"</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"無法驗證臉孔,硬件無法使用。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index eb1519e..b83fb35 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"請將你的頭部稍微向上或向下傾斜。"</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"請將你的頭部稍微向左或向右旋轉。"</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"請移除任何會遮住臉孔的物體。"</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"請清除螢幕頂端感應器的髒汙。"</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"相關硬體無法使用,因此無法驗證臉孔。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index c51e170..9aa84f6 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -577,7 +577,8 @@
<string name="face_acquired_tilt_too_extreme" msgid="4019954263012496468">"Jikisa ikhanda lakho kancane."</string>
<string name="face_acquired_roll_too_extreme" msgid="6312973147689664409">"Jikisa ikhanda lakho kancane."</string>
<string name="face_acquired_obscured" msgid="5357207702967893283">"Susa noma yini efihle ubuso bakho."</string>
- <string name="face_acquired_sensor_dirty" msgid="2535761002815565222">"Hlanza inzwa kunqenqema oluphezulu lwesikrini."</string>
+ <!-- no translation found for face_acquired_sensor_dirty (7905138627046865579) -->
+ <skip />
<string-array name="face_acquired_vendor">
</string-array>
<string name="face_error_hw_not_available" msgid="396883585636963908">"Ayikwazi ukuqinisekisa ubuso. Izingxenyekazi zekhompyutha azitholakali."</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 55d80ac..1a79adc 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -364,7 +364,7 @@
overridden by the device to present the capability of creating socket keepalives. -->
<!-- An Array of "[NetworkCapabilities.TRANSPORT_*],[supported keepalives] -->
<string-array translatable="false" name="config_networkSupportedKeepaliveCount">
- <item>0,3</item>
+ <item>0,1</item>
<item>1,3</item>
</string-array>
diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml
index 12a9ea2..bd4c484 100644
--- a/core/res/res/values/dimens_car.xml
+++ b/core/res/res/values/dimens_car.xml
@@ -147,5 +147,6 @@
<dimen name="action_bar_margin_end">@*android:dimen/car_margin</dimen>
<!-- Space between a button and another button or screen edge -->
<dimen name="action_bar_button_margin">@*android:dimen/car_padding_4</dimen>
+ <dimen name="action_bar_button_max_width">268dp</dimen>
<dimen name="action_bar_toggle_internal_padding">@*android:dimen/car_padding_3</dimen>
</resources>
diff --git a/core/res/res/values/styles_car.xml b/core/res/res/values/styles_car.xml
index d2f5cbb..ca3ba93 100644
--- a/core/res/res/values/styles_car.xml
+++ b/core/res/res/values/styles_car.xml
@@ -87,6 +87,11 @@
</style>
<!-- Action bar -->
+ <style name="ActionBarTitle" parent="@style/Widget.DeviceDefault.TextView">
+ <item name="android:singleLine">true</item>
+ <item name="android:textAppearance">?attr/textAppearanceLarge</item>
+ </style>
+
<style name="ActionBarButton"
parent="@style/Widget.DeviceDefault.Button.Borderless.Colored">
<item name="android:textAppearance">@style/ActionBarButtonTextAppearance</item>
@@ -94,11 +99,11 @@
<item name="android:paddingStart">@*android:dimen/car_padding_3</item>
<item name="android:paddingEnd">@*android:dimen/car_padding_3</item>
<item name="android:drawablePadding">@*android:dimen/car_padding_2</item>
+ <item name="android:maxWidth">@*android:dimen/action_bar_button_max_width</item>
</style>
<style name="ActionBarButtonTextAppearance"
parent="@style/TextAppearance.DeviceDefault.Widget.Button.Borderless.Colored">
- <item name="android:singleLine">true</item>
<item name="android:textAllCaps">false</item>
</style>
</resources>
diff --git a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
index 1b65603..707d7b3 100644
--- a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
+++ b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
@@ -19,13 +19,22 @@
import com.google.caliper.BeforeExperiment;
import com.google.caliper.Param;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
public class NetworkStatsBenchmark {
- private static final String UNDERLYING_IFACE = "wlan0";
+ private static final String[] UNDERLYING_IFACES = {"wlan0", "rmnet0"};
private static final String TUN_IFACE = "tun0";
private static final int TUN_UID = 999999999;
@Param({"100", "1000"})
private int mSize;
+ /**
+ * Should not be more than the length of {@link #UNDERLYING_IFACES}.
+ */
+ @Param({"1", "2"})
+ private int mNumUnderlyingIfaces;
private NetworkStats mNetworkStats;
@BeforeExperiment
@@ -33,8 +42,10 @@
mNetworkStats = new NetworkStats(0, mSize + 2);
int uid = 0;
NetworkStats.Entry recycle = new NetworkStats.Entry();
+ final List<String> allIfaces = getAllIfacesForBenchmark(); // also contains TUN_IFACE.
+ final int totalIfaces = allIfaces.size();
for (int i = 0; i < mSize; i++) {
- recycle.iface = (i < mSize / 2) ? TUN_IFACE : UNDERLYING_IFACE;
+ recycle.iface = allIfaces.get(i % totalIfaces);
recycle.uid = uid;
recycle.set = i % 2;
recycle.tag = NetworkStats.TAG_NONE;
@@ -48,22 +59,39 @@
uid++;
}
}
- recycle.iface = UNDERLYING_IFACE;
- recycle.uid = TUN_UID;
- recycle.set = NetworkStats.SET_FOREGROUND;
- recycle.tag = NetworkStats.TAG_NONE;
- recycle.rxBytes = 90000 * mSize;
- recycle.rxPackets = 40 * mSize;
- recycle.txBytes = 180000 * mSize;
- recycle.txPackets = 1200 * mSize;
- recycle.operations = 0;
- mNetworkStats.addValues(recycle);
+
+ for (int i = 0; i < mNumUnderlyingIfaces; i++) {
+ recycle.iface = UNDERLYING_IFACES[i];
+ recycle.uid = TUN_UID;
+ recycle.set = NetworkStats.SET_FOREGROUND;
+ recycle.tag = NetworkStats.TAG_NONE;
+ recycle.rxBytes = 90000 * mSize;
+ recycle.rxPackets = 40 * mSize;
+ recycle.txBytes = 180000 * mSize;
+ recycle.txPackets = 1200 * mSize;
+ recycle.operations = 0;
+ mNetworkStats.addValues(recycle);
+ }
+ }
+
+ private String[] getVpnUnderlyingIfaces() {
+ return Arrays.copyOf(UNDERLYING_IFACES, mNumUnderlyingIfaces);
+ }
+
+ /**
+ * Same as {@link #getVpnUnderlyingIfaces}, but also contains {@link #TUN_IFACE}.
+ */
+ private List<String> getAllIfacesForBenchmark() {
+ List<String> ifaces = new ArrayList<>();
+ ifaces.add(TUN_IFACE);
+ ifaces.addAll(Arrays.asList(getVpnUnderlyingIfaces()));
+ return ifaces;
}
public void timeMigrateTun(int reps) {
for (int i = 0; i < reps; i++) {
NetworkStats stats = mNetworkStats.clone();
- stats.migrateTun(TUN_UID, TUN_IFACE, UNDERLYING_IFACE);
+ stats.migrateTun(TUN_UID, TUN_IFACE, getVpnUnderlyingIfaces());
}
}
diff --git a/core/tests/benchmarks/src/android/text/format/AndroidTimeVsOthersBenchmark.java b/core/tests/benchmarks/src/android/text/format/AndroidTimeVsOthersBenchmark.java
new file mode 100644
index 0000000..ea24400
--- /dev/null
+++ b/core/tests/benchmarks/src/android/text/format/AndroidTimeVsOthersBenchmark.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+package android.text.format;
+
+import com.google.caliper.Benchmark;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+
+public class AndroidTimeVsOthersBenchmark {
+
+ private static final String[] TIMEZONE_IDS = {
+ "Europe/London",
+ "America/Los_Angeles",
+ "Asia/Shanghai",
+ };
+
+ @Benchmark
+ public void toMillis_androidTime(int reps) {
+ long answer = 0;
+ for (int i = 0; i < reps; i++) {
+ String timezoneId = TIMEZONE_IDS[i % TIMEZONE_IDS.length];
+ Time time = new Time(timezoneId);
+ time.set(1, 2, 3, 4, 5, 2010);
+ answer = time.toMillis(false);
+ }
+ // System.out.println(answer);
+ }
+
+ @Benchmark
+ public void toMillis_javaTime(int reps) {
+ long answer = 0;
+ for (int i = 0; i < reps; i++) {
+ String timezoneId = TIMEZONE_IDS[i % TIMEZONE_IDS.length];
+ LocalDateTime time = LocalDateTime.of(2010, 5 + 1, 4, 3, 2, 1);
+ ZoneOffset offset = ZoneId.of(timezoneId).getRules().getOffset(time);
+ answer = time.toInstant(offset).toEpochMilli();
+ }
+ // System.out.println(answer);
+ }
+
+ @Benchmark
+ public void toMillis_javaUtil(int reps) {
+ long answer = 0;
+ for (int i = 0; i < reps; i++) {
+ String timezoneId = TIMEZONE_IDS[i % TIMEZONE_IDS.length];
+ java.util.TimeZone timeZone = java.util.TimeZone.getTimeZone(timezoneId);
+ java.util.Calendar calendar = new java.util.GregorianCalendar(timeZone);
+ calendar.set(2010, 5, 4, 3, 2, 1);
+ calendar.set(java.util.Calendar.MILLISECOND, 0);
+ answer = calendar.getTimeInMillis();
+ }
+ // System.out.println(answer);
+ }
+
+ @Benchmark
+ public void toMillis_androidIucUtil(int reps) {
+ long answer = 0;
+ for (int i = 0; i < reps; i++) {
+ String timezoneId = TIMEZONE_IDS[i % TIMEZONE_IDS.length];
+ android.icu.util.TimeZone timeZone =
+ android.icu.util.TimeZone.getTimeZone(timezoneId);
+ android.icu.util.Calendar calendar = new android.icu.util.GregorianCalendar(timeZone);
+ calendar.set(2010, 5, 4, 3, 2, 1);
+ calendar.set(android.icu.util.Calendar.MILLISECOND, 0);
+ answer = calendar.getTimeInMillis();
+ }
+ // System.out.println(answer);
+ }
+}
diff --git a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java
index 0f32a82..6161108 100644
--- a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java
+++ b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java
@@ -24,6 +24,7 @@
import android.app.ActivityManager;
import android.app.Notification;
+import android.app.Person;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -87,6 +88,9 @@
assertEquals(0,
logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_SUMMARY));
assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CATEGORY));
+ assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_STYLE));
+ assertNull(logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_PEOPLE));
+
}
/** Verify that modifying the returned logMaker won't leave stale data behind for
@@ -159,6 +163,24 @@
sbn.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
}
+ @Test
+ public void testLogMakerWithPerson() {
+ Notification.Builder builder = getNotificationBuilder(GROUP_ID_1, CHANNEL_ID)
+ .addPerson(new Person.Builder().build());
+ final LogMaker logMaker = getNotification(PKG, builder).getLogMaker();
+ assertEquals(1,
+ logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_PEOPLE));
+ }
+
+ @Test
+ public void testLogMakerWithStyle() {
+ Notification.Builder builder = getNotificationBuilder(GROUP_ID_1, CHANNEL_ID)
+ .setStyle(new Notification.MessagingStyle(new Person.Builder().build()));
+ final LogMaker logMaker = getNotification(PKG, builder).getLogMaker();
+ assertEquals("android.app.Notification$MessagingStyle".hashCode(),
+ logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_STYLE));
+ }
+
private StatusBarNotification getNotification(String pkg, String group, String channelId) {
return getNotification(pkg, getNotificationBuilder(group, channelId));
}
diff --git a/core/tests/coretests/src/android/util/TimingsTraceLogTest.java b/core/tests/coretests/src/android/util/TimingsTraceLogTest.java
index 77d0552..f76471c 100644
--- a/core/tests/coretests/src/android/util/TimingsTraceLogTest.java
+++ b/core/tests/coretests/src/android/util/TimingsTraceLogTest.java
@@ -16,7 +16,7 @@
package android.util;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
import android.os.Trace;
@@ -31,7 +31,8 @@
/**
* Tests for {@link TimingsTraceLog}.
- * <p>Usage: bit FrameworksCoreTests:android.util.TimingsTraceLogTest
+ *
+ * <p>Usage: {@code atest FrameworksCoreTests:android.util.TimingsTraceLogTest}
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -64,7 +65,24 @@
});
t.start();
t.join();
- assertTrue(errors.toString(), errors.isEmpty());
+ assertThat(errors).isEmpty();
}
+ @Test
+ public void testGetUnfinishedTracesForDebug() {
+ TimingsTraceLog log = new TimingsTraceLog("TEST", Trace.TRACE_TAG_APP);
+ assertThat(log.getUnfinishedTracesForDebug()).isEmpty();
+
+ log.traceBegin("One");
+ assertThat(log.getUnfinishedTracesForDebug()).containsExactly("One").inOrder();
+
+ log.traceBegin("Two");
+ assertThat(log.getUnfinishedTracesForDebug()).containsExactly("One", "Two").inOrder();
+
+ log.traceEnd();
+ assertThat(log.getUnfinishedTracesForDebug()).containsExactly("One").inOrder();
+
+ log.traceEnd();
+ assertThat(log.getUnfinishedTracesForDebug()).isEmpty();
+ }
}
diff --git a/data/etc/car/com.android.car.developeroptions.xml b/data/etc/car/com.android.car.developeroptions.xml
index 76c8c62..5f5e908 100644
--- a/data/etc/car/com.android.car.developeroptions.xml
+++ b/data/etc/car/com.android.car.developeroptions.xml
@@ -42,6 +42,7 @@
<permission name="android.permission.PACKAGE_USAGE_STATS"/>
<permission name="android.permission.READ_SEARCH_INDEXABLES"/>
<permission name="android.permission.REBOOT"/>
+ <permission name="android.permission.REQUEST_NETWORK_SCORES"/>
<permission name="android.permission.SET_TIME"/>
<permission name="android.permission.STATUS_BAR"/>
<permission name="android.permission.TETHER_PRIVILEGED"/>
diff --git a/data/etc/com.android.settings.xml b/data/etc/com.android.settings.xml
index 3e53a38..72be9f5 100644
--- a/data/etc/com.android.settings.xml
+++ b/data/etc/com.android.settings.xml
@@ -41,6 +41,7 @@
<permission name="android.permission.PACKAGE_USAGE_STATS"/>
<permission name="android.permission.READ_SEARCH_INDEXABLES"/>
<permission name="android.permission.REBOOT"/>
+ <permission name="android.permission.REQUEST_NETWORK_SCORES"/>
<permission name="android.permission.SET_TIME"/>
<permission name="android.permission.STATUS_BAR"/>
<permission name="android.permission.TETHER_PRIVILEGED"/>
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index a305d48..1d735af 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -44,6 +44,7 @@
<permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
<permission name="android.permission.REAL_GET_TASKS"/>
+ <permission name="android.permission.REQUEST_NETWORK_SCORES"/>
<permission name="android.permission.RECEIVE_MEDIA_RESOURCE_USAGE"/>
<permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
<permission name="android.permission.START_ACTIVITY_AS_CALLER"/>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index a640122..ff4e100 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -185,6 +185,7 @@
<permission name="android.permission.ACCESS_CACHE_FILESYSTEM"/>
<permission name="android.permission.CLEAR_APP_CACHE"/>
<permission name="android.permission.CONNECTIVITY_INTERNAL"/>
+ <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
<permission name="android.permission.UPDATE_DEVICE_STATS"/>
</privapp-permissions>
diff --git a/data/keyboards/Vendor_045e_Product_028e.kl b/data/keyboards/Vendor_045e_Product_028e.kl
index 301601a..e4f48f9 100644
--- a/data/keyboards/Vendor_045e_Product_028e.kl
+++ b/data/keyboards/Vendor_045e_Product_028e.kl
@@ -22,9 +22,7 @@
key 308 BUTTON_Y
key 310 BUTTON_L1
key 311 BUTTON_R1
-key 314 BACK
-key 315 BUTTON_START
-key 316 HOME
+
key 317 BUTTON_THUMBL
key 318 BUTTON_THUMBR
@@ -44,3 +42,14 @@
# Hat.
axis 0x10 HAT_X
axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+
+# Button labeled as "BACK" (left-pointing triangle)
+key 314 BUTTON_SELECT
+
+# The branded "X" button in the center of the controller
+key 316 BUTTON_MODE
+
+# Button labeled as "START" (right-pointing triangle)
+key 315 BUTTON_START
diff --git a/data/keyboards/Vendor_057e_Product_2009.kl b/data/keyboards/Vendor_057e_Product_2009.kl
new file mode 100644
index 0000000..b36e946
--- /dev/null
+++ b/data/keyboards/Vendor_057e_Product_2009.kl
@@ -0,0 +1,68 @@
+# 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.
+
+#
+# Nintendo Switch Pro Controller - HAC-013 - Bluetooth
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Button labeled as "Y" but should really produce keycode "X"
+key 0x132 BUTTON_X
+# Button labeled as "B" but should really produce keycode "A"
+key 0x130 BUTTON_A
+# Button labeled as "A" but should really produce keycode "B"
+key 0x131 BUTTON_B
+# Button labeled as "X" but should really product keycode "Y"
+key 0x133 BUTTON_Y
+
+# Button labeled as "L"
+key 0x134 BUTTON_L1
+# Button labeled as "R"
+key 0x135 BUTTON_R1
+
+# No LT / RT axes on this controller. Instead, there are keys.
+# Trigger labeled as "ZL"
+key 0x136 BUTTON_L2
+# Trigger labeled as "ZR"
+key 0x137 BUTTON_R2
+
+# Left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+# Right Analog Stick
+axis 0x03 Z
+axis 0x04 RZ
+
+# Left stick click (generates linux BTN_SELECT)
+key 0x13a BUTTON_THUMBL
+# Right stick click (generates linux BTN_START)
+key 0x13b BUTTON_THUMBR
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Minus
+key 0x138 BUTTON_SELECT
+# Plus
+key 0x139 BUTTON_START
+
+# Circle
+key 0x13d BUTTON_MODE
+
+# Home key
+key 0x13c HOME
diff --git a/graphics/proto/Android.bp b/graphics/proto/Android.bp
index 1d06348..ddced59 100644
--- a/graphics/proto/Android.bp
+++ b/graphics/proto/Android.bp
@@ -5,7 +5,6 @@
type: "lite",
},
srcs: ["game_driver.proto"],
- no_framework_libs: true,
jarjar_rules: "jarjar-rules.txt",
sdk_version: "28",
}
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index 85b2d6f5..9f4a619 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -216,7 +216,7 @@
return false;
}
- ::ZipString name;
+ std::string name;
::ZipEntry entry;
// We need to hold back directories because many paths will contain them and we want to only
@@ -225,7 +225,7 @@
int32_t result;
while ((result = ::Next(cookie, &entry, &name)) == 0) {
- StringPiece full_file_path(reinterpret_cast<const char*>(name.name), name.name_length);
+ StringPiece full_file_path(name);
StringPiece leaf_file_path = full_file_path.substr(root_path_full.size());
if (!leaf_file_path.empty()) {
diff --git a/libs/androidfw/ZipFileRO.cpp b/libs/androidfw/ZipFileRO.cpp
index ee5f778..e77ac3d 100644
--- a/libs/androidfw/ZipFileRO.cpp
+++ b/libs/androidfw/ZipFileRO.cpp
@@ -39,7 +39,7 @@
class _ZipEntryRO {
public:
ZipEntry entry;
- ZipString name;
+ std::string_view name;
void *cookie;
_ZipEntryRO() : cookie(NULL) {}
@@ -96,7 +96,7 @@
{
_ZipEntryRO* data = new _ZipEntryRO;
- data->name = ZipString(entryName);
+ data->name = entryName;
const int32_t error = FindEntry(mHandle, entryName, &(data->entry));
if (error) {
@@ -194,14 +194,14 @@
const
{
const _ZipEntryRO* zipEntry = reinterpret_cast<_ZipEntryRO*>(entry);
- const uint16_t requiredSize = zipEntry->name.name_length + 1;
+ const uint16_t requiredSize = zipEntry->name.length() + 1;
if (bufLen < requiredSize) {
ALOGW("Buffer too short, requires %d bytes for entry name", requiredSize);
return requiredSize;
}
- memcpy(buffer, zipEntry->name.name, requiredSize - 1);
+ memcpy(buffer, zipEntry->name.data(), requiredSize - 1);
buffer[requiredSize - 1] = '\0';
return 0;
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 82bcf9e..354a4b3 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -241,6 +241,7 @@
"JankTracker.cpp",
"Layer.cpp",
"LayerUpdateQueue.cpp",
+ "LightingInfo.cpp",
"ProfileData.cpp",
"ProfileDataContainer.cpp",
"Readback.cpp",
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index 0aab58c..b75192f 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -100,15 +100,15 @@
public:
void importUiThreadInfo(int64_t* info);
- void markSyncStart() { set(FrameInfoIndex::SyncStart) = systemTime(CLOCK_MONOTONIC); }
+ void markSyncStart() { set(FrameInfoIndex::SyncStart) = systemTime(SYSTEM_TIME_MONOTONIC); }
void markIssueDrawCommandsStart() {
- set(FrameInfoIndex::IssueDrawCommandsStart) = systemTime(CLOCK_MONOTONIC);
+ set(FrameInfoIndex::IssueDrawCommandsStart) = systemTime(SYSTEM_TIME_MONOTONIC);
}
- void markSwapBuffers() { set(FrameInfoIndex::SwapBuffers) = systemTime(CLOCK_MONOTONIC); }
+ void markSwapBuffers() { set(FrameInfoIndex::SwapBuffers) = systemTime(SYSTEM_TIME_MONOTONIC); }
- void markFrameCompleted() { set(FrameInfoIndex::FrameCompleted) = systemTime(CLOCK_MONOTONIC); }
+ void markFrameCompleted() { set(FrameInfoIndex::FrameCompleted) = systemTime(SYSTEM_TIME_MONOTONIC); }
void addFlag(int frameInfoFlag) {
set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
diff --git a/libs/hwui/LightingInfo.cpp b/libs/hwui/LightingInfo.cpp
new file mode 100644
index 0000000..83bb255
--- /dev/null
+++ b/libs/hwui/LightingInfo.cpp
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#include "LightingInfo.h"
+
+#include <float.h>
+
+namespace android {
+namespace uirenderer {
+
+float LightingInfo::mLightRadius = 0;
+uint8_t LightingInfo::mAmbientShadowAlpha = 0;
+uint8_t LightingInfo::mSpotShadowAlpha = 0;
+
+Vector3 LightingInfo::mLightCenter = {FLT_MIN, FLT_MIN, FLT_MIN};
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/LightingInfo.h b/libs/hwui/LightingInfo.h
new file mode 100644
index 0000000..3112eb3
--- /dev/null
+++ b/libs/hwui/LightingInfo.h
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Lighting.h"
+#include "Properties.h"
+
+namespace android {
+namespace uirenderer {
+
+class LightingInfo {
+public:
+
+ static float getLightRadius() {
+ if (CC_UNLIKELY(Properties::overrideLightRadius > 0)) {
+ return Properties::overrideLightRadius;
+ }
+ return mLightRadius;
+ }
+
+ static uint8_t getAmbientShadowAlpha() {
+ if (CC_UNLIKELY(Properties::overrideAmbientShadowStrength >= 0)) {
+ return Properties::overrideAmbientShadowStrength;
+ }
+ return mAmbientShadowAlpha;
+ }
+
+ static uint8_t getSpotShadowAlpha() {
+ if (CC_UNLIKELY(Properties::overrideSpotShadowStrength >= 0)) {
+ return Properties::overrideSpotShadowStrength;
+ }
+ return mSpotShadowAlpha;
+ }
+
+ static Vector3 getLightCenter() {
+ if (CC_UNLIKELY(Properties::overrideLightPosY > 0 || Properties::overrideLightPosZ > 0)) {
+ Vector3 adjustedLightCenter = mLightCenter;
+ if (CC_UNLIKELY(Properties::overrideLightPosY > 0)) {
+ // negated since this shifts up
+ adjustedLightCenter.y = -Properties::overrideLightPosY;
+ }
+ if (CC_UNLIKELY(Properties::overrideLightPosZ > 0)) {
+ adjustedLightCenter.z = Properties::overrideLightPosZ;
+ }
+ return adjustedLightCenter;
+ }
+ return mLightCenter;
+ }
+
+ static Vector3 getLightCenterRaw() {
+ return mLightCenter;
+ }
+
+ static void setLightCenterRaw(const Vector3& lightCenter) {
+ mLightCenter = lightCenter;
+ }
+
+ static void updateLighting(const LightGeometry& lightGeometry, const LightInfo& lightInfo) {
+ mLightRadius = lightGeometry.radius;
+ mAmbientShadowAlpha = lightInfo.ambientShadowAlpha;
+ mSpotShadowAlpha = lightInfo.spotShadowAlpha;
+ mLightCenter = lightGeometry.center;
+ }
+private:
+ static float mLightRadius;
+ static uint8_t mAmbientShadowAlpha;
+ static uint8_t mSpotShadowAlpha;
+ static Vector3 mLightCenter;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/ProfileData.cpp b/libs/hwui/ProfileData.cpp
index 70ca4e3..c7f9232 100644
--- a/libs/hwui/ProfileData.cpp
+++ b/libs/hwui/ProfileData.cpp
@@ -143,7 +143,7 @@
mSlowFrameCounts.fill(0);
mTotalFrameCount = 0;
mJankFrameCount = 0;
- mStatStartTime = systemTime(CLOCK_MONOTONIC);
+ mStatStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
}
void ProfileData::reportFrame(int64_t duration) {
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp
index 7677f9c..4544bea 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.cpp
+++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp
@@ -24,12 +24,6 @@
#include <optional>
-#ifdef __APPLE__
- // macOS SDK 10.10 does not support CLOCK_MONOTONIC, which is not an issue since
- // the value of the argument is not used in the host definition of systemTime
-#define CLOCK_MONOTONIC
-#endif
-
namespace android {
AnimatedImageDrawable::AnimatedImageDrawable(sk_sp<SkAnimatedImage> animatedImage, size_t bytesUsed)
@@ -70,7 +64,7 @@
// Only called on the RenderThread while UI thread is locked.
bool AnimatedImageDrawable::isDirty(nsecs_t* outDelay) {
*outDelay = 0;
- const nsecs_t currentTime = systemTime(CLOCK_MONOTONIC);
+ const nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
const nsecs_t lastWallTime = mLastWallTime;
mLastWallTime = currentTime;
@@ -250,7 +244,7 @@
bool update = false;
{
- const nsecs_t currentTime = systemTime(CLOCK_MONOTONIC);
+ const nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
std::unique_lock lock{mSwapLock};
// mLastWallTime starts off at 0. If it is still 0, just update it to
// the current time and avoid updating
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index 0a3c8f4..5133bae 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -17,7 +17,7 @@
#include "ReorderBarrierDrawables.h"
#include "RenderNode.h"
#include "SkiaDisplayList.h"
-#include "SkiaPipeline.h"
+#include "LightingInfo.h"
#include <SkPathOps.h>
#include <SkShadowUtils.h>
@@ -139,8 +139,8 @@
return;
}
- float ambientAlpha = (SkiaPipeline::getAmbientShadowAlpha() / 255.f) * casterAlpha;
- float spotAlpha = (SkiaPipeline::getSpotShadowAlpha() / 255.f) * casterAlpha;
+ float ambientAlpha = (LightingInfo::getAmbientShadowAlpha() / 255.f) * casterAlpha;
+ float spotAlpha = (LightingInfo::getSpotShadowAlpha() / 255.f) * casterAlpha;
const RevealClip& revealClip = casterProperties.getRevealClip();
const SkPath* revealClipPath = revealClip.getPath();
@@ -192,7 +192,7 @@
casterPath = &tmpPath;
}
- const Vector3 lightPos = SkiaPipeline::getLightCenter();
+ const Vector3 lightPos = LightingInfo::getLightCenter();
SkPoint3 skiaLightPos = SkPoint3::Make(lightPos.x, lightPos.y, lightPos.z);
SkPoint3 zParams;
if (shadowMatrix.hasPerspective()) {
@@ -206,7 +206,7 @@
SkColor ambientColor = multiplyAlpha(casterProperties.getAmbientShadowColor(), ambientAlpha);
SkColor spotColor = multiplyAlpha(casterProperties.getSpotShadowColor(), spotAlpha);
SkShadowUtils::DrawShadow(
- canvas, *casterPath, zParams, skiaLightPos, SkiaPipeline::getLightRadius(),
+ canvas, *casterPath, zParams, skiaLightPos, LightingInfo::getLightRadius(),
ambientColor, spotColor,
casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0);
}
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 8092b1d..e7efe2f 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -18,6 +18,7 @@
#include "DeferredLayerUpdater.h"
#include "LayerDrawable.h"
+#include "LightingInfo.h"
#include "SkiaPipeline.h"
#include "SkiaProfileRenderer.h"
#include "hwui/Bitmap.h"
@@ -99,7 +100,7 @@
mRenderThread.getGrContext(), backendRT, this->getSurfaceOrigin(), colorType,
mSurfaceColorSpace, &props));
- SkiaPipeline::updateLighting(lightGeometry, lightInfo);
+ LightingInfo::updateLighting(lightGeometry, lightInfo);
renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
SkMatrix::I());
layerUpdateQueue->clear();
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 0668281..ff29a5b 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -23,6 +23,7 @@
#include <SkOverdrawColorFilter.h>
#include <SkPicture.h>
#include <SkPictureRecorder.h>
+#include "LightingInfo.h"
#include "TreeInfo.h"
#include "VectorDrawable.h"
#include "thread/CommonPool.h"
@@ -38,12 +39,6 @@
namespace uirenderer {
namespace skiapipeline {
-float SkiaPipeline::mLightRadius = 0;
-uint8_t SkiaPipeline::mAmbientShadowAlpha = 0;
-uint8_t SkiaPipeline::mSpotShadowAlpha = 0;
-
-Vector3 SkiaPipeline::mLightCenter = {FLT_MIN, FLT_MIN, FLT_MIN};
-
SkiaPipeline::SkiaPipeline(RenderThread& thread) : mRenderThread(thread) {
mVectorDrawables.reserve(30);
}
@@ -84,7 +79,7 @@
void SkiaPipeline::renderLayers(const LightGeometry& lightGeometry,
LayerUpdateQueue* layerUpdateQueue, bool opaque,
const LightInfo& lightInfo) {
- updateLighting(lightGeometry, lightInfo);
+ LightingInfo::updateLighting(lightGeometry, lightInfo);
ATRACE_NAME("draw layers");
renderVectorDrawableCache();
renderLayersImpl(*layerUpdateQueue, opaque);
@@ -117,9 +112,13 @@
layerCanvas->androidFramework_setDeviceClipRestriction(layerDamage.toSkIRect());
- auto savedLightCenter = mLightCenter;
+ // TODO: put localized light center calculation and storage to a drawable related code.
+ // It does not seem right to store something localized in a global state
+ const Vector3 savedLightCenter(LightingInfo::getLightCenterRaw());
+ Vector3 transformedLightCenter(savedLightCenter);
// map current light center into RenderNode's coordinate space
- layerNode->getSkiaLayer()->inverseTransformInWindow.mapPoint3d(mLightCenter);
+ layerNode->getSkiaLayer()->inverseTransformInWindow.mapPoint3d(transformedLightCenter);
+ LightingInfo::setLightCenterRaw(transformedLightCenter);
const RenderProperties& properties = layerNode->properties();
const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
@@ -136,7 +135,7 @@
RenderNodeDrawable root(layerNode, layerCanvas, false);
root.forceDraw(layerCanvas);
layerCanvas->restoreToCount(saveCount);
- mLightCenter = savedLightCenter;
+ LightingInfo::setLightCenterRaw(savedLightCenter);
// cache the current context so that we can defer flushing it until
// either all the layers have been rendered or the context changes
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index 41d8646..5fc1d61 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -60,49 +60,6 @@
void renderLayersImpl(const LayerUpdateQueue& layers, bool opaque);
- static float getLightRadius() {
- if (CC_UNLIKELY(Properties::overrideLightRadius > 0)) {
- return Properties::overrideLightRadius;
- }
- return mLightRadius;
- }
-
- static uint8_t getAmbientShadowAlpha() {
- if (CC_UNLIKELY(Properties::overrideAmbientShadowStrength >= 0)) {
- return Properties::overrideAmbientShadowStrength;
- }
- return mAmbientShadowAlpha;
- }
-
- static uint8_t getSpotShadowAlpha() {
- if (CC_UNLIKELY(Properties::overrideSpotShadowStrength >= 0)) {
- return Properties::overrideSpotShadowStrength;
- }
- return mSpotShadowAlpha;
- }
-
- static Vector3 getLightCenter() {
- if (CC_UNLIKELY(Properties::overrideLightPosY > 0 || Properties::overrideLightPosZ > 0)) {
- Vector3 adjustedLightCenter = mLightCenter;
- if (CC_UNLIKELY(Properties::overrideLightPosY > 0)) {
- // negated since this shifts up
- adjustedLightCenter.y = -Properties::overrideLightPosY;
- }
- if (CC_UNLIKELY(Properties::overrideLightPosZ > 0)) {
- adjustedLightCenter.z = Properties::overrideLightPosZ;
- }
- return adjustedLightCenter;
- }
- return mLightCenter;
- }
-
- static void updateLighting(const LightGeometry& lightGeometry, const LightInfo& lightInfo) {
- mLightRadius = lightGeometry.radius;
- mAmbientShadowAlpha = lightInfo.ambientShadowAlpha;
- mSpotShadowAlpha = lightInfo.spotShadowAlpha;
- mLightCenter = lightGeometry.center;
- }
-
void setPictureCapturedCallback(
const std::function<void(sk_sp<SkPicture>&&)>& callback) override {
mPictureCapturedCallback = callback;
@@ -163,11 +120,6 @@
std::unique_ptr<SkPictureRecorder> mRecorder;
std::unique_ptr<SkNWayCanvas> mNwayCanvas;
std::function<void(sk_sp<SkPicture>&&)> mPictureCapturedCallback;
-
- static float mLightRadius;
- static uint8_t mAmbientShadowAlpha;
- static uint8_t mSpotShadowAlpha;
- static Vector3 mLightCenter;
};
} /* namespace skiapipeline */
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index e8cb219..ad7c706 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -19,6 +19,7 @@
#include "DeferredLayerUpdater.h"
#include "Readback.h"
#include "ShaderCache.h"
+#include "LightingInfo.h"
#include "SkiaPipeline.h"
#include "SkiaProfileRenderer.h"
#include "VkInteropFunctorDrawable.h"
@@ -69,7 +70,7 @@
if (backBuffer.get() == nullptr) {
return false;
}
- SkiaPipeline::updateLighting(lightGeometry, lightInfo);
+ LightingInfo::updateLighting(lightGeometry, lightInfo);
renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer,
mVkSurface->getCurrentPreTransform());
ShaderCache::get().onVkFrameFlushed(mRenderThread.getGrContext());
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index f326ce8..c9203d9 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -463,7 +463,7 @@
}
SwapHistory& swap = mSwapHistory.next();
swap.damage = windowDirty;
- swap.swapCompletedTime = systemTime(CLOCK_MONOTONIC);
+ swap.swapCompletedTime = systemTime(SYSTEM_TIME_MONOTONIC);
swap.vsyncTime = mRenderThread.timeLord().latestVsync();
if (mNativeSurface.get()) {
int durationUs;
@@ -549,7 +549,7 @@
UiFrameInfoBuilder(frameInfo).addFlag(FrameInfoFlags::RTAnimation).setVsync(vsync, vsync);
TreeInfo info(TreeInfo::MODE_RT_ONLY, *this);
- prepareTree(info, frameInfo, systemTime(CLOCK_MONOTONIC), node);
+ prepareTree(info, frameInfo, systemTime(SYSTEM_TIME_MONOTONIC), node);
if (info.out.canDrawThisFrame) {
draw();
} else {
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 91dc3bc..1e59338 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -69,7 +69,7 @@
LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
mSyncResult = SyncResult::OK;
- mSyncQueued = systemTime(CLOCK_MONOTONIC);
+ mSyncQueued = systemTime(SYSTEM_TIME_MONOTONIC);
postAndWait();
return mSyncResult;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 1a1b9da..20247dc 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -339,7 +339,7 @@
};
nsecs_t lastVsync = renderThread->timeLord().latestVsync();
nsecs_t estimatedNextVsync = lastVsync + renderThread->timeLord().frameIntervalNanos();
- nsecs_t timeToNextVsync = estimatedNextVsync - systemTime(CLOCK_MONOTONIC);
+ nsecs_t timeToNextVsync = estimatedNextVsync - systemTime(SYSTEM_TIME_MONOTONIC);
// We expect the UI thread to take 4ms and for RT to be active from VSYNC+4ms to
// VSYNC+12ms or so, so aim for the gap during which RT is expected to
// be idle
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 8638142..ee1a7ce 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -103,7 +103,7 @@
[this]() { mRenderThread->drainDisplayEventQueue(); });
}
- virtual nsecs_t latestVsyncEvent() override { return systemTime(CLOCK_MONOTONIC); }
+ virtual nsecs_t latestVsyncEvent() override { return systemTime(SYSTEM_TIME_MONOTONIC); }
private:
RenderThread* mRenderThread;
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
index b82c5d1..784068f 100644
--- a/libs/hwui/renderthread/TimeLord.cpp
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -31,7 +31,7 @@
nsecs_t TimeLord::computeFrameTimeNanos() {
// Logic copied from Choreographer.java
- nsecs_t now = systemTime(CLOCK_MONOTONIC);
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
nsecs_t jitterNanos = now - mFrameTimeNanos;
if (jitterNanos >= mFrameIntervalNanos) {
nsecs_t lastFrameOffset = jitterNanos % mFrameIntervalNanos;
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 9c845f0..22d5abb 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -146,7 +146,7 @@
}
for (int i = 0; i < warmupFrameCount; i++) {
testContext.waitForVsync();
- nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
+ nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
proxy->syncAndDrawFrame();
}
@@ -161,10 +161,10 @@
ModifiedMovingAverage<double> avgMs(opts.reportFrametimeWeight);
- nsecs_t start = systemTime(CLOCK_MONOTONIC);
+ nsecs_t start = systemTime(SYSTEM_TIME_MONOTONIC);
for (int i = 0; i < opts.count; i++) {
testContext.waitForVsync();
- nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
+ nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
{
ATRACE_NAME("UI-Draw Frame");
UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
@@ -173,7 +173,7 @@
}
if (opts.reportFrametimeWeight) {
proxy->fence();
- nsecs_t done = systemTime(CLOCK_MONOTONIC);
+ nsecs_t done = systemTime(SYSTEM_TIME_MONOTONIC);
avgMs.add((done - vsync) / 1000000.0);
if (i % 10 == 9) {
printf("Average frametime %.3fms\n", avgMs.average());
@@ -181,7 +181,7 @@
}
}
proxy->fence();
- nsecs_t end = systemTime(CLOCK_MONOTONIC);
+ nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
if (reporter) {
outputBenchmarkReport(info, opts, reporter, proxy.get(), (end - start) / (double)s2ns(1));
diff --git a/libs/hwui/thread/WorkQueue.h b/libs/hwui/thread/WorkQueue.h
index 42f8503..46b8bc0 100644
--- a/libs/hwui/thread/WorkQueue.h
+++ b/libs/hwui/thread/WorkQueue.h
@@ -31,7 +31,7 @@
namespace android::uirenderer {
struct MonotonicClock {
- static nsecs_t now() { return systemTime(CLOCK_MONOTONIC); }
+ static nsecs_t now() { return systemTime(SYSTEM_TIME_MONOTONIC); }
};
class WorkQueue {
diff --git a/media/Android.bp b/media/Android.bp
index 70dacb2..4f9671f 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -27,7 +27,7 @@
installable: true,
// Make sure that the implementaion only relies on SDK or system APIs.
- no_framework_libs: true,
+ sdk_version: "core_platform",
libs: [
// The order matters. android_system_* library should come later.
"framework_media_annotation",
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 5645ba5..7ae6a02 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -367,6 +367,8 @@
public static final String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
/** Type is int. */
public static final String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
+ /** Type is int. */
+ public static final String TAG_THUMBNAIL_ORIENTATION = "ThumbnailOrientation";
/** Type is int. DNG Specification 1.4.0.0. Section 4 */
public static final String TAG_DNG_VERSION = "DNGVersion";
/** Type is int. DNG Specification 1.4.0.0. Section 4 */
@@ -1155,7 +1157,7 @@
new ExifTag(TAG_MAKE, 271, IFD_FORMAT_STRING),
new ExifTag(TAG_MODEL, 272, IFD_FORMAT_STRING),
new ExifTag(TAG_STRIP_OFFSETS, 273, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
- new ExifTag(TAG_ORIENTATION, 274, IFD_FORMAT_USHORT),
+ new ExifTag(TAG_THUMBNAIL_ORIENTATION, 274, IFD_FORMAT_USHORT),
new ExifTag(TAG_SAMPLES_PER_PIXEL, 277, IFD_FORMAT_USHORT),
new ExifTag(TAG_ROWS_PER_STRIP, 278, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
new ExifTag(TAG_STRIP_BYTE_COUNTS, 279, IFD_FORMAT_USHORT, IFD_FORMAT_ULONG),
diff --git a/media/proto/Android.bp b/media/proto/Android.bp
index 74fd525..2dc0d57 100644
--- a/media/proto/Android.bp
+++ b/media/proto/Android.bp
@@ -5,7 +5,6 @@
type: "lite",
},
srcs: ["mediaplayer2.proto"],
- no_framework_libs: true,
jarjar_rules: "jarjar-rules.txt",
sdk_version: "28",
}
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
index d946fbc..467c4a4 100644
--- a/packages/CarSystemUI/res/values/config.xml
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -29,6 +29,9 @@
<bool name="config_enableRightNavigationBar">false</bool>
<bool name="config_enableBottomNavigationBar">true</bool>
+ <!-- Whether heads-up notifications should be shown when shade is open. -->
+ <bool name="config_enableHeadsUpNotificationWhenNotificationShadeOpen">true</bool>
+
<bool name="config_hideNavWhenKeyguardBouncerShown">true</bool>
<bool name="config_enablePersistentDockedActivity">false</bool>
<string name="config_persistentDockedActivityIntentUri" translatable="false"></string>
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 16b0125..ed5ab6a 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -165,6 +165,8 @@
private boolean mIsNotificationCardSwiping;
// If notification shade is being swiped vertically to close.
private boolean mIsSwipingVerticallyToClose;
+ // Whether heads-up notifications should be shown when shade is open.
+ private boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen;
private final CarPowerStateListener mCarPowerStateListener =
(int state) -> {
@@ -423,14 +425,13 @@
}
);
- mNotificationClickHandlerFactory = new NotificationClickHandlerFactory(
- mBarService,
- launchResult -> {
- if (launchResult == ActivityManager.START_TASK_TO_FRONT
- || launchResult == ActivityManager.START_SUCCESS) {
- animateCollapsePanels();
- }
- });
+ mNotificationClickHandlerFactory = new NotificationClickHandlerFactory(mBarService);
+ mNotificationClickHandlerFactory.registerClickListener((launchResult, alertEntry) -> {
+ if (launchResult == ActivityManager.START_TASK_TO_FRONT
+ || launchResult == ActivityManager.START_SUCCESS) {
+ animateCollapsePanels();
+ }
+ });
Car car = Car.createCar(mContext);
CarUxRestrictionsManager carUxRestrictionsManager = (CarUxRestrictionsManager)
car.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);
@@ -459,6 +460,8 @@
}
});
+ mEnableHeadsUpNotificationWhenNotificationShadeOpen = mContext.getResources().getBoolean(
+ R.bool.config_enableHeadsUpNotificationWhenNotificationShadeOpen);
CarHeadsUpNotificationManager carHeadsUpNotificationManager =
new CarSystemUIHeadsUpNotificationManager(mContext,
mNotificationClickHandlerFactory, mNotificationDataManager);
@@ -1273,11 +1276,18 @@
}
@Override
+ protected void setInternalInsetsInfo(ViewTreeObserver.InternalInsetsInfo info,
+ HeadsUpEntry currentNotification, boolean panelExpanded) {
+ super.setInternalInsetsInfo(info, currentNotification, mPanelExpanded);
+ }
+
+ @Override
protected void setHeadsUpVisible() {
// if the Notifications panel is showing don't show the Heads up
- if (mPanelExpanded) {
+ if (!mEnableHeadsUpNotificationWhenNotificationShadeOpen && mPanelExpanded) {
return;
}
+
super.setHeadsUpVisible();
if (mHeadsUpPanel.getVisibility() == View.VISIBLE) {
mStatusBarWindowController.setHeadsUpShowing(true);
diff --git a/packages/PackageInstaller/res/values/strings.xml b/packages/PackageInstaller/res/values/strings.xml
index 797656e..3e42706 100644
--- a/packages/PackageInstaller/res/values/strings.xml
+++ b/packages/PackageInstaller/res/values/strings.xml
@@ -4,9 +4,9 @@
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.
@@ -185,9 +185,6 @@
<!-- Placeholder for an app name when it is unknown [CHAR LIMIT=50] -->
<string name="app_name_unknown">Unknown</string>
- <!-- Help URL, application permissions [DO NOT TRANSLATE] -->
- <string name="help_app_permissions" translatable="false"></string>
-
<!-- Text to show in warning dialog on the tablet when the app source is not trusted [CHAR LIMIT=NONE] -->
<string name="untrusted_external_source_warning" product="tablet">For your security, your tablet is not allowed to install unknown apps from this source.</string>
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
index 05c2f24..ca2d1ed 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java
@@ -24,6 +24,7 @@
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY_URI;
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE_URI;
import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL;
import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY;
@@ -168,6 +169,11 @@
ensureMetadataNotStale(context);
final PackageManager packageManager = context.getPackageManager();
if (mMetaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
+ if (mMetaData.containsKey(META_DATA_PREFERENCE_TITLE_URI)) {
+ // If has as uri to provide dynamic summary, skip loading here. UI will later load
+ // at tile binding time.
+ return null;
+ }
if (mMetaData.get(META_DATA_PREFERENCE_TITLE) instanceof Integer) {
try {
final Resources res =
@@ -211,6 +217,8 @@
final PackageManager packageManager = context.getPackageManager();
if (mMetaData != null) {
if (mMetaData.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) {
+ // If has as uri to provide dynamic summary, skip loading here. UI will later load
+ // at tile binding time.
return null;
}
if (mMetaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) {
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
index 31925ab..aced5ef 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
@@ -162,6 +162,16 @@
/**
* Name of the meta-data item that should be set in the AndroidManifest.xml
+ * to specify the content provider providing the title text that should be displayed for the
+ * preference.
+ *
+ * Title provided by the content provider overrides any static title.
+ */
+ public static final String META_DATA_PREFERENCE_TITLE_URI =
+ "com.android.settings.title_uri";
+
+ /**
+ * Name of the meta-data item that should be set in the AndroidManifest.xml
* to specify the summary text that should be displayed for the preference.
*/
public static final String META_DATA_PREFERENCE_SUMMARY = "com.android.settings.summary";
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 381e480..59754e0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -712,11 +712,25 @@
public boolean matches(WifiConfiguration config) {
if (config.isPasspoint()) {
return (isPasspoint() && config.FQDN.equals(mConfig.FQDN));
- } else {
- // Normal non-Passpoint network
- return ssid.equals(removeDoubleQuotes(config.SSID))
- && security == getSecurity(config)
- && (mConfig == null || mConfig.shared == config.shared);
+ }
+
+ if (!ssid.equals(removeDoubleQuotes(config.SSID))
+ || (mConfig != null && mConfig.shared != config.shared)) {
+ return false;
+ }
+
+ final int configSecurity = getSecurity(config);
+ final WifiManager wifiManager = getWifiManager();
+ switch (security) {
+ case SECURITY_PSK_SAE_TRANSITION:
+ return configSecurity == SECURITY_PSK
+ || (wifiManager.isWpa3SaeSupported() && configSecurity == SECURITY_SAE);
+ case SECURITY_OWE_TRANSITION:
+ return configSecurity == SECURITY_NONE
+ || (wifiManager.isEnhancedOpenSupported()
+ && configSecurity == SECURITY_OWE);
+ default:
+ return security == configSecurity;
}
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/SensorManagerPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/SensorManagerPlugin.java
index 2cbd788..60435d0 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/SensorManagerPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/SensorManagerPlugin.java
@@ -58,7 +58,7 @@
public static final int TYPE_WAKE_LOCK_SCREEN = 1;
public static final int TYPE_WAKE_DISPLAY = 2;
public static final int TYPE_SWIPE = 3;
- public static final int TYPE_STATUS = 4;
+ public static final int TYPE_SKIP_STATUS = 4;
private int mType;
diff --git a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
index eabc5c5..508619a 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
@@ -22,6 +22,7 @@
android:focusable="true"
android:clickable="true"
>
+
<com.android.systemui.statusbar.notification.row.NotificationBackgroundView
android:id="@+id/backgroundNormal"
android:layout_width="match_parent"
@@ -38,28 +39,7 @@
android:gravity="center_vertical"
android:orientation="horizontal"
>
- <TextView
- android:id="@+id/header_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_marginStart="@dimen/notification_section_header_padding_left"
- android:gravity="start"
- android:textAlignment="gravity"
- android:text="@string/notification_section_header_gentle"
- android:textSize="12sp"
- android:textColor="@color/notification_section_header_label_color"
- android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
- />
- <ImageView
- android:id="@+id/btn_clear_all"
- android:layout_width="@dimen/notification_section_header_height"
- android:layout_height="@dimen/notification_section_header_height"
- android:layout_marginEnd="4dp"
- android:src="@drawable/status_bar_notification_section_header_clear_btn"
- android:contentDescription="@string/accessibility_notification_section_header_gentle_clear_all"
- android:scaleType="center"
- />
+ <include layout="@layout/status_bar_notification_section_header_contents"/>
</LinearLayout>
<com.android.systemui.statusbar.notification.FakeShadowView
diff --git a/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml b/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml
new file mode 100644
index 0000000..feabd1c
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml
@@ -0,0 +1,41 @@
+<!--
+ ~ 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
+ -->
+
+<!-- Used by both status_bar_notification_header and SectionHeaderView -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
+ <TextView
+ android:id="@+id/header_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginStart="@dimen/notification_section_header_padding_left"
+ android:gravity="start"
+ android:textAlignment="gravity"
+ android:text="@string/notification_section_header_gentle"
+ android:textSize="12sp"
+ android:textColor="@color/notification_section_header_label_color"
+ android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+ />
+ <ImageView
+ android:id="@+id/btn_clear_all"
+ android:layout_width="@dimen/notification_section_header_height"
+ android:layout_height="@dimen/notification_section_header_height"
+ android:layout_marginEnd="4dp"
+ android:src="@drawable/status_bar_notification_section_header_clear_btn"
+ android:contentDescription="@string/accessibility_notification_section_header_gentle_clear_all"
+ android:scaleType="center"
+ />
+</merge>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 5dd01fe..bb7614a 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -40,6 +40,9 @@
<!-- Whether or not we show the number in the bar. -->
<bool name="config_statusBarShowNumber">false</bool>
+ <!-- For how long the lock screen can be on before the display turns off. -->
+ <integer name="config_lockScreenDisplayTimeout">10000</integer>
+
<!-- Vibrator pattern for camera gesture launch. -->
<integer-array translatable="false" name="config_cameraLaunchGestureVibePattern">
<item>0</item>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 77bb514..9228b17 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -55,10 +55,17 @@
/**
* Control the {@param alpha} of the back button in the navigation bar and {@param animate} if
* needed from current value
+ * @deprecated
*/
void setBackButtonAlpha(float alpha, boolean animate) = 8;
/**
+ * Control the {@param alpha} of the option nav bar button (back-button in 2 button mode
+ * and home bar in no-button mode) and {@param animate} if needed from current value
+ */
+ void setNavBarButtonAlpha(float alpha, boolean animate) = 19;
+
+ /**
* Proxies motion events from the homescreen UI to the status bar. Only called when
* swipe down is detected on WORKSPACE. The sender guarantees the following order of events on
* the tracking pointer.
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index f66463e..ffa69fa 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -365,6 +365,10 @@
} else {
setPercentTextAtCurrentLevel();
}
+ } else {
+ setContentDescription(
+ getContext().getString(mCharging ? R.string.accessibility_battery_level_charging
+ : R.string.accessibility_battery_level, mLevel));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 73e57de..f38b4f2 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -305,7 +305,7 @@
mAssistHintBlocked = blocked;
if (mAssistHintVisible && mAssistHintBlocked) {
- setAssistHintVisible(false);
+ hideAssistHandles();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
index 909b68b..0af333e 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
@@ -57,8 +57,8 @@
private static final String LEARNING_EVENT_COUNT_KEY = "reminder_exp_learning_event_count";
private static final String LEARNED_HINT_LAST_SHOWN_KEY =
"reminder_exp_learned_hint_last_shown";
- private static final long DEFAULT_LEARNING_TIME_MS = TimeUnit.DAYS.toMillis(200);
- private static final int DEFAULT_LEARNING_COUNT = 30000;
+ private static final long DEFAULT_LEARNING_TIME_MS = TimeUnit.DAYS.toMillis(10);
+ private static final int DEFAULT_LEARNING_COUNT = 10;
private static final long DEFAULT_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS = 150;
private static final long DEFAULT_SHOW_AND_GO_DELAYED_LONG_DELAY_MS =
TimeUnit.SECONDS.toMillis(1);
@@ -66,7 +66,7 @@
TimeUnit.SECONDS.toMillis(3);
private static final boolean DEFAULT_SUPPRESS_ON_LOCKSCREEN = false;
private static final boolean DEFAULT_SUPPRESS_ON_LAUNCHER = false;
- private static final boolean DEFAULT_SUPPRESS_ON_APPS = false;
+ private static final boolean DEFAULT_SUPPRESS_ON_APPS = true;
private static final String[] DEFAULT_HOME_CHANGE_ACTIONS = new String[] {
PackageManagerWrapper.ACTION_PREFERRED_ACTIVITY_CHANGED,
diff --git a/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java b/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java
index 61395f1..b3f57af 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java
@@ -22,28 +22,28 @@
import java.util.concurrent.Executor;
-class PhenotypeHelper {
+public class PhenotypeHelper {
- PhenotypeHelper() {}
+ public PhenotypeHelper() {}
- long getLong(String name, long defaultValue) {
+ public long getLong(String name, long defaultValue) {
return DeviceConfig.getLong(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue);
}
- int getInt(String name, int defaultValue) {
+ public int getInt(String name, int defaultValue) {
return DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue);
}
@Nullable
- String getString(String name, @Nullable String defaultValue) {
+ public String getString(String name, @Nullable String defaultValue) {
return DeviceConfig.getString(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue);
}
- boolean getBoolean(String name, boolean defaultValue) {
+ public boolean getBoolean(String name, boolean defaultValue) {
return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue);
}
- void addOnPropertiesChangedListener(
+ public void addOnPropertiesChangedListener(
Executor executor, DeviceConfig.OnPropertiesChangedListener listener) {
DeviceConfig.addOnPropertiesChangedListener(
DeviceConfig.NAMESPACE_SYSTEMUI, executor, listener);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index 368451a..5be097c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -36,13 +36,13 @@
* Delay entering low power mode when animating to make sure that we'll have
* time to move all elements into their final positions while still at 60 fps.
*/
- private static final int ENTER_DOZE_DELAY = 6000;
+ private static final int ENTER_DOZE_DELAY = 4000;
/**
* Hide wallpaper earlier when entering low power mode. The gap between
* hiding the wallpaper and changing the display mode is necessary to hide
* the black frame that's inherent to hardware specs.
*/
- public static final int ENTER_DOZE_HIDE_WALLPAPER_DELAY = 4500;
+ public static final int ENTER_DOZE_HIDE_WALLPAPER_DELAY = 2500;
private final DozeMachine.Service mDozeService;
private final Handler mHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 9616f0a..cc30fc8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -174,7 +174,7 @@
/**
* The default amount of time we stay awake (used for all key input)
*/
- public static final int AWAKE_INTERVAL_DEFAULT_MS = 10000;
+ public static final int AWAKE_INTERVAL_BOUNCER_MS = 10000;
/**
* How long to wait after the screen turns off due to timeout before
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 88a8b31..e5caf68 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -27,6 +27,9 @@
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SUPPORTS_WINDOW_CORNERS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_WINDOW_CORNER_RADIUS;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
import android.annotation.FloatRange;
import android.app.ActivityTaskManager;
@@ -67,6 +70,7 @@
import com.android.systemui.statusbar.phone.NavigationBarView;
import com.android.systemui.statusbar.phone.NavigationModeController;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.policy.CallbackController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -90,7 +94,6 @@
private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
public static final String TAG_OPS = "OverviewProxyService";
- public static final boolean DEBUG_OVERVIEW_PROXY = false;
private static final long BACKOFF_MILLIS = 1000;
private static final long DEFERRED_CALLBACK_MILLIS = 5000;
@@ -115,7 +118,7 @@
private boolean mBound;
private boolean mIsEnabled;
private int mCurrentBoundedUserId = -1;
- private float mBackButtonAlpha;
+ private float mNavBarButtonAlpha;
private MotionEvent mStatusBarGestureDownEvent;
private float mWindowCornerRadius;
private boolean mSupportsRoundedCornersOnWindows;
@@ -241,22 +244,25 @@
}
@Override
- public void setBackButtonAlpha(float alpha, boolean animate) {
- if (!verifyCaller("setBackButtonAlpha")) {
+ public void setNavBarButtonAlpha(float alpha, boolean animate) {
+ if (!verifyCaller("setNavBarButtonAlpha")) {
return;
}
long token = Binder.clearCallingIdentity();
try {
- mBackButtonAlpha = alpha;
- mHandler.post(() -> {
- notifyBackButtonAlphaChanged(alpha, animate);
- });
+ mNavBarButtonAlpha = alpha;
+ mHandler.post(() -> notifyNavBarButtonAlphaChanged(alpha, animate));
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
+ public void setBackButtonAlpha(float alpha, boolean animate) {
+ setNavBarButtonAlpha(alpha, animate);
+ }
+
+ @Override
public void onAssistantProgress(@FloatRange(from = 0.0, to = 1.0) float progress) {
if (!verifyCaller("onAssistantProgress")) {
return;
@@ -442,6 +448,8 @@
}
};
+ private final StatusBarWindowCallback mStatusBarWindowCallback = this::onStatusBarStateChanged;
+
// This is the death handler for the binder from the launcher service
private final IBinder.DeathRecipient mOverviewServiceDeathRcpt
= this::cleanupAfterDeath;
@@ -465,7 +473,7 @@
.supportsRoundedCornersOnWindows(mContext.getResources());
// Assumes device always starts with back button until launcher tells it that it does not
- mBackButtonAlpha = 1.0f;
+ mNavBarButtonAlpha = 1.0f;
// Listen for nav bar mode changes
mNavBarMode = navModeController.addListener(this);
@@ -481,6 +489,9 @@
PatternMatcher.PATTERN_LITERAL);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
mContext.registerReceiver(mLauncherStateChangedReceiver, filter);
+
+ // Listen for status bar state changes
+ statusBarWinController.registerCallback(mStatusBarWindowCallback);
}
public void notifyBackAction(boolean completed, int downX, int downY, boolean isButton,
@@ -531,7 +542,7 @@
navBarView.updateSystemUiStateFlags();
}
if (mStatusBarWinController != null) {
- mStatusBarWinController.updateSystemUiStateFlags();
+ mStatusBarWinController.notifyStateChangedCallbacks();
}
notifySystemUiStateFlags(mSysUiStateFlags);
}
@@ -546,6 +557,16 @@
}
}
+ private void onStatusBarStateChanged(boolean keyguardShowing, boolean keyguardOccluded,
+ boolean bouncerShowing) {
+ int displayId = mContext.getDisplayId();
+ setSystemUiStateFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING,
+ keyguardShowing && !keyguardOccluded, displayId);
+ setSystemUiStateFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED,
+ keyguardShowing && keyguardOccluded, displayId);
+ setSystemUiStateFlag(SYSUI_STATE_BOUNCER_SHOWING, bouncerShowing, displayId);
+ }
+
/**
* Sets the navbar region which can receive touch inputs
*/
@@ -565,7 +586,7 @@
}
public float getBackButtonAlpha() {
- return mBackButtonAlpha;
+ return mNavBarButtonAlpha;
}
public void cleanupAfterDeath() {
@@ -637,7 +658,7 @@
public void addCallback(OverviewProxyListener listener) {
mConnectionCallbacks.add(listener);
listener.onConnectionChanged(mOverviewProxy != null);
- listener.onBackButtonAlphaChanged(mBackButtonAlpha, false);
+ listener.onNavBarButtonAlphaChanged(mNavBarButtonAlpha, false);
listener.onSystemUiStateChanged(mSysUiStateFlags);
}
@@ -668,14 +689,14 @@
if (mOverviewProxy != null) {
mOverviewProxy.asBinder().unlinkToDeath(mOverviewServiceDeathRcpt, 0);
mOverviewProxy = null;
- notifyBackButtonAlphaChanged(1f, false /* animate */);
+ notifyNavBarButtonAlphaChanged(1f, false /* animate */);
notifyConnectionChanged();
}
}
- private void notifyBackButtonAlphaChanged(float alpha, boolean animate) {
+ private void notifyNavBarButtonAlphaChanged(float alpha, boolean animate) {
for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
- mConnectionCallbacks.get(i).onBackButtonAlphaChanged(alpha, animate);
+ mConnectionCallbacks.get(i).onNavBarButtonAlphaChanged(alpha, animate);
}
}
@@ -766,7 +787,8 @@
default void onQuickStepStarted() {}
default void onOverviewShown(boolean fromHome) {}
default void onQuickScrubStarted() {}
- default void onBackButtonAlphaChanged(float alpha, boolean animate) {}
+ /** Notify changes in the nav bar button alpha */
+ default void onNavBarButtonAlphaChanged(float alpha, boolean animate) {}
default void onSystemUiStateChanged(int sysuiStateFlags) {}
default void onAssistantProgress(@FloatRange(from = 0.0, to = 1.0) float progress) {}
default void onAssistantGestureCompletion(float velocity) {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
index 5747bb1..170a4d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
@@ -19,7 +19,6 @@
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
import android.annotation.Nullable;
-import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import android.view.LayoutInflater;
@@ -32,6 +31,8 @@
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
/**
* Manages the boundaries of the two notification sections (high priority and low priority). Also
@@ -43,8 +44,10 @@
private final NotificationStackScrollLayout mParent;
private final ActivityStarter mActivityStarter;
private final StatusBarStateController mStatusBarStateController;
+ private final ConfigurationController mConfigurationController;
private final boolean mUseMultipleSections;
+ private boolean mInitialized = false;
private SectionHeaderView mGentleHeader;
private boolean mGentleHeaderVisible = false;
@Nullable private ExpandableNotificationRow mFirstGentleNotif;
@@ -54,18 +57,29 @@
NotificationStackScrollLayout parent,
ActivityStarter activityStarter,
StatusBarStateController statusBarStateController,
+ ConfigurationController configurationController,
boolean useMultipleSections) {
mParent = parent;
mActivityStarter = activityStarter;
mStatusBarStateController = statusBarStateController;
+ mConfigurationController = configurationController;
mUseMultipleSections = useMultipleSections;
}
+ /** Must be called before use. */
+ void initialize(LayoutInflater layoutInflater) {
+ if (mInitialized) {
+ throw new IllegalStateException("NotificationSectionsManager already initialized");
+ }
+ mInitialized = true;
+ reinflateViews(layoutInflater);
+ mConfigurationController.addCallback(mConfigurationListener);
+ }
+
/**
- * Must be called before use. Should be called again whenever inflation-related things change,
- * such as density or theme changes.
+ * Reinflates the entire notification header, including all decoration views.
*/
- void inflateViews(Context context) {
+ void reinflateViews(LayoutInflater layoutInflater) {
int oldPos = -1;
if (mGentleHeader != null) {
if (mGentleHeader.getTransientContainer() != null) {
@@ -76,7 +90,7 @@
}
}
- mGentleHeader = (SectionHeaderView) LayoutInflater.from(context).inflate(
+ mGentleHeader = (SectionHeaderView) layoutInflater.inflate(
R.layout.status_bar_notification_section_header, mParent, false);
mGentleHeader.setOnHeaderClickListener(this::onGentleHeaderClick);
mGentleHeader.setOnClearAllClickListener(this::onClearGentleNotifsClick);
@@ -244,6 +258,13 @@
return lastChildBeforeGap;
}
+ private final ConfigurationListener mConfigurationListener = new ConfigurationListener() {
+ @Override
+ public void onLocaleListChanged() {
+ mGentleHeader.reinflateContents();
+ }
+ };
+
private void onGentleHeaderClick(View v) {
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_SETTINGS);
mActivityStarter.startActivity(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index cd2a654..aad35b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -32,7 +32,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.WallpaperManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
@@ -508,6 +507,7 @@
@Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress,
NotificationRoundnessManager notificationRoundnessManager,
DynamicPrivacyController dynamicPrivacyController,
+ ConfigurationController configurationController,
ActivityStarter activityStarter,
StatusBarStateController statusBarStateController,
HeadsUpManagerPhone headsUpManager,
@@ -532,8 +532,9 @@
this,
activityStarter,
statusBarStateController,
+ configurationController,
NotificationUtils.useNewInterruptionModel(context));
- mSectionsManager.inflateViews(context);
+ mSectionsManager.initialize(LayoutInflater.from(context));
mSectionsManager.setOnClearGentleNotifsClickListener(v -> {
// Leave the shade open if there will be other notifs left over to clear
final boolean closeShade = !hasActiveClearableNotifications(ROWS_HIGH_PRIORITY);
@@ -647,7 +648,7 @@
inflateFooterView();
inflateEmptyShadeView();
updateFooter();
- mSectionsManager.inflateViews(mContext);
+ mSectionsManager.reinflateViews(LayoutInflater.from(mContext));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
index e2f702d..cc1170f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
@@ -16,11 +16,16 @@
package com.android.systemui.statusbar.notification.stack;
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.Nullable;
import android.content.Context;
import android.graphics.RectF;
import android.util.AttributeSet;
+import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
@@ -32,9 +37,10 @@
* notification sections. Currently only used for gentle notifications.
*/
public class SectionHeaderView extends ActivatableNotificationView {
- private View mContents;
+ private ViewGroup mContents;
private TextView mLabelView;
private ImageView mClearAllButton;
+ @Nullable private View.OnClickListener mOnClearClickListener = null;
private final RectF mTmpRect = new RectF();
@@ -45,9 +51,16 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mContents = findViewById(R.id.content);
- mLabelView = findViewById(R.id.header_label);
- mClearAllButton = findViewById(R.id.btn_clear_all);
+ mContents = checkNotNull(findViewById(R.id.content));
+ bindContents();
+ }
+
+ private void bindContents() {
+ mLabelView = checkNotNull(findViewById(R.id.header_label));
+ mClearAllButton = checkNotNull(findViewById(R.id.btn_clear_all));
+ if (mOnClearClickListener != null) {
+ mClearAllButton.setOnClickListener(mOnClearClickListener);
+ }
}
@Override
@@ -55,6 +68,21 @@
return mContents;
}
+ /**
+ * Destroys and reinflates the visible contents of the section header. For use on configuration
+ * changes or any other time that layout values might need to be re-evaluated.
+ *
+ * Does not reinflate the base content view itself ({@link #getContentView()} or any of the
+ * decorator views, such as the background view or shadow view.
+ */
+ void reinflateContents() {
+ mContents.removeAllViews();
+ LayoutInflater.from(getContext()).inflate(
+ R.layout.status_bar_notification_section_header_contents,
+ mContents);
+ bindContents();
+ }
+
/** Must be called whenever the UI mode changes (i.e. when we enter night mode). */
void onUiModeChanged() {
updateBackgroundColors();
@@ -88,6 +116,7 @@
/** Fired when the user clicks on the "X" button on the far right of the header. */
void setOnClearAllClickListener(View.OnClickListener listener) {
+ mOnClearClickListener = listener;
mClearAllButton.setOnClickListener(listener);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 38ff468..cc0bc5f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -57,6 +57,7 @@
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.WindowManagerWrapper;
+import java.io.PrintWriter;
import java.util.concurrent.Executor;
/**
@@ -118,7 +119,7 @@
private final Region mExcludeRegion = new Region();
// The edge width where touch down is allowed
- private final int mEdgeWidth;
+ private int mEdgeWidth;
// The slop to distinguish between horizontal and vertical motion
private final float mTouchSlop;
// Duration after which we consider the event as longpress.
@@ -163,10 +164,6 @@
mWm = context.getSystemService(WindowManager.class);
mOverviewProxyService = overviewProxyService;
- // TODO: Get this for the current user
- mEdgeWidth = res.getDimensionPixelSize(
- com.android.internal.R.dimen.config_backGestureInset);
-
// Reduce the default touch slop to ensure that we can intercept the gesture
// before the app starts to react to it.
// TODO(b/130352502) Tune this value and extract into a constant
@@ -176,6 +173,12 @@
mNavBarHeight = res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height);
mMinArrowPosition = res.getDimensionPixelSize(R.dimen.navigation_edge_arrow_min_y);
mFingerOffset = res.getDimensionPixelSize(R.dimen.navigation_edge_finger_offset);
+ updateCurrentUserResources(res);
+ }
+
+ public void updateCurrentUserResources(Resources res) {
+ mEdgeWidth = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.config_backGestureInset);
}
/**
@@ -194,9 +197,10 @@
updateIsEnabled();
}
- public void onNavigationModeChanged(int mode) {
+ public void onNavigationModeChanged(int mode, Context currentUserContext) {
mIsGesturalModeEnabled = QuickStepContract.isGesturalMode(mode);
updateIsEnabled();
+ updateCurrentUserResources(currentUserContext.getResources());
}
private void disposeInputChannel() {
@@ -270,6 +274,8 @@
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
+ mEdgePanelLp.privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
mEdgePanelLp.setTitle(TAG + mDisplayId);
mEdgePanelLp.accessibilityTitle = mContext.getString(R.string.nav_bar_edge_panel);
mEdgePanelLp.windowAnimations = 0;
@@ -449,6 +455,16 @@
mRightInset = rightInset;
}
+ public void dump(PrintWriter pw) {
+ pw.println("EdgeBackGestureHandler:");
+ pw.println(" mIsEnabled=" + mIsEnabled);
+ pw.println(" mAllowGesture=" + mAllowGesture);
+ pw.println(" mExcludeRegion=" + mExcludeRegion);
+ pw.println(" mImeHeight=" + mImeHeight);
+ pw.println(" mIsAttached=" + mIsAttached);
+ pw.println(" mEdgeWidth=" + mEdgeWidth);
+ }
+
class SysUiInputEventReceiver extends InputEventReceiver {
SysUiInputEventReceiver(InputChannel channel, Looper looper) {
super(channel, looper);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
index 6bbeffa..deb314b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
@@ -115,7 +115,6 @@
return false;
}
mWindowManager.removeViewImmediate(mKeyButtonView);
- mRotationButtonController.cleanUp();
mIsShowing = false;
return true;
}
@@ -141,10 +140,7 @@
@Override
public void setOnClickListener(View.OnClickListener onClickListener) {
- mKeyButtonView.setOnClickListener(view -> {
- hide();
- onClickListener.onClick(view);
- });
+ mKeyButtonView.setOnClickListener(onClickListener);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 07436f8..69c2a70 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -420,10 +420,10 @@
private int getState() {
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
- if (mTransientBiometricsError) {
- return STATE_BIOMETRICS_ERROR;
- } else if ((mUnlockMethodCache.canSkipBouncer() || !mKeyguardShowing) && !mSimLocked) {
+ if ((mUnlockMethodCache.canSkipBouncer() || !mKeyguardShowing) && !mSimLocked) {
return STATE_LOCK_OPEN;
+ } else if (mTransientBiometricsError) {
+ return STATE_BIOMETRICS_ERROR;
} else if (updateMonitor.isFaceDetectionRunning()) {
return STATE_SCANNING_FACE;
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index 443cc43..c0a1b12 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -112,7 +112,9 @@
final boolean guestEnabled = !mContext.getSystemService(DevicePolicyManager.class)
.getGuestUserDisabled(null);
- return mUserSwitcherController.getSwitchableUserCount() > 1 || guestEnabled
+ return mUserSwitcherController.getSwitchableUserCount() > 1
+ // If we cannot add guests even if they are enabled, do not show
+ || (guestEnabled && !mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER))
|| mContext.getResources().getBoolean(R.bool.qs_show_user_switcher_for_single_user);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 79976d0..b56abcd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -203,17 +203,16 @@
}
@Override
- public void onBackButtonAlphaChanged(float alpha, boolean animate) {
- final ButtonDispatcher backButton = mNavigationBarView.getBackButton();
- final boolean useAltBack =
- (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
- if (QuickStepContract.isGesturalMode(mNavBarMode) && !useAltBack) {
- // If property was changed to hide/show back button, going home will trigger
- // launcher to to change the back button alpha to reflect property change
- backButton.setVisibility(View.GONE);
- } else {
- backButton.setVisibility(alpha > 0 ? View.VISIBLE : View.INVISIBLE);
- backButton.setAlpha(alpha, animate);
+ public void onNavBarButtonAlphaChanged(float alpha, boolean animate) {
+ ButtonDispatcher buttonDispatcher = null;
+ if (QuickStepContract.isSwipeUpMode(mNavBarMode)) {
+ buttonDispatcher = mNavigationBarView.getBackButton();
+ } else if (QuickStepContract.isGesturalMode(mNavBarMode)) {
+ buttonDispatcher = mNavigationBarView.getHomeHandle();
+ }
+ if (buttonDispatcher != null) {
+ buttonDispatcher.setVisibility(alpha > 0 ? View.VISIBLE : View.INVISIBLE);
+ buttonDispatcher.setAlpha(alpha, animate);
}
}
};
@@ -872,9 +871,6 @@
boolean[] feedbackEnabled = new boolean[1];
int a11yFlags = getA11yButtonState(feedbackEnabled);
- mNavigationBarView.getRotationButtonController().setAccessibilityFeedbackEnabled(
- feedbackEnabled[0]);
-
boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0;
mNavigationBarView.setAccessibilityButtonState(clickable, longClickable);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 90bce39..9919abd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -772,9 +772,10 @@
@Override
public void onNavigationModeChanged(int mode) {
+ Context curUserCtx = Dependency.get(NavigationModeController.class).getCurrentUserContext();
mNavBarMode = mode;
mBarTransitions.onNavigationModeChanged(mNavBarMode);
- mEdgeBackGestureHandler.onNavigationModeChanged(mNavBarMode);
+ mEdgeBackGestureHandler.onNavigationModeChanged(mNavBarMode, curUserCtx);
mRecentsOnboarding.onNavigationModeChanged(mNavBarMode);
getRotateSuggestionButton().onNavigationModeChanged(mNavBarMode);
@@ -1039,6 +1040,9 @@
reorient();
onNavigationModeChanged(mNavBarMode);
setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
+ if (mRotationButtonController != null) {
+ mRotationButtonController.registerListeners();
+ }
mEdgeBackGestureHandler.onNavBarAttached();
getViewTreeObserver().addOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener);
@@ -1052,6 +1056,10 @@
for (int i = 0; i < mButtonDispatchers.size(); ++i) {
mButtonDispatchers.valueAt(i).onDestroy();
}
+ if (mRotationButtonController != null) {
+ mRotationButtonController.unregisterListeners();
+ }
+
mEdgeBackGestureHandler.onNavBarDetached();
getViewTreeObserver().removeOnComputeInternalInsetsListener(
mOnComputeInternalInsetsListener);
@@ -1103,6 +1111,7 @@
mContextualButtonGroup.dump(pw);
mRecentsOnboarding.dump(pw);
mTintController.dump(pw);
+ mEdgeBackGestureHandler.dump(pw);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
index 77eb469..1124220 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
@@ -224,7 +224,7 @@
return mode;
}
- private Context getCurrentUserContext() {
+ public Context getCurrentUserContext() {
int userId = ActivityManagerWrapper.getInstance().getCurrentUserId();
if (DEBUG) {
Log.d(TAG, "getCurrentUserContext: contextUser=" + mContext.getUserId()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index e51baf3..4acf7b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -316,10 +316,11 @@
@Override
public void onViewRemoved(View child) {
super.onViewRemoved(child);
- if (mAnimationsEnabled && child instanceof StatusBarIconView) {
+
+ if (child instanceof StatusBarIconView) {
boolean isReplacingIcon = isReplacingIcon(child);
final StatusBarIconView icon = (StatusBarIconView) child;
- if (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
+ if (mAnimationsEnabled && icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
&& child.getVisibility() == VISIBLE && isReplacingIcon) {
int animationStartIndex = findFirstViewIndexAfter(icon.getTranslationX());
if (mAddAnimationStartIndex < 0) {
@@ -330,7 +331,7 @@
}
if (!mChangingViewPositions) {
mIconStates.remove(child);
- if (!isReplacingIcon) {
+ if (mAnimationsEnabled && !isReplacingIcon) {
addTransientView(icon, 0);
boolean isIsolatedIcon = child == mIsolatedIcon;
icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, true /* animate */,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
index 1e5406f..0147e7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationButtonController.java
@@ -26,7 +26,7 @@
import android.content.ContentResolver;
import android.content.Context;
import android.os.Handler;
-import android.os.Message;
+import android.os.Looper;
import android.os.RemoteException;
import android.provider.Settings;
import android.view.IRotationWatcher.Stub;
@@ -34,6 +34,7 @@
import android.view.Surface;
import android.view.View;
import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -42,6 +43,7 @@
import com.android.systemui.R;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
import com.android.systemui.statusbar.policy.RotationLockController;
@@ -64,8 +66,10 @@
private boolean mPendingRotationSuggestion;
private boolean mHoveringRotationSuggestion;
private RotationLockController mRotationLockController;
+ private AccessibilityManagerWrapper mAccessibilityManagerWrapper;
private TaskStackListenerImpl mTaskStackListener;
private Consumer<Integer> mRotWatcherListener;
+ private boolean mListenersRegistered = false;
private boolean mIsNavigationBarShowing;
private final Runnable mRemoveRotationProposal =
@@ -73,22 +77,17 @@
private final Runnable mCancelPendingRotationProposal =
() -> mPendingRotationSuggestion = false;
private Animator mRotateHideAnimator;
- private boolean mAccessibilityFeedbackEnabled;
private final Context mContext;
private final RotationButton mRotationButton;
+ private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
private final Stub mRotationWatcher = new Stub() {
@Override
public void onRotationChanged(final int rotation) throws RemoteException {
- if (mRotationButton.getCurrentView() == null) {
- return;
- }
-
// We need this to be scheduled as early as possible to beat the redrawing of
// window in response to the orientation change.
- Handler h = mRotationButton.getCurrentView().getHandler();
- Message msg = Message.obtain(h, () -> {
+ mMainThreadHandler.postAtFrontOfQueue(() -> {
// If the screen rotation changes while locked, potentially update lock to flow with
// new screen rotation and hide any showing suggestions.
if (mRotationLockController.isRotationLocked()) {
@@ -102,8 +101,6 @@
mRotWatcherListener.accept(rotation);
}
});
- msg.setAsynchronous(true);
- h.sendMessageAtFrontOfQueue(msg);
}
};
@@ -124,40 +121,49 @@
mStyleRes = style;
mIsNavigationBarShowing = true;
mRotationLockController = Dependency.get(RotationLockController.class);
+ mAccessibilityManagerWrapper = Dependency.get(AccessibilityManagerWrapper.class);
// Register the task stack listener
mTaskStackListener = new TaskStackListenerImpl();
- ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
mRotationButton.setOnClickListener(this::onRotateSuggestionClick);
mRotationButton.setOnHoverListener(this::onRotateSuggestionHover);
+ }
+ void registerListeners() {
+ if (mListenersRegistered) {
+ return;
+ }
+
+ mListenersRegistered = true;
try {
WindowManagerGlobal.getWindowManagerService()
.watchRotation(mRotationWatcher, mContext.getDisplay().getDisplayId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
+
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
}
- void cleanUp() {
- // Unregister the task stack listener
- ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskStackListener);
+ void unregisterListeners() {
+ if (!mListenersRegistered) {
+ return;
+ }
+ mListenersRegistered = false;
try {
WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(mRotationWatcher);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
+
+ ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskStackListener);
}
void addRotationCallback(Consumer<Integer> watcher) {
mRotWatcherListener = watcher;
}
- void setAccessibilityFeedbackEnabled(boolean flag) {
- mAccessibilityFeedbackEnabled = flag;
- }
-
void setRotationLockedAtAngle(int rotationSuggestion) {
mRotationLockController.setRotationLockedAtAngle(true /* locked */, rotationSuggestion);
}
@@ -185,7 +191,7 @@
// Clear any pending suggestion flag as it has either been nullified or is being shown
mPendingRotationSuggestion = false;
- view.removeCallbacks(mCancelPendingRotationProposal);
+ mMainThreadHandler.removeCallbacks(mCancelPendingRotationProposal);
// Handle the visibility change and animation
if (visible) { // Appear and change (cannot force)
@@ -255,13 +261,9 @@
return;
}
- final View currentView = mRotationButton.getCurrentView();
-
// If window rotation matches suggested rotation, remove any current suggestions
if (rotation == windowRotation) {
- if (currentView != null) {
- currentView.removeCallbacks(mRemoveRotationProposal);
- }
+ mMainThreadHandler.removeCallbacks(mRemoveRotationProposal);
setRotateSuggestionButtonState(false /* visible */);
return;
}
@@ -285,11 +287,9 @@
// If the navbar isn't shown, flag the rotate icon to be shown should the navbar become
// visible given some time limit.
mPendingRotationSuggestion = true;
- if (currentView != null) {
- currentView.removeCallbacks(mCancelPendingRotationProposal);
- currentView.postDelayed(mCancelPendingRotationProposal,
- NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS);
- }
+ mMainThreadHandler.removeCallbacks(mCancelPendingRotationProposal);
+ mMainThreadHandler.postDelayed(mCancelPendingRotationProposal,
+ NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS);
}
}
@@ -334,9 +334,7 @@
private void onRotationSuggestionsDisabled() {
// Immediately hide the rotate button and clear any planned removal
setRotateSuggestionButtonState(false /* visible */, true /* force */);
- if (mRotationButton.getCurrentView() != null) {
- mRotationButton.getCurrentView().removeCallbacks(mRemoveRotationProposal);
- }
+ mMainThreadHandler.removeCallbacks(mRemoveRotationProposal);
}
private void showAndLogRotationSuggestion() {
@@ -369,10 +367,6 @@
}
private void rescheduleRotationTimeout(final boolean reasonHover) {
- if (mRotationButton.getCurrentView() == null) {
- return;
- }
-
// May be called due to a new rotation proposal or a change in hover state
if (reasonHover) {
// Don't reschedule if a hide animator is running
@@ -382,16 +376,16 @@
}
// Stop any pending removal
- mRotationButton.getCurrentView().removeCallbacks(mRemoveRotationProposal);
+ mMainThreadHandler.removeCallbacks(mRemoveRotationProposal);
// Schedule timeout
- mRotationButton.getCurrentView().postDelayed(mRemoveRotationProposal,
+ mMainThreadHandler.postDelayed(mRemoveRotationProposal,
computeRotationProposalTimeout());
}
private int computeRotationProposalTimeout() {
- if (mAccessibilityFeedbackEnabled) return 10000;
- if (mHoveringRotationSuggestion) return 8000;
- return 5000;
+ return mAccessibilityManagerWrapper.getRecommendedTimeoutMillis(
+ mHoveringRotationSuggestion ? 16000 : 5000,
+ AccessibilityManager.FLAG_CONTENT_CONTROLS);
}
private boolean isRotateSuggestionIntroduced() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
index 24e7336..bd96752 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
@@ -64,13 +64,6 @@
}
@Override
- public void onDestroy() {
- if (mRotationButtonController != null) {
- mRotationButtonController.cleanUp();
- }
- }
-
- @Override
public void onNavigationModeChanged(int mode) {
mNavBarMode = mode;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index e19fe07..c36f81d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -494,7 +494,7 @@
private Runnable mLaunchTransitionEndRunnable;
private NotificationEntry mDraggedDownEntry;
- private boolean mLaunchCameraOnScreenTurningOn;
+ private boolean mLaunchCameraWhenFinishedWaking;
private boolean mLaunchCameraOnFinishedGoingToSleep;
private int mLastCameraLaunchSource;
protected PowerManager.WakeLock mGestureWakeLock;
@@ -3597,7 +3597,7 @@
public void onFinishedGoingToSleep() {
mNotificationPanel.onAffordanceLaunchEnded();
releaseGestureWakeLock();
- mLaunchCameraOnScreenTurningOn = false;
+ mLaunchCameraWhenFinishedWaking = false;
mDeviceInteractive = false;
mWakeUpComingFromTouch = false;
mWakeUpTouchLocation = null;
@@ -3644,6 +3644,11 @@
@Override
public void onFinishedWakingUp() {
mWakeUpCoordinator.setWakingUp(false);
+ if (mLaunchCameraWhenFinishedWaking) {
+ mNotificationPanel.launchCamera(false /* animate */, mLastCameraLaunchSource);
+ mLaunchCameraWhenFinishedWaking = false;
+ }
+ updateScrimController();
}
};
@@ -3665,13 +3670,6 @@
public void onScreenTurningOn() {
mFalsingManager.onScreenTurningOn();
mNotificationPanel.onScreenTurningOn();
-
- if (mLaunchCameraOnScreenTurningOn) {
- mNotificationPanel.launchCamera(false, mLastCameraLaunchSource);
- mLaunchCameraOnScreenTurningOn = false;
- }
-
- updateScrimController();
}
@Override
@@ -3772,7 +3770,7 @@
// comes on.
mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
}
- if (isScreenTurningOnOrOn()) {
+ if (isWakingUpOrAwake()) {
if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Launching camera");
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mStatusBarKeyguardViewManager.reset(true /* hide */);
@@ -3785,7 +3783,7 @@
// incorrectly get notified because of the screen on event (which resumes and pauses
// some activities)
if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Deferring until screen turns on");
- mLaunchCameraOnScreenTurningOn = true;
+ mLaunchCameraWhenFinishedWaking = true;
}
}
}
@@ -3810,9 +3808,9 @@
== WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
}
- private boolean isScreenTurningOnOrOn() {
- return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_ON
- || mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_ON;
+ private boolean isWakingUpOrAwake() {
+ return mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE
+ || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING;
}
public void notifyBiometricAuthModeChanged() {
@@ -3844,7 +3842,7 @@
ScrimState state = mStatusBarKeyguardViewManager.bouncerNeedsScrimming()
? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
mScrimController.transitionTo(state);
- } else if (isInLaunchTransition() || mLaunchCameraOnScreenTurningOn
+ } else if (isInLaunchTransition() || mLaunchCameraWhenFinishedWaking
|| launchingAffordanceWithPreview) {
mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
} else if (mBrightnessMirrorVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowCallback.java
new file mode 100644
index 0000000..f33ff27
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowCallback.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+package com.android.systemui.statusbar.phone;
+
+public interface StatusBarWindowCallback {
+ void onStateChanged(boolean keyguardShowing, boolean keyguardOccluded, boolean bouncerShowing);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index a4f495a..4ddd0e99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -18,9 +18,6 @@
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
import android.app.ActivityManager;
@@ -47,17 +44,19 @@
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
-import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.statusbar.RemoteInputController.Callback;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.google.android.collect.Lists;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
+import java.util.ArrayList;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -75,6 +74,7 @@
private final DozeParameters mDozeParameters;
private final WindowManager.LayoutParams mLpChanged;
private final boolean mKeyguardScreenRotation;
+ private final long mLockScreenDisplayTimeout;
private ViewGroup mStatusBarView;
private WindowManager.LayoutParams mLp;
private boolean mHasTopUi;
@@ -84,6 +84,8 @@
private final State mCurrentState = new State();
private OtherwisedCollapsedListener mListener;
private ForcePluginOpenListener mForcePluginOpenListener;
+ private final ArrayList<WeakReference<StatusBarWindowCallback>>
+ mCallbacks = Lists.newArrayList();
private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
@@ -103,12 +105,27 @@
mDozeParameters = dozeParameters;
mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
mLpChanged = new WindowManager.LayoutParams();
+ mLockScreenDisplayTimeout = context.getResources()
+ .getInteger(R.integer.config_lockScreenDisplayTimeout);
((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
.addCallback(mStateListener,
SysuiStatusBarStateController.RANK_STATUS_BAR_WINDOW_CONTROLLER);
Dependency.get(ConfigurationController.class).addCallback(this);
}
+ /**
+ * Register to receive notifications about status bar window state changes.
+ */
+ public void registerCallback(StatusBarWindowCallback callback) {
+ // Prevent adding duplicate callbacks
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ if (mCallbacks.get(i).get() == callback) {
+ return;
+ }
+ }
+ mCallbacks.add(new WeakReference<StatusBarWindowCallback>(callback));
+ }
+
private boolean shouldEnableKeyguardScreenRotation() {
Resources res = mContext.getResources();
return SystemProperties.getBoolean("lockscreen.rot_override", false)
@@ -266,7 +283,8 @@
if (state.isKeyguardShowingAndNotOccluded()
&& state.statusBarState == StatusBarState.KEYGUARD
&& !state.qsExpanded) {
- mLpChanged.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
+ mLpChanged.userActivityTimeout = state.bouncerShowing
+ ? KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS : mLockScreenDisplayTimeout;
} else {
mLpChanged.userActivityTimeout = -1;
}
@@ -319,18 +337,18 @@
}
mHasTopUi = mHasTopUiChanged;
}
- updateSystemUiStateFlags();
+ notifyStateChangedCallbacks();
}
- public void updateSystemUiStateFlags() {
- int displayId = mContext.getDisplayId();
- OverviewProxyService overviewProxyService = Dependency.get(OverviewProxyService.class);
- overviewProxyService.setSystemUiStateFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING,
- mCurrentState.keyguardShowing && !mCurrentState.keyguardOccluded, displayId);
- overviewProxyService.setSystemUiStateFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED,
- mCurrentState.keyguardShowing && mCurrentState.keyguardOccluded, displayId);
- overviewProxyService.setSystemUiStateFlag(SYSUI_STATE_BOUNCER_SHOWING,
- mCurrentState.bouncerShowing, displayId);
+ public void notifyStateChangedCallbacks() {
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ StatusBarWindowCallback cb = mCallbacks.get(i).get();
+ if (cb != null) {
+ cb.onStateChanged(mCurrentState.keyguardShowing,
+ mCurrentState.keyguardOccluded,
+ mCurrentState.bouncerShowing);
+ }
+ }
}
private void applyForceStatusBarVisibleFlag(State state) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
index efd6e03..fa7af0b 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
@@ -16,6 +16,8 @@
package com.android.systemui.util.leak;
+import android.content.ClipData;
+import android.content.ClipDescription;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -47,10 +49,11 @@
private static final String FILEPROVIDER_PATH = "leak";
private static final String TAG = "DumpTruck";
- private static final int BUFSIZ = 512 * 1024; // 512K
+ private static final int BUFSIZ = 1024 * 1024; // 1MB
private final Context context;
private Uri hprofUri;
+ private long pss;
final StringBuilder body = new StringBuilder();
public DumpTruck(Context context) {
@@ -89,6 +92,7 @@
.append(info.currentPss)
.append(" uss=")
.append(info.currentUss);
+ pss = info.currentPss;
}
}
if (pid == myPid) {
@@ -114,6 +118,7 @@
if (DumpTruck.zipUp(zipfile, paths)) {
final File pathFile = new File(zipfile);
hprofUri = FileProvider.getUriForFile(context, FILEPROVIDER_AUTHORITY, pathFile);
+ Log.v(TAG, "Heap dump accessible at URI: " + hprofUri);
}
} catch (IOException e) {
Log.e(TAG, "unable to zip up heapdumps", e);
@@ -138,16 +143,27 @@
* @return share intent
*/
public Intent createShareIntent() {
- Intent shareIntent = new Intent(Intent.ACTION_SEND);
+ Intent shareIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- shareIntent.putExtra(Intent.EXTRA_SUBJECT, "SystemUI memory dump");
+ shareIntent.putExtra(Intent.EXTRA_SUBJECT,
+ String.format("SystemUI memory dump (pss=%dM)", pss / 1024));
shareIntent.putExtra(Intent.EXTRA_TEXT, body.toString());
if (hprofUri != null) {
+ final ArrayList<Uri> uriList = new ArrayList<>();
+ uriList.add(hprofUri);
shareIntent.setType("application/zip");
- shareIntent.putExtra(Intent.EXTRA_STREAM, hprofUri);
+ shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uriList);
+
+ // Include URI in ClipData also, so that grantPermission picks it up.
+ // We don't use setData here because some apps interpret this as "to:".
+ ClipData clipdata = new ClipData(new ClipDescription("content",
+ new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
+ new ClipData.Item(hprofUri));
+ shareIntent.setClipData(clipdata);
+ shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
return shareIntent;
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index aa3fd5f..583f6b3 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -16,9 +16,13 @@
package com.android.systemui.util.leak;
+import static android.service.quicksettings.Tile.STATE_ACTIVE;
+import static android.telephony.ims.feature.ImsFeature.STATE_UNAVAILABLE;
+
import static com.android.internal.logging.MetricsLogger.VIEW_UNKNOWN;
import static com.android.systemui.Dependency.BG_LOOPER_NAME;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
@@ -38,11 +42,11 @@
import android.os.Process;
import android.os.SystemProperties;
import android.provider.Settings;
-import android.service.quicksettings.Tile;
import android.text.format.DateUtils;
import android.util.Log;
import android.util.LongSparseArray;
+import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
@@ -50,6 +54,8 @@
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
import javax.inject.Inject;
@@ -59,7 +65,7 @@
/**
*/
@Singleton
-public class GarbageMonitor {
+public class GarbageMonitor implements Dumpable {
private static final boolean LEAK_REPORTING_ENABLED =
Build.IS_DEBUGGABLE
&& SystemProperties.getBoolean("debug.enable_leak_reporting", false);
@@ -77,12 +83,15 @@
private static final long GARBAGE_INSPECTION_INTERVAL =
15 * DateUtils.MINUTE_IN_MILLIS; // 15 min
private static final long HEAP_TRACK_INTERVAL = 1 * DateUtils.MINUTE_IN_MILLIS; // 1 min
+ private static final int HEAP_TRACK_HISTORY_LEN = 720; // 12 hours
private static final int DO_GARBAGE_INSPECTION = 1000;
private static final int DO_HEAP_TRACK = 3000;
private static final int GARBAGE_ALLOWANCE = 5;
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
private final Handler mHandler;
private final TrackedGarbage mTrackedGarbage;
private final LeakReporter mLeakReporter;
@@ -180,7 +189,7 @@
sb.append(p);
sb.append(" ");
}
- Log.v(TAG, sb.toString());
+ if (DEBUG) Log.v(TAG, sb.toString());
}
private void update() {
@@ -189,18 +198,18 @@
for (int i = 0; i < dinfos.length; i++) {
Debug.MemoryInfo dinfo = dinfos[i];
if (i > mPids.size()) {
- Log.e(TAG, "update: unknown process info received: " + dinfo);
+ if (DEBUG) Log.e(TAG, "update: unknown process info received: " + dinfo);
break;
}
final long pid = mPids.get(i).intValue();
final ProcessMemInfo info = mData.get(pid);
- info.head = (info.head + 1) % info.pss.length;
info.pss[info.head] = info.currentPss = dinfo.getTotalPss();
info.uss[info.head] = info.currentUss = dinfo.getTotalPrivateDirty();
+ info.head = (info.head + 1) % info.pss.length;
if (info.currentPss > info.max) info.max = info.currentPss;
if (info.currentUss > info.max) info.max = info.currentUss;
if (info.currentPss == 0) {
- Log.v(TAG, "update: pid " + pid + " has pss=0, it probably died");
+ if (DEBUG) Log.v(TAG, "update: pid " + pid + " has pss=0, it probably died");
mData.remove(pid);
}
}
@@ -230,11 +239,36 @@
return b + SUFFIXES[i];
}
- private void dumpHprofAndShare() {
- final Intent share = mDumpTruck.captureHeaps(getTrackedProcesses()).createShareIntent();
- mContext.startActivity(share);
+ private Intent dumpHprofAndGetShareIntent() {
+ return mDumpTruck.captureHeaps(getTrackedProcesses()).createShareIntent();
}
+ @Override
+ public void dump(@Nullable FileDescriptor fd, PrintWriter pw, @Nullable String[] args) {
+ pw.println("GarbageMonitor params:");
+ pw.println(String.format(" mHeapLimit=%d KB", mHeapLimit));
+ pw.println(String.format(" GARBAGE_INSPECTION_INTERVAL=%d (%.1f mins)",
+ GARBAGE_INSPECTION_INTERVAL,
+ (float) GARBAGE_INSPECTION_INTERVAL / DateUtils.MINUTE_IN_MILLIS));
+ final float htiMins = HEAP_TRACK_INTERVAL / DateUtils.MINUTE_IN_MILLIS;
+ pw.println(String.format(" HEAP_TRACK_INTERVAL=%d (%.1f mins)",
+ HEAP_TRACK_INTERVAL,
+ htiMins));
+ pw.println(String.format(" HEAP_TRACK_HISTORY_LEN=%d (%.1f hr total)",
+ HEAP_TRACK_HISTORY_LEN,
+ (float) HEAP_TRACK_HISTORY_LEN * htiMins / 60f));
+
+ pw.println("GarbageMonitor tracked processes:");
+
+ for (long pid : mPids) {
+ final ProcessMemInfo pmi = mData.get(pid);
+ if (pmi != null) {
+ pmi.dump(fd, pw, args);
+ }
+ }
+ }
+
+
private static class MemoryIconDrawable extends Drawable {
long pss, limit;
final Drawable baseIcon;
@@ -244,7 +278,7 @@
MemoryIconDrawable(Context context) {
baseIcon = context.getDrawable(R.drawable.ic_memory).mutate();
dp = context.getResources().getDisplayMetrics().density;
- paint.setColor(QSTileImpl.getColorForState(context, Tile.STATE_ACTIVE));
+ paint.setColor(QSTileImpl.getColorForState(context, STATE_ACTIVE));
}
public void setPss(long pss) {
@@ -354,6 +388,7 @@
private final GarbageMonitor gm;
private ProcessMemInfo pmi;
+ private boolean dumpInProgress;
@Inject
public MemoryTile(QSHost host) {
@@ -373,8 +408,26 @@
@Override
protected void handleClick() {
- getHost().collapsePanels();
- mHandler.post(gm::dumpHprofAndShare);
+ if (dumpInProgress) return;
+
+ dumpInProgress = true;
+ refreshState();
+ new Thread("HeapDumpThread") {
+ @Override
+ public void run() {
+ try {
+ // wait for animations & state changes
+ Thread.sleep(500);
+ } catch (InterruptedException ignored) { }
+ final Intent shareIntent = gm.dumpHprofAndGetShareIntent();
+ mHandler.post(() -> {
+ dumpInProgress = false;
+ refreshState();
+ getHost().collapsePanels();
+ mContext.startActivity(shareIntent);
+ });
+ }
+ }.start();
}
@Override
@@ -404,9 +457,12 @@
pmi = gm.getMemInfo(Process.myPid());
final MemoryGraphIcon icon = new MemoryGraphIcon();
icon.setHeapLimit(gm.mHeapLimit);
+ state.state = dumpInProgress ? STATE_UNAVAILABLE : STATE_ACTIVE;
+ state.label = dumpInProgress
+ ? "Dumping..."
+ : mContext.getString(R.string.heap_dump_tile_name);
if (pmi != null) {
icon.setPss(pmi.currentPss);
- state.label = mContext.getString(R.string.heap_dump_tile_name);
state.secondaryLabel =
String.format(
"pss: %s / %s",
@@ -414,7 +470,6 @@
formatBytes(gm.mHeapLimit * 1024));
} else {
icon.setPss(0);
- state.label = "Dump SysUI";
state.secondaryLabel = null;
}
state.icon = icon;
@@ -433,13 +488,14 @@
}
}
- public static class ProcessMemInfo {
+ /** */
+ public static class ProcessMemInfo implements Dumpable {
public long pid;
public String name;
public long startTime;
public long currentPss, currentUss;
- public long[] pss = new long[256];
- public long[] uss = new long[256];
+ public long[] pss = new long[HEAP_TRACK_HISTORY_LEN];
+ public long[] uss = new long[HEAP_TRACK_HISTORY_LEN];
public long max = 1;
public int head = 0;
@@ -452,9 +508,33 @@
public long getUptime() {
return System.currentTimeMillis() - startTime;
}
+
+ @Override
+ public void dump(@Nullable FileDescriptor fd, PrintWriter pw, @Nullable String[] args) {
+ pw.print("{ \"pid\": ");
+ pw.print(pid);
+ pw.print(", \"name\": \"");
+ pw.print(name.replace('"', '-'));
+ pw.print("\", \"start\": ");
+ pw.print(startTime);
+ pw.print(", \"pss\": [");
+ // write pss values starting from the oldest, which is pss[head], wrapping around to
+ // pss[(head-1) % pss.length]
+ for (int i = 0; i < pss.length; i++) {
+ if (i > 0) pw.print(",");
+ pw.print(pss[(head + i) % pss.length]);
+ }
+ pw.print("], \"uss\": [");
+ for (int i = 0; i < uss.length; i++) {
+ if (i > 0) pw.print(",");
+ pw.print(uss[(head + i) % uss.length]);
+ }
+ pw.println("] }");
+ }
}
- public static class Service extends SystemUI {
+ /** */
+ public static class Service extends SystemUI implements Dumpable {
private GarbageMonitor mGarbageMonitor;
@Override
@@ -472,6 +552,11 @@
mGarbageMonitor.startHeapTracking();
}
}
+
+ @Override
+ public void dump(@Nullable FileDescriptor fd, PrintWriter pw, @Nullable String[] args) {
+ if (mGarbageMonitor != null) mGarbageMonitor.dump(fd, pw, args);
+ }
}
private class BackgroundHeapCheckHandler extends Handler {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
index b99958a..73abda9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
@@ -31,6 +31,7 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.AttributeSet;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -41,6 +42,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import org.junit.Before;
import org.junit.Rule;
@@ -60,6 +62,7 @@
@Mock private NotificationStackScrollLayout mNssl;
@Mock private ActivityStarterDelegate mActivityStarterDelegate;
@Mock private StatusBarStateController mStatusBarStateController;
+ @Mock private ConfigurationController mConfigurationController;
private NotificationSectionsManager mSectionsManager;
@@ -70,15 +73,21 @@
mNssl,
mActivityStarterDelegate,
mStatusBarStateController,
+ mConfigurationController,
true);
// Required in order for the header inflation to work properly
when(mNssl.generateLayoutParams(any(AttributeSet.class)))
.thenReturn(new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
- mSectionsManager.inflateViews(mContext);
+ mSectionsManager.initialize(LayoutInflater.from(mContext));
when(mNssl.indexOfChild(any(View.class))).thenReturn(-1);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
}
+ @Test(expected = IllegalStateException.class)
+ public void testDuplicateInitializeThrows() {
+ mSectionsManager.initialize(LayoutInflater.from(mContext));
+ }
+
@Test
public void testInsertHeader() {
// GIVEN a stack with HI and LO rows but no section headers
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index f337b69..95cf90b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -75,6 +75,7 @@
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarTest.TestableNotificationEntryManager;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import org.junit.After;
import org.junit.Assert;
@@ -155,6 +156,7 @@
mStackScrollerInternal = new NotificationStackScrollLayout(getContext(), null,
true /* allowLongPress */, mNotificationRoundnessManager,
mock(DynamicPrivacyController.class),
+ mock(ConfigurationController.class),
mock(ActivityStarterDelegate.class),
mock(StatusBarStateController.class),
mHeadsUpManager,
diff --git a/proto/Android.bp b/proto/Android.bp
index 7b119a7..65bccbb 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -5,7 +5,6 @@
type: "nano",
},
srcs: ["src/**/*.proto"],
- no_framework_libs: true,
sdk_version: "9",
// Pin java_version until jarjar is certified to support later versions. http://b/72703434
java_version: "1.8",
@@ -26,6 +25,5 @@
type: "nano",
},
srcs: ["src/metrics_constants/metrics_constants.proto"],
- no_framework_libs: true,
sdk_version: "system_current",
}
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 0f0e6f9..c58e929 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -7388,6 +7388,20 @@
// CATEGORY: NOTIFICATION
MEDIA_NOTIFICATION_SEEKBAR = 1743;
+ // Custom tag for StatusBarNotification. Length of
+ // Notification.extras[EXTRA_PEOPLE_LIST], set by addPerson().
+ FIELD_NOTIFICATION_PEOPLE = 1744;
+
+ // Custom tag for StatusBarNotification. The Java hashcode of
+ // Notification.extras[EXTRA_TEMPLATE], which is a string like
+ // android.app.Notification$MessagingStyle, set by setStyle().
+ FIELD_NOTIFICATION_STYLE = 1745;
+
+ // OPEN: Settings > About phone > Legal information > Google Play system update licenses
+ // CATEGORY: SETTINGS
+ // OS: Q
+ MODULE_LICENSES_DASHBOARD = 1746;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/backup/java/com/android/server/backup/BackupAgentTimeoutParameters.java b/services/backup/java/com/android/server/backup/BackupAgentTimeoutParameters.java
index ae850ac..0e99b34 100644
--- a/services/backup/java/com/android/server/backup/BackupAgentTimeoutParameters.java
+++ b/services/backup/java/com/android/server/backup/BackupAgentTimeoutParameters.java
@@ -33,8 +33,6 @@
* are represented as a comma-delimited key value list.
*/
public class BackupAgentTimeoutParameters extends KeyValueSettingObserver {
- private static final String TAG = "BackupAgentTimeout";
-
@VisibleForTesting
public static final String SETTING = Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS;
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 302e3ff..8df25b5 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -39,7 +39,6 @@
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.FileUtils;
-import android.os.HandlerThread;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.Trace;
@@ -87,7 +86,6 @@
private final Context mContext;
private final Trampoline mTrampoline;
- private final HandlerThread mBackupThread;
// Keeps track of all unlocked users registered with this service. Indexed by user id.
private final SparseArray<UserBackupManagerService> mServiceUsers = new SparseArray<>();
@@ -107,11 +105,9 @@
};
/** Instantiate a new instance of {@link BackupManagerService}. */
- public BackupManagerService(
- Context context, Trampoline trampoline, HandlerThread backupThread) {
+ public BackupManagerService(Context context, Trampoline trampoline) {
mContext = checkNotNull(context);
mTrampoline = checkNotNull(trampoline);
- mBackupThread = checkNotNull(backupThread);
// Set up our transport options.
SystemConfig systemConfig = SystemConfig.getInstance();
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index a9b292b3..53bbac4 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -110,15 +110,15 @@
private final Object mStateLock = new Object();
private volatile BackupManagerService mService;
- private HandlerThread mHandlerThread;
- private Handler mHandler;
+ private final Handler mHandler;
public Trampoline(Context context) {
mContext = context;
mGlobalDisable = isBackupDisabled();
- mHandlerThread = new HandlerThread(BACKUP_THREAD, Process.THREAD_PRIORITY_BACKGROUND);
- mHandlerThread.start();
- mHandler = new Handler(mHandlerThread.getLooper());
+ HandlerThread handlerThread =
+ new HandlerThread(BACKUP_THREAD, Process.THREAD_PRIORITY_BACKGROUND);
+ handlerThread.start();
+ mHandler = new Handler(handlerThread.getLooper());
mUserManager = UserManager.get(context);
}
@@ -232,7 +232,7 @@
}
protected BackupManagerService createBackupManagerService() {
- return new BackupManagerService(mContext, this, mHandlerThread);
+ return new BackupManagerService(mContext, this);
}
protected void postToHandler(Runnable runnable) {
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index c0af99c..ed4e5961 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -367,6 +367,9 @@
private long mCurrentToken = 0;
@Nullable private File mAncestralSerialNumberFile;
+ private final ContentObserver mSetupObserver;
+ private final BroadcastReceiver mRunBackupReceiver;
+ private final BroadcastReceiver mRunInitReceiver;
/**
* Creates an instance of {@link UserBackupManagerService} and initializes state for it. This
@@ -493,11 +496,11 @@
mAutoRestore = Settings.Secure.getIntForUser(resolver,
Settings.Secure.BACKUP_AUTO_RESTORE, 1, userId) != 0;
- ContentObserver setupObserver = new SetupObserver(this, mBackupHandler);
+ mSetupObserver = new SetupObserver(this, mBackupHandler);
resolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE),
/* notifyForDescendents */ false,
- setupObserver,
+ mSetupObserver,
mUserId);
mBaseStateDir = checkNotNull(baseStateDir, "baseStateDir cannot be null");
@@ -516,21 +519,21 @@
mBackupPasswordManager = new BackupPasswordManager(mContext, mBaseStateDir, mRng);
// Receivers for scheduled backups and transport initialization operations.
- BroadcastReceiver runBackupReceiver = new RunBackupReceiver(this);
+ mRunBackupReceiver = new RunBackupReceiver(this);
IntentFilter filter = new IntentFilter();
filter.addAction(RUN_BACKUP_ACTION);
context.registerReceiverAsUser(
- runBackupReceiver,
+ mRunBackupReceiver,
UserHandle.of(userId),
filter,
android.Manifest.permission.BACKUP,
/* scheduler */ null);
- BroadcastReceiver runInitReceiver = new RunInitializeReceiver(this);
+ mRunInitReceiver = new RunInitializeReceiver(this);
filter = new IntentFilter();
filter.addAction(RUN_INITIALIZE_ACTION);
context.registerReceiverAsUser(
- runInitReceiver,
+ mRunInitReceiver,
UserHandle.of(userId),
filter,
android.Manifest.permission.BACKUP,
@@ -599,6 +602,12 @@
/** Cleans up state when the user of this service is stopped. */
void tearDownService() {
+ mAgentTimeoutParameters.stop();
+ mConstants.stop();
+ mContext.getContentResolver().unregisterContentObserver(mSetupObserver);
+ mContext.unregisterReceiver(mRunBackupReceiver);
+ mContext.unregisterReceiver(mRunInitReceiver);
+ mContext.unregisterReceiver(mPackageTrackingReceiver);
mUserBackupThread.quit();
}
@@ -747,7 +756,7 @@
@VisibleForTesting
BroadcastReceiver getPackageTrackingReceiver() {
- return mBroadcastReceiver;
+ return mPackageTrackingReceiver;
}
@Nullable
@@ -788,10 +797,6 @@
mPendingInits.clear();
}
- public PerformFullTransportBackupTask getRunningFullBackupTask() {
- return mRunningFullBackupTask;
- }
-
public void setRunningFullBackupTask(
PerformFullTransportBackupTask runningFullBackupTask) {
mRunningFullBackupTask = runningFullBackupTask;
@@ -874,7 +879,7 @@
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme("package");
mContext.registerReceiverAsUser(
- mBroadcastReceiver,
+ mPackageTrackingReceiver,
UserHandle.of(mUserId),
filter,
/* broadcastPermission */ null,
@@ -885,7 +890,7 @@
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
mContext.registerReceiverAsUser(
- mBroadcastReceiver,
+ mPackageTrackingReceiver,
UserHandle.of(mUserId),
sdFilter,
/* broadcastPermission */ null,
@@ -1158,7 +1163,7 @@
* A {@link BroadcastReceiver} tracking changes to packages and sd cards in order to update our
* internal bookkeeping.
*/
- private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ private BroadcastReceiver mPackageTrackingReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
if (MORE_DEBUG) {
Slog.d(TAG, "Received broadcast " + intent);
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java
index 593478c..06d9395 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsPerUserService.java
@@ -95,7 +95,7 @@
@GuardedBy("mLock")
void provideContextImageLocked(int taskId, @NonNull Bundle imageContextRequestExtras) {
- RemoteContentSuggestionsService service = getRemoteServiceLocked();
+ RemoteContentSuggestionsService service = ensureRemoteServiceLocked();
if (service != null) {
ActivityManager.TaskSnapshot snapshot =
mActivityTaskManagerInternal.getTaskSnapshotNoRestore(taskId, false);
@@ -118,7 +118,7 @@
void suggestContentSelectionsLocked(
@NonNull SelectionsRequest selectionsRequest,
@NonNull ISelectionsCallback selectionsCallback) {
- RemoteContentSuggestionsService service = getRemoteServiceLocked();
+ RemoteContentSuggestionsService service = ensureRemoteServiceLocked();
if (service != null) {
service.suggestContentSelections(selectionsRequest, selectionsCallback);
}
@@ -128,7 +128,7 @@
void classifyContentSelectionsLocked(
@NonNull ClassificationsRequest classificationsRequest,
@NonNull IClassificationsCallback callback) {
- RemoteContentSuggestionsService service = getRemoteServiceLocked();
+ RemoteContentSuggestionsService service = ensureRemoteServiceLocked();
if (service != null) {
service.classifyContentSelections(classificationsRequest, callback);
}
@@ -136,7 +136,7 @@
@GuardedBy("mLock")
void notifyInteractionLocked(@NonNull String requestId, @NonNull Bundle bundle) {
- RemoteContentSuggestionsService service = getRemoteServiceLocked();
+ RemoteContentSuggestionsService service = ensureRemoteServiceLocked();
if (service != null) {
service.notifyInteraction(requestId, bundle);
}
@@ -153,12 +153,12 @@
@GuardedBy("mLock")
@Nullable
- private RemoteContentSuggestionsService getRemoteServiceLocked() {
+ private RemoteContentSuggestionsService ensureRemoteServiceLocked() {
if (mRemoteService == null) {
final String serviceName = getComponentNameLocked();
if (serviceName == null) {
if (mMaster.verbose) {
- Slog.v(TAG, "getRemoteServiceLocked(): not set");
+ Slog.v(TAG, "ensureRemoteServiceLocked(): not set");
}
return null;
}
@@ -170,8 +170,8 @@
@Override
public void onServiceDied(
@NonNull RemoteContentSuggestionsService service) {
- // TODO(b/120865921): properly implement
Slog.w(TAG, "remote content suggestions service died");
+ updateRemoteServiceLocked();
}
}, mMaster.isBindInstantServiceAllowed(), mMaster.verbose);
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index e2a874e..d162441 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -3019,46 +3019,10 @@
DateFormat.format(pattern, info.getTriggerTime()).toString();
}
- /**
- * If the last time AlarmThread woke up precedes any due wakeup or non-wakeup alarm that we set
- * by more than half a minute, log a wtf.
- */
- private void validateLastAlarmExpiredLocked(long nowElapsed) {
- final StringBuilder errorMsg = new StringBuilder();
- boolean stuck = false;
- if (mNextNonWakeup < (nowElapsed - 10_000) && mLastWakeup < mNextNonWakeup) {
- stuck = true;
- errorMsg.append("[mNextNonWakeup=");
- TimeUtils.formatDuration(mNextNonWakeup - nowElapsed, errorMsg);
- errorMsg.append(" set at ");
- TimeUtils.formatDuration(mNextNonWakeUpSetAt - nowElapsed, errorMsg);
- errorMsg.append(", mLastWakeup=");
- TimeUtils.formatDuration(mLastWakeup - nowElapsed, errorMsg);
- errorMsg.append(", timerfd_gettime=" + mInjector.getNextAlarm(ELAPSED_REALTIME));
- errorMsg.append("];");
- }
- if (mNextWakeup < (nowElapsed - 10_000) && mLastWakeup < mNextWakeup) {
- stuck = true;
- errorMsg.append("[mNextWakeup=");
- TimeUtils.formatDuration(mNextWakeup - nowElapsed, errorMsg);
- errorMsg.append(" set at ");
- TimeUtils.formatDuration(mNextWakeUpSetAt - nowElapsed, errorMsg);
- errorMsg.append(", mLastWakeup=");
- TimeUtils.formatDuration(mLastWakeup - nowElapsed, errorMsg);
- errorMsg.append(", timerfd_gettime="
- + mInjector.getNextAlarm(ELAPSED_REALTIME_WAKEUP));
- errorMsg.append("];");
- }
- if (stuck) {
- Slog.wtf(TAG, "Alarm delivery stuck: " + errorMsg.toString());
- }
- }
-
void rescheduleKernelAlarmsLocked() {
// Schedule the next upcoming wakeup alarm. If there is a deliverable batch
// prior to that which contains no wakeups, we schedule that as well.
final long nowElapsed = mInjector.getElapsedRealtime();
- validateLastAlarmExpiredLocked(nowElapsed);
long nextNonWakeup = 0;
if (mAlarmBatches.size() > 0) {
final Batch firstWakeup = findFirstWakeupBatchLocked();
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 4091a9a..61fe1a8 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -20,6 +20,7 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.NETID_UNSET;
+import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_NONE;
import static android.net.ConnectivityManager.TYPE_VPN;
@@ -192,6 +193,7 @@
import com.android.server.net.BaseNetworkObserver;
import com.android.server.net.LockdownVpnTracker;
import com.android.server.net.NetworkPolicyManagerInternal;
+import com.android.server.net.NetworkStatsFactory;
import com.android.server.utils.PriorityDump;
import com.google.android.collect.Lists;
@@ -4381,7 +4383,7 @@
/**
* @return VPN information for accounting, or null if we can't retrieve all required
- * information, e.g primary underlying iface.
+ * information, e.g underlying ifaces.
*/
@Nullable
private VpnInfo createVpnInfo(Vpn vpn) {
@@ -4393,17 +4395,28 @@
// see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret
// the underlyingNetworks list.
if (underlyingNetworks == null) {
- NetworkAgentInfo defaultNetwork = getDefaultNetwork();
- if (defaultNetwork != null && defaultNetwork.linkProperties != null) {
- info.primaryUnderlyingIface = getDefaultNetwork().linkProperties.getInterfaceName();
- }
- } else if (underlyingNetworks.length > 0) {
- LinkProperties linkProperties = getLinkProperties(underlyingNetworks[0]);
- if (linkProperties != null) {
- info.primaryUnderlyingIface = linkProperties.getInterfaceName();
+ NetworkAgentInfo defaultNai = getDefaultNetwork();
+ if (defaultNai != null) {
+ underlyingNetworks = new Network[] { defaultNai.network };
}
}
- return info.primaryUnderlyingIface == null ? null : info;
+ if (underlyingNetworks != null && underlyingNetworks.length > 0) {
+ List<String> interfaces = new ArrayList<>();
+ for (Network network : underlyingNetworks) {
+ LinkProperties lp = getLinkProperties(network);
+ if (lp != null) {
+ for (String iface : lp.getAllInterfaceNames()) {
+ if (!TextUtils.isEmpty(iface)) {
+ interfaces.add(iface);
+ }
+ }
+ }
+ }
+ if (!interfaces.isEmpty()) {
+ info.underlyingIfaces = interfaces.toArray(new String[interfaces.size()]);
+ }
+ }
+ return info.underlyingIfaces == null ? null : info;
}
/**
@@ -6783,8 +6796,8 @@
}
/**
- * Notify NetworkStatsService that the set of active ifaces has changed, or that one of the
- * properties tracked by NetworkStatsService on an active iface has changed.
+ * Notify NetworkStatsService and NetworkStatsFactory that the set of active ifaces has changed,
+ * or that one of the active iface's trackedproperties has changed.
*/
private void notifyIfacesChangedForNetworkStats() {
ensureRunningOnConnectivityServiceThread();
@@ -6793,11 +6806,17 @@
if (activeLinkProperties != null) {
activeIface = activeLinkProperties.getInterfaceName();
}
+
+ // CAUTION: Ordering matters between updateVpnInfos() and forceUpdateIfaces(), which
+ // triggers a new poll. Trigger the poll first to ensure a snapshot is taken before
+ // switching to the new state. This ensures that traffic does not get mis-attributed to
+ // incorrect apps (including VPN app).
try {
mStatsService.forceUpdateIfaces(
- getDefaultNetworks(), getAllVpnInfo(), getAllNetworkState(), activeIface);
+ getDefaultNetworks(), getAllNetworkState(), activeIface);
} catch (Exception ignored) {
}
+ NetworkStatsFactory.updateVpnInfos(getAllVpnInfo());
}
@Override
@@ -6952,6 +6971,12 @@
}
}
+ // restore private DNS settings to default mode (opportunistic)
+ if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_PRIVATE_DNS)) {
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_OPPORTUNISTIC);
+ }
+
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 8d76634..e5fb506 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -36,7 +36,6 @@
import static android.net.NetworkStats.STATS_PER_UID;
import static android.net.NetworkStats.TAG_ALL;
import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStats.UID_ALL;
import static android.net.TrafficStats.UID_TETHERING;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
@@ -1236,7 +1235,7 @@
public NetworkStats getNetworkStatsDetail() {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
- return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null);
+ return mStatsFactory.readNetworkStatsDetail();
} catch (IOException e) {
throw new IllegalStateException(e);
}
@@ -1545,7 +1544,7 @@
public NetworkStats getNetworkStatsUidDetail(int uid, String[] ifaces) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
- return mStatsFactory.readNetworkStatsDetail(uid, ifaces, TAG_ALL, null);
+ return mStatsFactory.readNetworkStatsDetail(uid, ifaces, TAG_ALL);
} catch (IOException e) {
throw new IllegalStateException(e);
}
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index c5b4966..9711152e 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -17,12 +17,15 @@
package com.android.server;
import android.annotation.NonNull;
+import android.annotation.UserIdInt;
import android.content.Context;
import android.os.Environment;
import android.os.SystemClock;
import android.os.Trace;
import android.util.Slog;
+import com.android.server.utils.TimingsTraceAndSlog;
+
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@@ -138,9 +141,10 @@
* Starts the specified boot phase for all system services that have been started up to
* this point.
*
+ * @param t trace logger
* @param phase The boot phase to start.
*/
- public void startBootPhase(final int phase) {
+ public void startBootPhase(@NonNull TimingsTraceAndSlog t, int phase) {
if (phase <= mCurrentPhase) {
throw new IllegalArgumentException("Next phase must be larger than previous");
}
@@ -148,12 +152,12 @@
Slog.i(TAG, "Starting phase " + mCurrentPhase);
try {
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "OnBootPhase " + phase);
+ t.traceBegin("OnBootPhase " + phase);
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
long time = SystemClock.elapsedRealtime();
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, service.getClass().getName());
+ t.traceBegin(service.getClass().getName());
try {
service.onBootPhase(mCurrentPhase);
} catch (Exception ex) {
@@ -163,10 +167,15 @@
+ mCurrentPhase, ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onBootPhase");
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ t.traceEnd();
}
} finally {
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ t.traceEnd();
+ }
+
+ if (phase == SystemService.PHASE_BOOT_COMPLETED) {
+ final long totalBootTime = SystemClock.uptimeMillis() - mRuntimeStartUptime;
+ t.logDuration("TotalBootTime", totalBootTime);
}
}
@@ -177,13 +186,17 @@
return mCurrentPhase >= SystemService.PHASE_BOOT_COMPLETED;
}
- public void startUser(final int userHandle) {
+ /**
+ * Starts the given user.
+ */
+ public void startUser(@NonNull TimingsTraceAndSlog t, final @UserIdInt int userHandle) {
+ t.traceBegin("ssm.startUser-" + userHandle);
Slog.i(TAG, "Calling onStartUser u" + userHandle);
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onStartUser "
- + service.getClass().getName());
+ final String serviceName = service.getClass().getName();
+ t.traceBegin("onStartUser-" + userHandle + " " + serviceName);
long time = SystemClock.elapsedRealtime();
try {
service.onStartUser(userHandle);
@@ -192,84 +205,109 @@
+ " to service " + service.getClass().getName(), ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStartUser ");
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ t.traceEnd();
}
+ t.traceEnd();
}
- public void unlockUser(final int userHandle) {
+ /**
+ * Unlocks the given user.
+ */
+ public void unlockUser(final @UserIdInt int userHandle) {
+ final TimingsTraceAndSlog t = TimingsTraceAndSlog.newAsyncLog();
+ t.traceBegin("ssm.unlockUser-" + userHandle);
Slog.i(TAG, "Calling onUnlockUser u" + userHandle);
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onUnlockUser "
- + service.getClass().getName());
+ final String serviceName = service.getClass().getName();
+ t.traceBegin("onUnlockUser-" + userHandle + " " + serviceName);
long time = SystemClock.elapsedRealtime();
try {
service.onUnlockUser(userHandle);
} catch (Exception ex) {
Slog.wtf(TAG, "Failure reporting unlock of user " + userHandle
- + " to service " + service.getClass().getName(), ex);
+ + " to service " + serviceName, ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onUnlockUser ");
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ t.traceEnd();
}
+ t.traceEnd();
}
- public void switchUser(final int userHandle) {
+ /**
+ * Switches to the given user.
+ */
+ public void switchUser(final @UserIdInt int userHandle) {
+ final TimingsTraceAndSlog t = TimingsTraceAndSlog.newAsyncLog();
+ t.traceBegin("ssm.switchUser-" + userHandle);
Slog.i(TAG, "Calling switchUser u" + userHandle);
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onSwitchUser "
- + service.getClass().getName());
+ final String serviceName = service.getClass().getName();
+ t.traceBegin("onSwitchUser-" + userHandle + " " + serviceName);
long time = SystemClock.elapsedRealtime();
try {
service.onSwitchUser(userHandle);
} catch (Exception ex) {
Slog.wtf(TAG, "Failure reporting switch of user " + userHandle
- + " to service " + service.getClass().getName(), ex);
+ + " to service " + serviceName, ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onSwitchUser");
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ t.traceEnd();
}
+ t.traceEnd();
}
- public void stopUser(final int userHandle) {
+ /**
+ * Stops the given user.
+ */
+ public void stopUser(final @UserIdInt int userHandle) {
+ final TimingsTraceAndSlog t = TimingsTraceAndSlog.newAsyncLog();
+ t.traceBegin("ssm.stopUser-" + userHandle);
Slog.i(TAG, "Calling onStopUser u" + userHandle);
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onStopUser "
- + service.getClass().getName());
+ final String serviceName = service.getClass().getName();
+ t.traceBegin("onStopUser-" + userHandle + " " + serviceName);
long time = SystemClock.elapsedRealtime();
try {
service.onStopUser(userHandle);
} catch (Exception ex) {
Slog.wtf(TAG, "Failure reporting stop of user " + userHandle
- + " to service " + service.getClass().getName(), ex);
+ + " to service " + serviceName, ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStopUser");
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ t.traceEnd();
}
+ t.traceEnd();
}
- public void cleanupUser(final int userHandle) {
+ /**
+ * Cleans up the given user.
+ */
+ public void cleanupUser(final @UserIdInt int userHandle) {
+ final TimingsTraceAndSlog t = TimingsTraceAndSlog.newAsyncLog();
+ t.traceBegin("ssm.cleanupUser-" + userHandle);
Slog.i(TAG, "Calling onCleanupUser u" + userHandle);
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
- Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onCleanupUser "
- + service.getClass().getName());
+ final String serviceName = service.getClass().getName();
+ t.traceBegin("onCleanupUser-" + userHandle + " " + serviceName);
long time = SystemClock.elapsedRealtime();
try {
service.onCleanupUser(userHandle);
} catch (Exception ex) {
Slog.wtf(TAG, "Failure reporting cleanup of user " + userHandle
- + " to service " + service.getClass().getName(), ex);
+ + " to service " + serviceName, ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onCleanupUser");
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ t.traceEnd();
}
+ t.traceEnd();
}
/** Sets the safe mode flag for services to query. */
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 0eb3a84..59589cd2 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -46,7 +46,9 @@
import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.ShellCommand;
+import android.os.SystemProperties;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings.Secure;
import android.service.dreams.Sandman;
import android.service.vr.IVrManager;
@@ -64,6 +66,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.Objects;
final class UiModeManagerService extends SystemService {
private static final String TAG = UiModeManager.class.getSimpleName();
@@ -71,6 +74,7 @@
// Enable launching of applications when entering the dock.
private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true;
+ private static final String SYSTEM_PROPERTY_DEVICE_THEME = "persist.sys.theme";
final Object mLock = new Object();
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
@@ -330,8 +334,13 @@
mNightMode = defaultNightMode;
}
- // false if night mode stayed the same, true otherwise.
- return !(oldNightMode == mNightMode);
+ if (UserManager.get(context).isPrimaryUser()) {
+ final String newTheme = Integer.toString(mNightMode);
+ if (!Objects.equals(SystemProperties.get(SYSTEM_PROPERTY_DEVICE_THEME), mNightMode)) {
+ SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME, newTheme);
+ }
+ }
+ return oldNightMode != mNightMode;
}
private final IUiModeManager.Stub mService = new IUiModeManager.Stub() {
@@ -411,6 +420,11 @@
try {
synchronized (mLock) {
if (mNightMode != mode) {
+ if (UserManager.get(getContext()).isPrimaryUser()) {
+ SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME,
+ Integer.toString(mode));
+ }
+
// Only persist setting if not in car mode
if (!mCarModeEnabled) {
Secure.putIntForUser(getContext().getContentResolver(),
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 4e416a2..cb22151 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -111,6 +111,7 @@
"android.hardware.media.c2@1.0::IComponentStore",
"android.hardware.media.omx@1.0::IOmx",
"android.hardware.media.omx@1.0::IOmxStore",
+ "android.hardware.power.stats@1.0::IPowerStats",
"android.hardware.sensors@1.0::ISensors",
"android.hardware.vr@1.0::IVr",
"android.hardware.biometrics.face@1.0::IBiometricsFace"
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index aa2a086..1c53b9e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5094,7 +5094,8 @@
}
final void finishBooting() {
- TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG, Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
+ Trace.TRACE_TAG_ACTIVITY_MANAGER);
t.traceBegin("FinishBooting");
synchronized (this) {
@@ -5168,7 +5169,7 @@
}
// Let system services know.
- mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+ mSystemServiceManager.startBootPhase(t, SystemService.PHASE_BOOT_COMPLETED);
synchronized (this) {
// Ensure that any processes we had put on hold are now started
@@ -8866,9 +8867,11 @@
if (goingCallback != null) {
goingCallback.run();
}
+ t.traceEnd(); // PhaseActivityManagerReady
return;
}
+ t.traceBegin("controllersReady");
mLocalDeviceIdleController
= LocalServices.getService(DeviceIdleController.LocalService.class);
mActivityTaskManager.onSystemReady();
@@ -8876,6 +8879,7 @@
mUserController.onSystemReady();
mAppOpsService.systemReady();
mSystemReady = true;
+ t.traceEnd();
}
try {
@@ -8884,6 +8888,7 @@
.getSerial();
} catch (RemoteException e) {}
+ t.traceBegin("killProcesses");
ArrayList<ProcessRecord> procsToKill = null;
synchronized(mPidsSelfLocked) {
for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
@@ -8911,17 +8916,28 @@
// we won't trample on them any more.
mProcessesReady = true;
}
+ t.traceEnd(); // KillProcesses
Slog.i(TAG, "System now ready");
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY, SystemClock.uptimeMillis());
+ t.traceBegin("updateTopComponentForFactoryTest");
mAtmInternal.updateTopComponentForFactoryTest();
+ t.traceEnd();
+ t.traceBegin("watchDeviceProvisioning");
watchDeviceProvisioning(mContext);
+ t.traceEnd();
+ t.traceBegin("retrieveSettings");
retrieveSettings();
- mUgmInternal.onSystemReady();
+ t.traceEnd();
+ t.traceBegin("Ugm.onSystemReady");
+ mUgmInternal.onSystemReady();
+ t.traceEnd();
+
+ t.traceBegin("updateForceBackgroundCheck");
final PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class);
if (pmi != null) {
pmi.registerLowPowerModeObserver(ServiceType.FORCE_BACKGROUND_CHECK,
@@ -8931,8 +8947,11 @@
} else {
Slog.wtf(TAG, "PowerManagerInternal not found.");
}
+ t.traceEnd();
if (goingCallback != null) goingCallback.run();
+
+ t.traceBegin("getCurrentUser"); // should be fast, but these methods acquire locks
// Check the current user here as a user can be started inside goingCallback.run() from
// other system services.
final int currentUserId = mUserController.getCurrentUserId();
@@ -8943,17 +8962,21 @@
throw new RuntimeException("System user not started while current user is:"
+ currentUserId);
}
+ t.traceEnd();
+
t.traceBegin("ActivityManagerStartApps");
mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
Integer.toString(currentUserId), currentUserId);
mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
Integer.toString(currentUserId), currentUserId);
- mSystemServiceManager.startUser(currentUserId);
+ mSystemServiceManager.startUser(t, currentUserId);
synchronized (this) {
// Only start up encryption-aware persistent apps; once user is
// unlocked we'll come back around and start unaware apps
+ t.traceBegin("startPersistentApps");
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
+ t.traceEnd();
// Start up initial activity.
mBooting = true;
@@ -8963,6 +8986,7 @@
if (UserManager.isSplitSystemUser() &&
Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.USER_SETUP_COMPLETE, 0) != 0) {
+ t.traceBegin("enableHomeActivity");
ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);
try {
AppGlobals.getPackageManager().setComponentEnabledSetting(cName,
@@ -8971,63 +8995,81 @@
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
+ t.traceEnd();
}
+ t.traceBegin("startHomeOnAllDisplays");
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
+ t.traceEnd();
+ t.traceBegin("showSystemReadyErrorDialogs");
mAtmInternal.showSystemReadyErrorDialogsIfNeeded();
+ t.traceEnd();
- final int callingUid = Binder.getCallingUid();
- final int callingPid = Binder.getCallingPid();
- long ident = Binder.clearCallingIdentity();
- try {
- Intent intent = new Intent(Intent.ACTION_USER_STARTED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_FOREGROUND);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
- broadcastIntentLocked(null, null, intent,
- null, null, 0, null, null, null, OP_NONE,
- null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
- currentUserId);
- intent = new Intent(Intent.ACTION_USER_STARTING);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
- broadcastIntentLocked(null, null, intent,
- null, new IIntentReceiver.Stub() {
- @Override
- public void performReceive(Intent intent, int resultCode, String data,
- Bundle extras, boolean ordered, boolean sticky, int sendingUser)
- throws RemoteException {
- }
- }, 0, null, null,
- new String[] {INTERACT_ACROSS_USERS}, OP_NONE,
- null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
- UserHandle.USER_ALL);
- } catch (Throwable e) {
- Slog.wtf(TAG, "Failed sending first user broadcasts", e);
- } finally {
- Binder.restoreCallingIdentity(ident);
+ boolean isSystemUser = currentUserId == UserHandle.USER_SYSTEM;
+ if (isSystemUser) {
+ t.traceBegin("sendUserStartBroadcast");
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+ long ident = Binder.clearCallingIdentity();
+ try {
+ Intent intent = new Intent(Intent.ACTION_USER_STARTED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
+ broadcastIntentLocked(null, null, intent,
+ null, null, 0, null, null, null, OP_NONE,
+ null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
+ currentUserId);
+ intent = new Intent(Intent.ACTION_USER_STARTING);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
+ broadcastIntentLocked(null, null, intent, null,
+ new IIntentReceiver.Stub() {
+ @Override
+ public void performReceive(Intent intent, int resultCode,
+ String data, Bundle extras, boolean ordered, boolean sticky,
+ int sendingUser) {}
+ }, 0, null, null, new String[] {INTERACT_ACROSS_USERS}, OP_NONE, null,
+ true, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
+ UserHandle.USER_ALL);
+ } catch (Throwable e) {
+ Slog.wtf(TAG, "Failed sending first user broadcasts", e);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ t.traceEnd();
+ } else {
+ Slog.i(TAG, "Not sending multi-user broadcasts for non-system user "
+ + currentUserId);
}
- mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
- mUserController.sendUserSwitchBroadcasts(-1, currentUserId);
+ t.traceBegin("resumeTopActivities");
+ mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
+ t.traceEnd();
+
+ if (isSystemUser) {
+ t.traceBegin("sendUserSwitchBroadcasts");
+ mUserController.sendUserSwitchBroadcasts(-1, currentUserId);
+ t.traceEnd();
+ }
+
+ t.traceBegin("setBinderProxies");
BinderInternal.nSetBinderProxyCountWatermarks(BINDER_PROXY_HIGH_WATERMARK,
BINDER_PROXY_LOW_WATERMARK);
BinderInternal.nSetBinderProxyCountEnabled(true);
BinderInternal.setBinderProxyCountCallback(
- new BinderInternal.BinderProxyLimitListener() {
- @Override
- public void onLimitReached(int uid) {
- Slog.wtf(TAG, "Uid " + uid + " sent too many Binders to uid "
- + Process.myUid());
- BinderProxy.dumpProxyDebugInfo();
- if (uid == Process.SYSTEM_UID) {
- Slog.i(TAG, "Skipping kill (uid is SYSTEM)");
- } else {
- killUid(UserHandle.getAppId(uid), UserHandle.getUserId(uid),
- "Too many Binders sent to SYSTEM");
- }
+ (uid) -> {
+ Slog.wtf(TAG, "Uid " + uid + " sent too many Binders to uid "
+ + Process.myUid());
+ BinderProxy.dumpProxyDebugInfo();
+ if (uid == Process.SYSTEM_UID) {
+ Slog.i(TAG, "Skipping kill (uid is SYSTEM)");
+ } else {
+ killUid(UserHandle.getAppId(uid), UserHandle.getUserId(uid),
+ "Too many Binders sent to SYSTEM");
}
}, mHandler);
+ t.traceEnd(); // setBinderProxies
t.traceEnd(); // ActivityManagerStartApps
t.traceEnd(); // PhaseActivityManagerReady
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 043c207..8619ad5 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -912,7 +912,7 @@
final String localPackageName = packageName;
final int localForegroundId = foregroundId;
final int appUid = appInfo.uid;
- final int appPid = app.pid;
+ final int appPid = app != null ? app.pid : 0;
ams.mHandler.post(new Runnable() {
public void run() {
NotificationManagerInternal nm = LocalServices.getService(
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index a7d347b..d4ceb5a 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -72,7 +72,6 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
-import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
@@ -85,7 +84,6 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
-import android.util.TimingsTraceLog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
@@ -978,11 +976,13 @@
* <ul>
* <li>{@link Intent#ACTION_USER_STARTED} - sent to registered receivers of the new user
* <li>{@link Intent#ACTION_USER_BACKGROUND} - sent to registered receivers of the outgoing
- * user and all profiles of this user. Sent only if {@code foreground} parameter is true
+ * user and all profiles of this user. Sent only if {@code foreground} parameter is
+ * {@code false}
* <li>{@link Intent#ACTION_USER_FOREGROUND} - sent to registered receivers of the new
- * user and all profiles of this user. Sent only if {@code foreground} parameter is true
+ * user and all profiles of this user. Sent only if {@code foreground} parameter is
+ * {@code true}
* <li>{@link Intent#ACTION_USER_SWITCHED} - sent to registered receivers of the new user.
- * Sent only if {@code foreground} parameter is true
+ * Sent only if {@code foreground} parameter is {@code true}
* <li>{@link Intent#ACTION_USER_STARTING} - ordered broadcast sent to registered receivers
* of the new fg user
* <li>{@link Intent#ACTION_LOCKED_BOOT_COMPLETED} - ordered broadcast sent to receivers of
@@ -2135,6 +2135,7 @@
}
}
+ @Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case START_USER_SWITCH_FG_MSG:
@@ -2159,7 +2160,8 @@
mInjector.batteryStatsServiceNoteEvent(
BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
Integer.toString(msg.arg1), msg.arg1);
- mInjector.getSystemServiceManager().startUser(msg.arg1);
+ mInjector.getSystemServiceManager().startUser(TimingsTraceAndSlog.newAsyncLog(),
+ msg.arg1);
break;
case SYSTEM_USER_UNLOCK_MSG:
final int userId = msg.arg1;
@@ -2215,14 +2217,12 @@
// Report system user unlock time to perf dashboard
if (id == UserHandle.USER_SYSTEM) {
- new TimingsTraceLog("SystemServerTiming", Trace.TRACE_TAG_SYSTEM_SERVER)
- .logDuration("SystemUserUnlock", unlockTime);
+ new TimingsTraceAndSlog().logDuration("SystemUserUnlock", unlockTime);
} else {
- new TimingsTraceLog("SystemServerTiming", Trace.TRACE_TAG_SYSTEM_SERVER)
- .logDuration("User" + id + "Unlock", unlockTime);
+ new TimingsTraceAndSlog().logDuration("User" + id + "Unlock", unlockTime);
}
}
- };
+ }
@VisibleForTesting
static class Injector {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index a10a597..2fe5bbe 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1749,7 +1749,14 @@
*/
private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName,
boolean raw) {
- boolean isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
+ boolean isPrivileged;
+
+ try {
+ isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
+ } catch (SecurityException e) {
+ Slog.e(TAG, "checkOperation", e);
+ return AppOpsManager.opToDefaultMode(code);
+ }
synchronized (this) {
if (isOpRestrictedLocked(uid, code, packageName, isPrivileged)) {
@@ -1939,8 +1946,8 @@
try {
isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
} catch (SecurityException e) {
- Slog.e(TAG, "Cannot startOperation", e);
- return AppOpsManager.MODE_IGNORED;
+ Slog.e(TAG, "noteOperation", e);
+ return AppOpsManager.MODE_ERRORED;
}
synchronized (this) {
@@ -2117,8 +2124,8 @@
try {
isPrivileged = verifyAndGetIsPrivileged(uid, packageName);
} catch (SecurityException e) {
- Slog.e(TAG, "Cannot startOperation", e);
- return AppOpsManager.MODE_IGNORED;
+ Slog.e(TAG, "startOperation", e);
+ return AppOpsManager.MODE_ERRORED;
}
synchronized (this) {
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 626d724..9bae902 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -562,7 +562,7 @@
if (KeepaliveInfo.STARTING == ki.mStartedState) {
if (SUCCESS == reason) {
// Keepalive successfully started.
- if (DBG) Log.d(TAG, "Started keepalive " + slot + " on " + nai.name());
+ Log.d(TAG, "Started keepalive " + slot + " on " + nai.name());
ki.mStartedState = KeepaliveInfo.STARTED;
try {
ki.mCallback.onStarted(slot);
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index bcf5a71..077c405 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -178,31 +178,15 @@
CharSequence title;
CharSequence details;
int icon = getIcon(transportType, notifyType);
- if (notifyType == NotificationType.NO_INTERNET) {
- switch (transportType) {
- case TRANSPORT_WIFI:
- title = r.getString(R.string.wifi_no_internet,
- WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID()));
- details = r.getString(R.string.wifi_no_internet_detailed);
- break;
- default:
- // TODO: Display notifications for those networks that provide internet.
- // except VPN.
- return;
- }
-
- } else if (notifyType == NotificationType.PARTIAL_CONNECTIVITY) {
- switch (transportType) {
- case TRANSPORT_WIFI:
- title = r.getString(R.string.network_partial_connectivity,
- WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID()));
- details = r.getString(R.string.network_partial_connectivity_detailed);
- break;
- default:
- // TODO: Display notifications for those networks that provide internet.
- // except VPN.
- return;
- }
+ if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) {
+ title = r.getString(R.string.wifi_no_internet,
+ WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID()));
+ details = r.getString(R.string.wifi_no_internet_detailed);
+ } else if (notifyType == NotificationType.PARTIAL_CONNECTIVITY
+ && transportType == TRANSPORT_WIFI) {
+ title = r.getString(R.string.network_partial_connectivity,
+ WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID()));
+ details = r.getString(R.string.network_partial_connectivity_detailed);
} else if (notifyType == NotificationType.LOST_INTERNET &&
transportType == TRANSPORT_WIFI) {
title = r.getString(R.string.wifi_no_internet,
@@ -248,6 +232,11 @@
title = r.getString(R.string.network_switch_metered, toTransport);
details = r.getString(R.string.network_switch_metered_detail, toTransport,
fromTransport);
+ } else if (notifyType == NotificationType.NO_INTERNET
+ || notifyType == NotificationType.PARTIAL_CONNECTIVITY) {
+ // NO_INTERNET and PARTIAL_CONNECTIVITY notification for non-WiFi networks
+ // are sent, but they are not implemented yet.
+ return;
} else {
Slog.wtf(TAG, "Unknown notification type " + notifyType + " on network transport "
+ getTransportName(transportType));
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index fe75a81..27acb6b 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -935,7 +935,7 @@
if (mNightDisplayTintController.isActivatedStateNotSet()
|| (mNightDisplayTintController.isActivated() != activate)) {
- mNightDisplayTintController.setActivated(activate);
+ mNightDisplayTintController.setActivated(activate, activate ? start : end);
}
updateNextAlarm(mNightDisplayTintController.isActivated(), now);
@@ -1131,6 +1131,14 @@
@Override
public void setActivated(Boolean activated) {
+ setActivated(activated, LocalDateTime.now());
+ }
+
+ /**
+ * Use directly when it is important that the last activation time be exact (for example, an
+ * automatic change). Otherwise use {@link #setActivated(Boolean)}.
+ */
+ public void setActivated(Boolean activated, @NonNull LocalDateTime lastActivationTime) {
if (activated == null) {
super.setActivated(null);
return;
@@ -1142,7 +1150,7 @@
// This is a true state change, so set this as the last activation time.
Secure.putStringForUser(getContext().getContentResolver(),
Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
- LocalDateTime.now().toString(),
+ lastActivationTime.toString(),
mCurrentUser);
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index d4dded0..433ce81 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -32,6 +32,7 @@
import static com.android.internal.widget.LockPatternUtils.frpCredentialEnabled;
import static com.android.internal.widget.LockPatternUtils.userOwnsFrpCredential;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -169,6 +170,20 @@
private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
private static final int SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT = 1;
+ // No challenge provided
+ private static final int CHALLENGE_NONE = 0;
+ // Challenge was provided from the external caller (non-LockSettingsService)
+ private static final int CHALLENGE_FROM_CALLER = 1;
+ // Challenge was generated from within LockSettingsService, for resetLockout. When challenge
+ // type is set to internal, LSS will revokeChallenge after all profiles for that user are
+ // unlocked.
+ private static final int CHALLENGE_INTERNAL = 2;
+
+ @IntDef({CHALLENGE_NONE,
+ CHALLENGE_FROM_CALLER,
+ CHALLENGE_INTERNAL})
+ @interface ChallengeType {};
+
// Order of holding lock: mSeparateChallengeLock -> mSpManager -> this
// Do not call into ActivityManager while holding mSpManager lock.
private final Object mSeparateChallengeLock = new Object();
@@ -276,6 +291,15 @@
}
}
+ private class PendingResetLockout {
+ final int mUserId;
+ final byte[] mHAT;
+ PendingResetLockout(int userId, byte[] hat) {
+ mUserId = userId;
+ mHAT = hat;
+ }
+ }
+
/**
* Tie managed profile to primary profile if it is in unified mode and not tied before.
*
@@ -585,7 +609,7 @@
// be still locked, we ignore this case since the user will be prompted to unlock
// the device after boot.
unlockChildProfile(userId, true /* ignoreUserNotAuthenticated */,
- false /* hasChallenge */, 0 /* challenge */);
+ CHALLENGE_NONE, 0 /* challenge */, null /* resetLockouts */);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to unlock child profile");
}
@@ -1162,12 +1186,14 @@
}
private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated,
- boolean hasChallenge, long challenge)
+ @ChallengeType int challengeType, long challenge,
+ @Nullable ArrayList<PendingResetLockout> resetLockouts)
throws RemoteException {
try {
doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle),
CREDENTIAL_TYPE_PASSWORD,
- hasChallenge, challenge, profileHandle, null /* progressCallback */);
+ challengeType, challenge, profileHandle, null /* progressCallback */,
+ resetLockouts);
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
| NoSuchAlgorithmException | NoSuchPaddingException
| InvalidAlgorithmParameterException | IllegalBlockSizeException
@@ -1183,7 +1209,7 @@
}
private void unlockUser(int userId, byte[] token, byte[] secret) {
- unlockUser(userId, token, secret, false /* hasChallenge */, 0 /* challenge */);
+ unlockUser(userId, token, secret, CHALLENGE_NONE, 0 /* challenge */, null);
}
/**
@@ -1195,7 +1221,8 @@
* {@link com.android.server.SystemServiceManager#unlockUser} </em>
*/
private void unlockUser(int userId, byte[] token, byte[] secret,
- boolean hasChallenge, long challenge) {
+ @ChallengeType int challengeType, long challenge,
+ @Nullable ArrayList<PendingResetLockout> resetLockouts) {
// TODO: make this method fully async so we can update UI with progress strings
final boolean alreadyUnlocked = mUserManager.isUserUnlockingOrUnlocked(userId);
final CountDownLatch latch = new CountDownLatch(1);
@@ -1240,7 +1267,7 @@
// Must pass the challenge on for resetLockout, so it's not over-written, which
// causes LockSettingsService to revokeChallenge inappropriately.
unlockChildProfile(profile.id, false /* ignoreUserNotAuthenticated */,
- hasChallenge, challenge);
+ challengeType, challenge, resetLockouts);
} catch (RemoteException e) {
Log.d(TAG, "Failed to unlock child profile", e);
}
@@ -1257,6 +1284,21 @@
}
}
+
+ if (resetLockouts != null && !resetLockouts.isEmpty()) {
+ mHandler.post(() -> {
+ final BiometricManager bm = mContext.getSystemService(BiometricManager.class);
+ final PackageManager pm = mContext.getPackageManager();
+ for (int i = 0; i < resetLockouts.size(); i++) {
+ bm.setActiveUser(resetLockouts.get(i).mUserId);
+ bm.resetLockout(resetLockouts.get(i).mHAT);
+ }
+ if (challengeType == CHALLENGE_INTERNAL
+ && pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
+ mContext.getSystemService(FaceManager.class).revokeChallenge();
+ }
+ });
+ }
}
private boolean tiedManagedProfileReadyToUnlock(UserInfo userInfo) {
@@ -1528,7 +1570,8 @@
setUserKeyProtection(userId, credential, convertResponse(gkResponse));
fixateNewestUserKeyAuth(userId);
// Refresh the auth token
- doVerifyCredential(credential, credentialType, true, 0, userId, null /* progressCallback */);
+ doVerifyCredential(credential, credentialType, CHALLENGE_FROM_CALLER, 0, userId,
+ null /* progressCallback */);
synchronizeUnifiedWorkChallengeForProfiles(userId, null);
sendCredentialsOnChangeIfRequired(
credentialType, credential, userId, isLockTiedToParent);
@@ -1753,24 +1796,32 @@
public VerifyCredentialResponse checkCredential(byte[] credential, int type, int userId,
ICheckCredentialProgressCallback progressCallback) throws RemoteException {
checkPasswordReadPermission(userId);
- return doVerifyCredential(credential, type, false, 0, userId, progressCallback);
+ return doVerifyCredential(credential, type, CHALLENGE_NONE, 0, userId, progressCallback);
}
@Override
public VerifyCredentialResponse verifyCredential(byte[] credential, int type, long challenge,
int userId) throws RemoteException {
checkPasswordReadPermission(userId);
- return doVerifyCredential(credential, type, true, challenge, userId,
+ return doVerifyCredential(credential, type, CHALLENGE_FROM_CALLER, challenge, userId,
null /* progressCallback */);
}
+ private VerifyCredentialResponse doVerifyCredential(byte[] credential, int credentialType,
+ @ChallengeType int challengeType, long challenge, int userId,
+ ICheckCredentialProgressCallback progressCallback) throws RemoteException {
+ return doVerifyCredential(credential, credentialType, challengeType, challenge, userId,
+ progressCallback, null /* resetLockouts */);
+ }
+
/**
* Verify user credential and unlock the user. Fix pattern bug by deprecating the old base zero
* format.
*/
private VerifyCredentialResponse doVerifyCredential(byte[] credential, int credentialType,
- boolean hasChallenge, long challenge, int userId,
- ICheckCredentialProgressCallback progressCallback) throws RemoteException {
+ @ChallengeType int challengeType, long challenge, int userId,
+ ICheckCredentialProgressCallback progressCallback,
+ @Nullable ArrayList<PendingResetLockout> resetLockouts) throws RemoteException {
if (credential == null || credential.length == 0) {
throw new IllegalArgumentException("Credential can't be null or empty");
}
@@ -1780,8 +1831,8 @@
return VerifyCredentialResponse.ERROR;
}
VerifyCredentialResponse response = null;
- response = spBasedDoVerifyCredential(credential, credentialType, hasChallenge, challenge,
- userId, progressCallback);
+ response = spBasedDoVerifyCredential(credential, credentialType, challengeType, challenge,
+ userId, progressCallback, resetLockouts);
// The user employs synthetic password based credential.
if (response != null) {
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
@@ -1813,7 +1864,7 @@
}
response = verifyCredential(userId, storedHash, credentialToVerify,
- hasChallenge, challenge, progressCallback);
+ challengeType, challenge, progressCallback);
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
mStrongAuth.reportSuccessfulStrongAuthUnlock(userId);
@@ -1839,7 +1890,7 @@
final VerifyCredentialResponse parentResponse = doVerifyCredential(
credential,
type,
- true /* hasChallenge */,
+ CHALLENGE_FROM_CALLER,
challenge,
parentProfileId,
null /* progressCallback */);
@@ -1852,7 +1903,7 @@
// Unlock work profile, and work profile with unified lock must use password only
return doVerifyCredential(getDecryptedPasswordForTiedProfile(userId),
CREDENTIAL_TYPE_PASSWORD,
- true,
+ CHALLENGE_FROM_CALLER,
challenge,
userId, null /* progressCallback */);
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
@@ -1870,7 +1921,7 @@
* hash to GK.
*/
private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash,
- byte[] credential, boolean hasChallenge, long challenge,
+ byte[] credential, @ChallengeType int challengeType, long challenge,
ICheckCredentialProgressCallback progressCallback) throws RemoteException {
if ((storedHash == null || storedHash.hash.length == 0)
&& (credential == null || credential.length == 0)) {
@@ -1913,7 +1964,7 @@
: DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
/* TODO(roosa): keep the same password quality */,
userId, false, /* isLockTiedToParent= */ false);
- if (!hasChallenge) {
+ if (challengeType == CHALLENGE_NONE) {
notifyActivePasswordMetricsAvailable(storedHash.type, credential, userId);
// Use credentials to create recoverable keystore snapshot.
sendCredentialsOnUnlockIfRequired(storedHash.type, credential, userId);
@@ -2501,12 +2552,13 @@
}
private VerifyCredentialResponse spBasedDoVerifyCredential(byte[] userCredential,
- @CredentialType int credentialType, boolean hasChallenge, long challenge, int userId,
- ICheckCredentialProgressCallback progressCallback) throws RemoteException {
+ @CredentialType int credentialType, @ChallengeType int challengeType, long challenge,
+ int userId, ICheckCredentialProgressCallback progressCallback,
+ @Nullable ArrayList<PendingResetLockout> resetLockouts) throws RemoteException {
final boolean hasEnrolledBiometrics = mInjector.hasEnrolledBiometrics(userId);
- Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId + " hasChallenge=" + hasChallenge
+ Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId + " challengeType=" + challengeType
+ " hasEnrolledBiometrics=" + hasEnrolledBiometrics);
if (credentialType == CREDENTIAL_TYPE_NONE) {
userCredential = null;
@@ -2516,8 +2568,11 @@
// TODO: When lockout is handled under the HAL for all biometrics (fingerprint),
// we need to generate challenge for each one, have it signed by GK and reset lockout
// for each modality.
- if (!hasChallenge && pm.hasSystemFeature(PackageManager.FEATURE_FACE)
+ if (challengeType == CHALLENGE_NONE && pm.hasSystemFeature(PackageManager.FEATURE_FACE)
&& hasEnrolledBiometrics) {
+ // If there are multiple profiles in the same account, ensure we only generate the
+ // challenge once.
+ challengeType = CHALLENGE_INTERNAL;
challenge = mContext.getSystemService(FaceManager.class).generateChallenge();
}
@@ -2559,19 +2614,18 @@
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
notifyActivePasswordMetricsAvailable(credentialType, userCredential, userId);
unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId);
- // Reset lockout only if user has enrolled templates
- if (hasEnrolledBiometrics) {
- BiometricManager bm = mContext.getSystemService(BiometricManager.class);
- bm.resetLockout(response.getPayload());
- if (!hasChallenge && pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
- mContext.getSystemService(FaceManager.class).revokeChallenge();
+ // Do resetLockout / revokeChallenge when all profiles are unlocked
+ if (hasEnrolledBiometrics) {
+ if (resetLockouts == null) {
+ resetLockouts = new ArrayList<>();
}
+ resetLockouts.add(new PendingResetLockout(userId, response.getPayload()));
}
final byte[] secret = authResult.authToken.deriveDiskEncryptionKey();
Slog.i(TAG, "Unlocking user " + userId + " with secret only, length " + secret.length);
- unlockUser(userId, null, secret, hasChallenge, challenge);
+ unlockUser(userId, null, secret, challengeType, challenge, resetLockouts);
activateEscrowTokens(authResult.authToken, userId);
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index 69efd02..2d3c66d6 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -16,6 +16,7 @@
package com.android.server.net;
+import static android.net.NetworkStats.INTERFACES_ALL;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.TAG_ALL;
import static android.net.NetworkStats.TAG_NONE;
@@ -33,6 +34,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.net.VpnInfo;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ProcFileReader;
@@ -70,11 +72,25 @@
private INetd mNetdService;
- // A persistent Snapshot since device start for eBPF stats
- @GuardedBy("mPersistSnapshot")
- private final NetworkStats mPersistSnapshot;
+ /**
+ * Guards persistent data access in this class
+ *
+ * <p>In order to prevent deadlocks, critical sections protected by this lock SHALL NOT call out
+ * to other code that will acquire other locks within the system server. See b/134244752.
+ */
+ private static final Object sPersistentDataLock = new Object();
- // TODO: only do adjustments in NetworkStatsService and remove this.
+ /** Set containing info about active VPNs and their underlying networks. */
+ private static volatile VpnInfo[] sVpnInfos = new VpnInfo[0];
+
+ // A persistent snapshot of cumulative stats since device start
+ @GuardedBy("sPersistentDataLock")
+ private NetworkStats mPersistSnapshot;
+
+ // The persistent snapshot of tun and 464xlat adjusted stats since device start
+ @GuardedBy("sPersistentDataLock")
+ private NetworkStats mTunAnd464xlatAdjustedStats;
+
/**
* (Stacked interface) -> (base interface) association for all connected ifaces since boot.
*
@@ -91,6 +107,24 @@
}
/**
+ * Set active VPN information for data usage migration purposes
+ *
+ * <p>Traffic on TUN-based VPNs inherently all appear to be originated from the VPN providing
+ * app's UID. This method is used to support migration of VPN data usage, ensuring data is
+ * accurately billed to the real owner of the traffic.
+ *
+ * @param vpnArray The snapshot of the currently-running VPNs.
+ */
+ public static void updateVpnInfos(VpnInfo[] vpnArray) {
+ sVpnInfos = vpnArray.clone();
+ }
+
+ @VisibleForTesting
+ public static VpnInfo[] getVpnInfos() {
+ return sVpnInfos.clone();
+ }
+
+ /**
* Get a set of interfaces containing specified ifaces and stacked interfaces.
*
* <p>The added stacked interfaces are ifaces stacked on top of the specified ones, or ifaces
@@ -146,6 +180,7 @@
mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
mUseBpfStats = useBpfStats;
mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1);
+ mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
}
public NetworkStats readBpfNetworkStatsDev() throws IOException {
@@ -264,22 +299,24 @@
}
public NetworkStats readNetworkStatsDetail() throws IOException {
- return readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null);
+ return readNetworkStatsDetail(UID_ALL, INTERFACES_ALL, TAG_ALL);
}
- public NetworkStats readNetworkStatsDetail(int limitUid, String[] limitIfaces, int limitTag,
- NetworkStats lastStats) throws IOException {
- final NetworkStats stats =
- readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag, lastStats);
-
- // No locking here: apply464xlatAdjustments behaves fine with an add-only ConcurrentHashMap.
- // TODO: remove this and only apply adjustments in NetworkStatsService.
- stats.apply464xlatAdjustments(sStackedIfaces, mUseBpfStats);
-
- return stats;
+ /**
+ * Reads the detailed UID stats based on the provided parameters
+ *
+ * @param limitUid the UID to limit this query to
+ * @param limitIfaces the interfaces to limit this query to. Use {@link
+ * NetworkStats.INTERFACES_ALL} to select all interfaces
+ * @param limitTag the tags to limit this query to
+ * @return the NetworkStats instance containing network statistics at the present time.
+ */
+ public NetworkStats readNetworkStatsDetail(
+ int limitUid, @Nullable String[] limitIfaces, int limitTag) throws IOException {
+ return readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag);
}
- @GuardedBy("mPersistSnapshot")
+ @GuardedBy("sPersistentDataLock")
private void requestSwapActiveStatsMapLocked() throws RemoteException {
// Ask netd to do a active map stats swap. When the binder call successfully returns,
// the system server should be able to safely read and clean the inactive map
@@ -292,19 +329,20 @@
}
}
- // TODO: delete the lastStats parameter
- private NetworkStats readNetworkStatsDetailInternal(int limitUid, String[] limitIfaces,
- int limitTag, NetworkStats lastStats) throws IOException {
- if (USE_NATIVE_PARSING) {
- final NetworkStats stats;
- if (lastStats != null) {
- stats = lastStats;
- stats.setElapsedRealtime(SystemClock.elapsedRealtime());
- } else {
- stats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
- }
- if (mUseBpfStats) {
- synchronized (mPersistSnapshot) {
+ private NetworkStats readNetworkStatsDetailInternal(
+ int limitUid, String[] limitIfaces, int limitTag) throws IOException {
+ // In order to prevent deadlocks, anything protected by this lock MUST NOT call out to other
+ // code that will acquire other locks within the system server. See b/134244752.
+ synchronized (sPersistentDataLock) {
+ // Take a reference. If this gets swapped out, we still have the old reference.
+ final VpnInfo[] vpnArray = sVpnInfos;
+ // Take a defensive copy. mPersistSnapshot is mutated in some cases below
+ final NetworkStats prev = mPersistSnapshot.clone();
+
+ if (USE_NATIVE_PARSING) {
+ final NetworkStats stats =
+ new NetworkStats(SystemClock.elapsedRealtime(), 0 /* initialSize */);
+ if (mUseBpfStats) {
try {
requestSwapActiveStatsMapLocked();
} catch (RemoteException e) {
@@ -313,32 +351,66 @@
// Stats are always read from the inactive map, so they must be read after the
// swap
if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL,
- null, TAG_ALL, mUseBpfStats) != 0) {
+ INTERFACES_ALL, TAG_ALL, mUseBpfStats) != 0) {
throw new IOException("Failed to parse network stats");
}
+
+ // BPF stats are incremental; fold into mPersistSnapshot.
mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime());
mPersistSnapshot.combineAllValues(stats);
- NetworkStats result = mPersistSnapshot.clone();
- result.filter(limitUid, limitIfaces, limitTag);
- return result;
+ } else {
+ if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL,
+ INTERFACES_ALL, TAG_ALL, mUseBpfStats) != 0) {
+ throw new IOException("Failed to parse network stats");
+ }
+ if (SANITY_CHECK_NATIVE) {
+ final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid,
+ UID_ALL, INTERFACES_ALL, TAG_ALL);
+ assertEquals(javaStats, stats);
+ }
+
+ mPersistSnapshot = stats;
}
} else {
- if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid,
- limitIfaces, limitTag, mUseBpfStats) != 0) {
- throw new IOException("Failed to parse network stats");
- }
- if (SANITY_CHECK_NATIVE) {
- final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid, limitUid,
- limitIfaces, limitTag);
- assertEquals(javaStats, stats);
- }
- return stats;
+ mPersistSnapshot = javaReadNetworkStatsDetail(mStatsXtUid, UID_ALL, INTERFACES_ALL,
+ TAG_ALL);
}
- } else {
- return javaReadNetworkStatsDetail(mStatsXtUid, limitUid, limitIfaces, limitTag);
+
+ NetworkStats adjustedStats = adjustForTunAnd464Xlat(mPersistSnapshot, prev, vpnArray);
+
+ // Filter return values
+ adjustedStats.filter(limitUid, limitIfaces, limitTag);
+ return adjustedStats;
}
}
+ @GuardedBy("sPersistentDataLock")
+ private NetworkStats adjustForTunAnd464Xlat(
+ NetworkStats uidDetailStats, NetworkStats previousStats, VpnInfo[] vpnArray) {
+ // Calculate delta from last snapshot
+ final NetworkStats delta = uidDetailStats.subtract(previousStats);
+
+ // Apply 464xlat adjustments before VPN adjustments. If VPNs are using v4 on a v6 only
+ // network, the overhead is their fault.
+ // No locking here: apply464xlatAdjustments behaves fine with an add-only
+ // ConcurrentHashMap.
+ delta.apply464xlatAdjustments(sStackedIfaces, mUseBpfStats);
+
+ // Migrate data usage over a VPN to the TUN network.
+ for (VpnInfo info : vpnArray) {
+ delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces);
+ }
+
+ // Filter out debug entries as that may lead to over counting.
+ delta.filterDebugEntries();
+
+ // Update mTunAnd464xlatAdjustedStats with migrated delta.
+ mTunAnd464xlatAdjustedStats.combineAllValues(delta);
+ mTunAnd464xlatAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime());
+
+ return mTunAnd464xlatAdjustedStats.clone();
+ }
+
/**
* Parse and return {@link NetworkStats} with UID-level details. Values are
* expected to monotonically increase since device boot.
diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java
index d840873..2564dae 100644
--- a/services/core/java/com/android/server/net/NetworkStatsObservers.java
+++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java
@@ -39,7 +39,6 @@
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.net.VpnInfo;
import java.util.concurrent.atomic.AtomicInteger;
@@ -104,9 +103,9 @@
public void updateStats(NetworkStats xtSnapshot, NetworkStats uidSnapshot,
ArrayMap<String, NetworkIdentitySet> activeIfaces,
ArrayMap<String, NetworkIdentitySet> activeUidIfaces,
- VpnInfo[] vpnArray, long currentTime) {
+ long currentTime) {
StatsContext statsContext = new StatsContext(xtSnapshot, uidSnapshot, activeIfaces,
- activeUidIfaces, vpnArray, currentTime);
+ activeUidIfaces, currentTime);
getHandler().sendMessage(mHandler.obtainMessage(MSG_UPDATE_STATS, statsContext));
}
@@ -354,7 +353,7 @@
// thread will update it. We pass a null VPN array because usage is aggregated by uid
// for this snapshot, so VPN traffic can't be reattributed to responsible apps.
mRecorder.recordSnapshotLocked(statsContext.mXtSnapshot, statsContext.mActiveIfaces,
- null /* vpnArray */, statsContext.mCurrentTime);
+ statsContext.mCurrentTime);
}
/**
@@ -396,7 +395,7 @@
// thread will update it. We pass the VPN info so VPN traffic is reattributed to
// responsible apps.
mRecorder.recordSnapshotLocked(statsContext.mUidSnapshot, statsContext.mActiveUidIfaces,
- statsContext.mVpnArray, statsContext.mCurrentTime);
+ statsContext.mCurrentTime);
}
/**
@@ -427,18 +426,16 @@
NetworkStats mUidSnapshot;
ArrayMap<String, NetworkIdentitySet> mActiveIfaces;
ArrayMap<String, NetworkIdentitySet> mActiveUidIfaces;
- VpnInfo[] mVpnArray;
long mCurrentTime;
StatsContext(NetworkStats xtSnapshot, NetworkStats uidSnapshot,
ArrayMap<String, NetworkIdentitySet> activeIfaces,
ArrayMap<String, NetworkIdentitySet> activeUidIfaces,
- VpnInfo[] vpnArray, long currentTime) {
+ long currentTime) {
mXtSnapshot = xtSnapshot;
mUidSnapshot = uidSnapshot;
mActiveIfaces = activeIfaces;
mActiveUidIfaces = activeUidIfaces;
- mVpnArray = vpnArray;
mCurrentTime = currentTime;
}
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index a2e7e0c..06ec341 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -23,7 +23,6 @@
import static com.android.internal.util.Preconditions.checkNotNull;
-import android.annotation.Nullable;
import android.net.NetworkStats;
import android.net.NetworkStats.NonMonotonicObserver;
import android.net.NetworkStatsHistory;
@@ -37,14 +36,13 @@
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
-import com.android.internal.net.VpnInfo;
import com.android.internal.util.FileRotator;
import com.android.internal.util.IndentingPrintWriter;
-import libcore.io.IoUtils;
-
import com.google.android.collect.Sets;
+import libcore.io.IoUtils;
+
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
@@ -202,18 +200,12 @@
}
/**
- * Record any delta that occurred since last {@link NetworkStats} snapshot,
- * using the given {@link Map} to identify network interfaces. First
- * snapshot is considered bootstrap, and is not counted as delta.
- *
- * @param vpnArray Optional info about the currently active VPN, if any. This is used to
- * redistribute traffic from the VPN app to the underlying responsible apps.
- * This should always be set to null if the provided snapshot is aggregated
- * across all UIDs (e.g. contains UID_ALL buckets), regardless of VPN state.
+ * Record any delta that occurred since last {@link NetworkStats} snapshot, using the given
+ * {@link Map} to identify network interfaces. First snapshot is considered bootstrap, and is
+ * not counted as delta.
*/
public void recordSnapshotLocked(NetworkStats snapshot,
- Map<String, NetworkIdentitySet> ifaceIdent, @Nullable VpnInfo[] vpnArray,
- long currentTimeMillis) {
+ Map<String, NetworkIdentitySet> ifaceIdent, long currentTimeMillis) {
final HashSet<String> unknownIfaces = Sets.newHashSet();
// skip recording when snapshot missing
@@ -232,12 +224,6 @@
final long end = currentTimeMillis;
final long start = end - delta.getElapsedRealtime();
- if (vpnArray != null) {
- for (VpnInfo info : vpnArray) {
- delta.migrateTun(info.ownerUid, info.vpnIface, info.primaryUnderlyingIface);
- }
- }
-
NetworkStats.Entry entry = null;
for (int i = 0; i < delta.size(); i++) {
entry = delta.getValues(i, entry);
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index f34ace5..42802f6 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -131,7 +131,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.net.VpnInfo;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FileRotator;
@@ -267,10 +266,6 @@
@GuardedBy("mStatsLock")
private Network[] mDefaultNetworks = new Network[0];
- /** Set containing info about active VPNs and their underlying networks. */
- @GuardedBy("mStatsLock")
- private VpnInfo[] mVpnInfos = new VpnInfo[0];
-
private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
new DropBoxNonMonotonicObserver();
@@ -864,7 +859,6 @@
@Override
public void forceUpdateIfaces(
Network[] defaultNetworks,
- VpnInfo[] vpnArray,
NetworkState[] networkStates,
String activeIface) {
checkNetworkStackPermission(mContext);
@@ -872,7 +866,7 @@
final long token = Binder.clearCallingIdentity();
try {
- updateIfaces(defaultNetworks, vpnArray, networkStates, activeIface);
+ updateIfaces(defaultNetworks, networkStates, activeIface);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1138,13 +1132,11 @@
private void updateIfaces(
Network[] defaultNetworks,
- VpnInfo[] vpnArray,
NetworkState[] networkStates,
String activeIface) {
synchronized (mStatsLock) {
mWakeLock.acquire();
try {
- mVpnInfos = vpnArray;
mActiveIface = activeIface;
updateIfacesLocked(defaultNetworks, networkStates);
} finally {
@@ -1154,10 +1146,9 @@
}
/**
- * Inspect all current {@link NetworkState} to derive mapping from {@code
- * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
- * are active on a single {@code iface}, they are combined under a single
- * {@link NetworkIdentitySet}.
+ * Inspect all current {@link NetworkState} to derive mapping from {@code iface} to {@link
+ * NetworkStatsHistory}. When multiple {@link NetworkInfo} are active on a single {@code iface},
+ * they are combined under a single {@link NetworkIdentitySet}.
*/
@GuardedBy("mStatsLock")
private void updateIfacesLocked(Network[] defaultNetworks, NetworkState[] states) {
@@ -1274,27 +1265,24 @@
// For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic
// can't be reattributed to responsible apps.
Trace.traceBegin(TRACE_TAG_NETWORK, "recordDev");
- mDevRecorder.recordSnapshotLocked(
- devSnapshot, mActiveIfaces, null /* vpnArray */, currentTime);
+ mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
Trace.traceEnd(TRACE_TAG_NETWORK);
Trace.traceBegin(TRACE_TAG_NETWORK, "recordXt");
- mXtRecorder.recordSnapshotLocked(
- xtSnapshot, mActiveIfaces, null /* vpnArray */, currentTime);
+ mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime);
Trace.traceEnd(TRACE_TAG_NETWORK);
// For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps.
- VpnInfo[] vpnArray = mVpnInfos;
Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid");
- mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime);
+ mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
Trace.traceEnd(TRACE_TAG_NETWORK);
Trace.traceBegin(TRACE_TAG_NETWORK, "recordUidTag");
- mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime);
+ mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
Trace.traceEnd(TRACE_TAG_NETWORK);
// We need to make copies of member fields that are sent to the observer to avoid
// a race condition between the service handler thread and the observer's
mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces),
- new ArrayMap<>(mActiveUidIfaces), vpnArray, currentTime);
+ new ArrayMap<>(mActiveUidIfaces), currentTime);
}
/**
@@ -1667,8 +1655,6 @@
*/
private NetworkStats getNetworkStatsUidDetail(String[] ifaces)
throws RemoteException {
-
- // TODO: remove 464xlat adjustments from NetworkStatsFactory and apply all at once here.
final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL,
ifaces);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index c3188c8..83c9c73 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2399,6 +2399,13 @@
}
@Override
+ public void silenceNotificationSound() {
+ checkCallerIsSystem();
+
+ mNotificationDelegate.clearEffects();
+ }
+
+ @Override
public void setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled) {
enforceSystemOrSystemUI("setNotificationsEnabledForPackage");
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index adcd19e..b3b0029 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -85,6 +85,9 @@
public static final int FLAG_USE_QUOTA = IInstalld.FLAG_USE_QUOTA;
public static final int FLAG_FORCE = IInstalld.FLAG_FORCE;
+ public static final int FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES =
+ IInstalld.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES;
+
private final boolean mIsolated;
private volatile IInstalld mInstalld;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b04a051..62dd3fb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -322,6 +322,7 @@
import com.android.server.pm.permission.PermissionsState;
import com.android.server.security.VerityUtils;
import com.android.server.storage.DeviceStorageMonitorInternal;
+import com.android.server.utils.TimingsTraceAndSlog;
import com.android.server.wm.ActivityTaskManagerInternal;
import dalvik.system.CloseGuard;
@@ -2384,10 +2385,12 @@
}
}
- public PackageManagerService(Context context, Installer installer,
- boolean factoryTest, boolean onlyCore) {
+ public PackageManagerService(Context context, Installer installer, boolean factoryTest,
+ boolean onlyCore) {
+ final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
+ Trace.TRACE_TAG_PACKAGE_MANAGER);
+ t.traceBegin("create package manager");
LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "create package manager");
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
SystemClock.uptimeMillis());
@@ -2403,6 +2406,8 @@
mInstaller = installer;
// Create sub-components that provide services / data. Order here is important.
+ t.traceBegin("createSubComponents");
+ // CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
synchronized (mPackages) {
// Expose private service for system components to use.
@@ -2420,6 +2425,10 @@
mPermissionManager.getPermissionSettings(), mPackages);
}
}
+ // CHECKSTYLE:ON IndentationCheck
+ t.traceEnd();
+
+ t.traceBegin("addSharedUsers");
mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
@@ -2436,6 +2445,7 @@
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.networkstack", NETWORKSTACK_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+ t.traceEnd();
String separateProcesses = SystemProperties.get("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {
@@ -2467,14 +2477,15 @@
getDefaultDisplayMetrics(context, mMetrics);
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "get system config");
+ t.traceBegin("get system config");
SystemConfig systemConfig = SystemConfig.getInstance();
mAvailableFeatures = systemConfig.getAvailableFeatures();
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ t.traceEnd();
mProtectedPackages = new ProtectedPackages(mContext);
mApexManager = new ApexManager(context);
+ // CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
// writer
synchronized (mPackages) {
@@ -2513,13 +2524,13 @@
SELinuxMMAC.readInstallPolicy();
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "loadFallbacks");
+ t.traceBegin("loadFallbacks");
FallbackCategoryProvider.loadFallbacks();
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ t.traceEnd();
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings");
+ t.traceBegin("read user settings");
mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ t.traceEnd();
// Clean up orphaned packages for which the code path doesn't exist
// and they are an update to a system app - caused by bug/32321269
@@ -3240,7 +3251,8 @@
// No apps are running this early, so no need to freeze
clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
- | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ | Installer.FLAG_CLEAR_CODE_CACHE_ONLY
+ | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
}
}
ver.fingerprint = Build.FINGERPRINT;
@@ -3269,9 +3281,9 @@
ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;
// can downgrade to reader
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "write settings");
+ t.traceBegin("write settings");
mSettings.writeLPr();
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ t.traceEnd();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
@@ -3357,15 +3369,16 @@
}
} // synchronized (mPackages)
} // synchronized (mInstallLock)
+ // CHECKSTYLE:ON IndentationCheck
mModuleInfoProvider = new ModuleInfoProvider(mContext, this);
// Now after opening every single application zip, make sure they
// are all flushed. Not really needed, but keeps things nice and
// tidy.
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "GC");
+ t.traceBegin("GC");
Runtime.getRuntime().gc();
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ t.traceEnd();
// The initial scanning above does many calls into installd while
// holding the mPackages lock, but we're mostly interested in yelling
@@ -3376,7 +3389,7 @@
mServiceStartWithDelay = SystemClock.uptimeMillis() + (60 * 1000L);
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ t.traceEnd(); // "create package manager"
}
/**
@@ -10320,7 +10333,9 @@
clearAppDataLeafLIF(pkg.childPackages.get(i), userId, flags);
}
- clearAppProfilesLIF(pkg, UserHandle.USER_ALL);
+ if ((flags & Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) {
+ clearAppProfilesLIF(pkg, UserHandle.USER_ALL);
+ }
}
private void clearAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
@@ -22541,7 +22556,8 @@
if (!Build.FINGERPRINT.equals(ver.fingerprint)) {
clearAppDataLIF(ps.pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
- | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY
+ | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
}
}
}
@@ -24340,8 +24356,12 @@
@Override
public boolean isPermissionsReviewRequired(String packageName, int userId) {
synchronized (mPackages) {
- return mPermissionManager.isPermissionsReviewRequired(
- mPackages.get(packageName), userId);
+ final PackageParser.Package pkg = mPackages.get(packageName);
+ if (pkg == null) {
+ return false;
+ }
+
+ return mPermissionManager.isPermissionsReviewRequired(pkg, userId);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 50fd8a7..5b80556 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -129,6 +129,7 @@
private static final String STDIN_PATH = "-";
/** Path where ART profiles snapshots are dumped for the shell user */
private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
+ private static final int DEFAULT_WAIT_MS = 60 * 1000;
final IPackageManager mInterface;
final private WeakHashMap<String, Resources> mResourceCache =
@@ -1078,6 +1079,45 @@
return 1;
}
abandonSession = false;
+
+ if (!params.sessionParams.isStaged || !params.waitForStagedSessionReady) {
+ pw.println("Success");
+ return 0;
+ }
+
+ long timeoutMs = params.timeoutMs <= 0
+ ? DEFAULT_WAIT_MS
+ : params.timeoutMs;
+ PackageInstaller.SessionInfo si = mInterface.getPackageInstaller()
+ .getSessionInfo(sessionId);
+ long currentTime = System.currentTimeMillis();
+ long endTime = currentTime + timeoutMs;
+ // Using a loop instead of BroadcastReceiver since we can receive session update
+ // broadcast only if packageInstallerName is "android". We can't always force
+ // "android" as packageIntallerName, e.g, rollback auto implies
+ // "-i com.android.shell".
+ while (currentTime < endTime) {
+ if (si != null
+ && (si.isStagedSessionReady() || si.isStagedSessionFailed())) {
+ break;
+ }
+ SystemClock.sleep(Math.min(endTime - currentTime, 100));
+ currentTime = System.currentTimeMillis();
+ si = mInterface.getPackageInstaller().getSessionInfo(sessionId);
+ }
+ if (si == null) {
+ pw.println("Failure [failed to retrieve SessionInfo]");
+ return 1;
+ }
+ if (!si.isStagedSessionReady() && !si.isStagedSessionFailed()) {
+ pw.println("Failure [timed out after " + timeoutMs + " ms]");
+ return 1;
+ }
+ if (!si.isStagedSessionReady()) {
+ pw.println("Error [" + si.getStagedSessionErrorCode() + "] ["
+ + si.getStagedSessionErrorMessage() + "]");
+ return 1;
+ }
pw.println("Success");
return 0;
} finally {
@@ -2368,6 +2408,8 @@
SessionParams sessionParams;
String installerPackageName;
int userId = UserHandle.USER_ALL;
+ boolean waitForStagedSessionReady = false;
+ long timeoutMs = DEFAULT_WAIT_MS;
}
private InstallParams makeInstallParams() {
@@ -2493,6 +2535,14 @@
}
sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK;
break;
+ case "--wait":
+ params.waitForStagedSessionReady = true;
+ try {
+ params.timeoutMs = Long.parseLong(peekNextArg());
+ getNextArg();
+ } catch (NumberFormatException ignore) {
+ }
+ break;
default:
throw new IllegalArgumentException("Unknown option " + opt);
}
@@ -3048,7 +3098,8 @@
pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
pw.println(" [--preload] [--instantapp] [--full] [--dont-kill]");
pw.println(" [--enable-rollback]");
- pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES] [--apex]");
+ pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
+ pw.println(" [--apex] [--wait TIMEOUT]");
pw.println(" [PATH|-]");
pw.println(" Install an application. Must provide the apk data to install, either as a");
pw.println(" file path or '-' to read from stdin. Options are:");
@@ -3078,6 +3129,9 @@
pw.println(" 3=device setup, 4=user request");
pw.println(" --force-uuid: force install on to disk volume with given UUID");
pw.println(" --apex: install an .apex file, not an .apk");
+ pw.println(" --wait: when performing staged install, wait TIMEOUT milliseconds");
+ pw.println(" for pre-reboot verification to complete. If TIMEOUT is not");
+ pw.println(" specified it will wait for " + DEFAULT_WAIT_MS + " milliseconds.");
pw.println("");
pw.println(" install-create [-lrtsfdg] [-i PACKAGE] [--user USER_ID|all|current]");
pw.println(" [-p INHERIT_PACKAGE] [--install-location 0/1/2]");
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 829dd0f..f4ba449 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -3693,6 +3693,11 @@
long now = System.currentTimeMillis();
final long nowRealtime = SystemClock.elapsedRealtime();
+
+ final int currentUser = LocalServices.getService(ActivityManagerInternal.class)
+ .getCurrentUserId();
+ pw.print("Current user: "); pw.println(currentUser);
+
StringBuilder sb = new StringBuilder();
synchronized (mPackagesLock) {
synchronized (mUsersLock) {
@@ -3706,6 +3711,7 @@
final int userId = userInfo.id;
pw.print(" "); pw.print(userInfo);
pw.print(" serialNo="); pw.print(userInfo.serialNumber);
+ pw.print(" isPrimary="); pw.print(userInfo.isPrimary());
if (mRemovingUserIds.get(userId)) {
pw.print(" <removing> ");
}
@@ -3788,13 +3794,15 @@
synchronized (mUserStates) {
pw.println(" Started users state: " + mUserStates);
}
- // Dump some capabilities
- pw.println();
- pw.println(" Max users: " + UserManager.getMaxSupportedUsers());
- pw.println(" Supports switchable users: " + UserManager.supportsMultipleUsers());
- pw.println(" All guests ephemeral: " + Resources.getSystem().getBoolean(
- com.android.internal.R.bool.config_guestUserEphemeral));
- }
+ } // synchronized (mPackagesLock)
+
+ // Dump some capabilities
+ pw.println();
+ pw.println(" Max users: " + UserManager.getMaxSupportedUsers());
+ pw.println(" Supports switchable users: " + UserManager.supportsMultipleUsers());
+ pw.println(" All guests ephemeral: " + Resources.getSystem().getBoolean(
+ com.android.internal.R.bool.config_guestUserEphemeral));
+ pw.println(" Is split-system user: " + UserManager.isSplitSystemUser());
}
private static void dumpTimeAgo(PrintWriter pw, StringBuilder sb, long nowTime, long time) {
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 03c7789..db01d77 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -143,12 +143,6 @@
CONTACTS_PERMISSIONS.add(Manifest.permission.GET_ACCOUNTS);
}
- private static final Set<String> LOCATION_PERMISSIONS = new ArraySet<>();
- static {
- LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_FINE_LOCATION);
- LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_COARSE_LOCATION);
- }
-
private static final Set<String> ALWAYS_LOCATION_PERMISSIONS = new ArraySet<>();
static {
ALWAYS_LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_FINE_LOCATION);
@@ -453,7 +447,8 @@
// SetupWizard
grantPermissionsToSystemPackage(
getKnownPackage(PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId), userId,
- PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, LOCATION_PERMISSIONS, CAMERA_PERMISSIONS);
+ PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS,
+ CAMERA_PERMISSIONS);
// Camera
grantPermissionsToSystemPackage(
@@ -585,7 +580,7 @@
// Maps
grantPermissionsToSystemPackage(
getDefaultSystemHandlerActivityPackageForCategory(Intent.CATEGORY_APP_MAPS, userId),
- userId, LOCATION_PERMISSIONS);
+ userId, ALWAYS_LOCATION_PERMISSIONS);
// Gallery
grantPermissionsToSystemPackage(
@@ -609,14 +604,14 @@
}
}
grantPermissionsToPackage(browserPackage, userId, false /* ignoreSystemPackage */,
- true /*whitelistRestrictedPermissions*/, LOCATION_PERMISSIONS);
+ true /*whitelistRestrictedPermissions*/, ALWAYS_LOCATION_PERMISSIONS);
// Voice interaction
if (voiceInteractPackageNames != null) {
for (String voiceInteractPackageName : voiceInteractPackageNames) {
grantPermissionsToSystemPackage(voiceInteractPackageName, userId,
CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
- PHONE_PERMISSIONS, SMS_PERMISSIONS, LOCATION_PERMISSIONS);
+ PHONE_PERMISSIONS, SMS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS);
}
}
@@ -625,7 +620,7 @@
grantPermissionsToSystemPackage(
getDefaultSystemHandlerActivityPackage(
SearchManager.INTENT_ACTION_GLOBAL_SEARCH, userId),
- userId, MICROPHONE_PERMISSIONS, LOCATION_PERMISSIONS);
+ userId, MICROPHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS);
}
// Voice recognition
@@ -667,7 +662,7 @@
.addCategory(Intent.CATEGORY_LAUNCHER_APP);
grantPermissionsToSystemPackage(
getDefaultSystemHandlerActivityPackage(homeIntent, userId), userId,
- LOCATION_PERMISSIONS);
+ ALWAYS_LOCATION_PERMISSIONS);
// Watches
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH, 0)) {
@@ -676,18 +671,18 @@
String wearPackage = getDefaultSystemHandlerActivityPackageForCategory(
Intent.CATEGORY_HOME_MAIN, userId);
grantPermissionsToSystemPackage(wearPackage, userId,
- CONTACTS_PERMISSIONS, MICROPHONE_PERMISSIONS, LOCATION_PERMISSIONS);
+ CONTACTS_PERMISSIONS, MICROPHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS);
grantSystemFixedPermissionsToSystemPackage(wearPackage, userId, PHONE_PERMISSIONS);
// Fitness tracking on watches
grantPermissionsToSystemPackage(
getDefaultSystemHandlerActivityPackage(ACTION_TRACK, userId), userId,
- SENSORS_PERMISSIONS, LOCATION_PERMISSIONS);
+ SENSORS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS);
}
// Print Spooler
grantSystemFixedPermissionsToSystemPackage(PrintManager.PRINT_SPOOLER_PACKAGE_NAME, userId,
- LOCATION_PERMISSIONS);
+ ALWAYS_LOCATION_PERMISSIONS);
// EmergencyInfo
grantSystemFixedPermissionsToSystemPackage(
@@ -725,7 +720,7 @@
if (!TextUtils.isEmpty(textClassifierPackageName)) {
grantPermissionsToSystemPackage(textClassifierPackageName, userId,
PHONE_PERMISSIONS, SMS_PERMISSIONS, CALENDAR_PERMISSIONS,
- LOCATION_PERMISSIONS, CONTACTS_PERMISSIONS);
+ ALWAYS_LOCATION_PERMISSIONS, CONTACTS_PERMISSIONS);
}
// Atthention Service
@@ -835,7 +830,7 @@
}
for (String packageName : packageNames) {
grantPermissionsToSystemPackage(packageName, userId,
- PHONE_PERMISSIONS, MICROPHONE_PERMISSIONS, LOCATION_PERMISSIONS,
+ PHONE_PERMISSIONS, MICROPHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS,
CAMERA_PERMISSIONS, CONTACTS_PERMISSIONS);
}
}
@@ -850,7 +845,7 @@
// Grant these permissions as system-fixed, so that nobody can accidentally
// break cellular data.
grantSystemFixedPermissionsToSystemPackage(packageName, userId,
- PHONE_PERMISSIONS, LOCATION_PERMISSIONS);
+ PHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS);
}
}
@@ -864,7 +859,7 @@
PackageInfo pkg = getSystemPackageInfo(packageName);
if (isSystemPackage(pkg) && doesPackageSupportRuntimePermissions(pkg)) {
revokeRuntimePermissions(packageName, PHONE_PERMISSIONS, true, userId);
- revokeRuntimePermissions(packageName, LOCATION_PERMISSIONS, true, userId);
+ revokeRuntimePermissions(packageName, ALWAYS_LOCATION_PERMISSIONS, true, userId);
}
}
}
@@ -889,7 +884,7 @@
public void grantDefaultPermissionsToDefaultBrowser(String packageName, int userId) {
Log.i(TAG, "Granting permissions to default browser for user:" + userId);
- grantPermissionsToSystemPackage(packageName, userId, LOCATION_PERMISSIONS);
+ grantPermissionsToSystemPackage(packageName, userId, ALWAYS_LOCATION_PERMISSIONS);
}
private String getDefaultSystemHandlerActivityPackage(String intentAction, int userId) {
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 561b111..890a3c3 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1904,14 +1904,15 @@
return Boolean.TRUE == granted;
}
- private boolean isPermissionsReviewRequired(PackageParser.Package pkg, int userId) {
+ private boolean isPermissionsReviewRequired(@NonNull PackageParser.Package pkg,
+ @UserIdInt int userId) {
// Permission review applies only to apps not supporting the new permission model.
if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M) {
return false;
}
// Legacy apps have the permission and get user consent on launch.
- if (pkg == null || pkg.mExtras == null) {
+ if (pkg.mExtras == null) {
return false;
}
final PackageSetting ps = (PackageSetting) pkg.mExtras;
@@ -2142,7 +2143,7 @@
}
if (bp.isSoftRestricted() && !SoftRestrictedPermissionPolicy.forPermission(mContext,
- pkg.applicationInfo, permName).canBeGranted()) {
+ pkg.applicationInfo, UserHandle.of(userId), permName).canBeGranted()) {
Log.e(TAG, "Cannot grant soft restricted permission " + permName + " for package "
+ packageName);
return;
@@ -3111,7 +3112,7 @@
PermissionManagerService.this.systemReady();
}
@Override
- public boolean isPermissionsReviewRequired(Package pkg, int userId) {
+ public boolean isPermissionsReviewRequired(@NonNull Package pkg, @UserIdInt int userId) {
return PermissionManagerService.this.isPermissionsReviewRequired(pkg, userId);
}
@Override
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index fc92a77..98781e8 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.PermissionInfoFlags;
import android.content.pm.PackageParser;
@@ -65,7 +66,8 @@
public abstract void systemReady();
- public abstract boolean isPermissionsReviewRequired(PackageParser.Package pkg, int userId);
+ public abstract boolean isPermissionsReviewRequired(@NonNull PackageParser.Package pkg,
+ @UserIdInt int userId);
public abstract void grantRuntimePermission(
@NonNull String permName, @NonNull String packageName, boolean overridePolicy,
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 6882afb..93b11bef 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -414,7 +414,7 @@
} else if (permissionInfo.isSoftRestricted()) {
final SoftRestrictedPermissionPolicy policy =
SoftRestrictedPermissionPolicy.forPermission(mContext, pkg.applicationInfo,
- permission);
+ mContext.getUser(), permission);
if (opCode != OP_NONE) {
if (policy.canBeGranted()) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 19560c8..74ab2a9 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -107,6 +107,7 @@
import android.app.ActivityTaskManager;
import android.app.AppOpsManager;
import android.app.IUiModeManager;
+import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.app.UiModeManager;
@@ -2565,6 +2566,10 @@
return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
}
+ NotificationManager getNotificationService() {
+ return mContext.getSystemService(NotificationManager.class);
+ }
+
static IAudioService getAudioService() {
IAudioService audioService = IAudioService.Stub.asInterface(
ServiceManager.checkService(Context.AUDIO_SERVICE));
@@ -3799,6 +3804,11 @@
if (down) {
sendSystemKeyToStatusBarAsync(event.getKeyCode());
+ NotificationManager nm = getNotificationService();
+ if (nm != null && !mHandleVolumeKeysInWM) {
+ nm.silenceNotificationSound();
+ }
+
TelecomManager telecomManager = getTelecommService();
if (telecomManager != null && !mHandleVolumeKeysInWM) {
// When {@link #mHandleVolumeKeysInWM} is set, volume key events
@@ -5199,6 +5209,11 @@
awakenDreams();
}
+ if (!isUserSetupComplete()) {
+ Slog.i(TAG, "Not going home because user setup is in progress.");
+ return;
+ }
+
// Start dock.
Intent dock = createHomeDockIntent();
if (dock != null) {
diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
index d447617..90e0dc4 100644
--- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
+++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
@@ -33,6 +33,7 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Build;
+import android.os.UserHandle;
/**
* The behavior of soft restricted permissions is different for each permission. This class collects
@@ -75,12 +76,14 @@
*
* @param context A context to use
* @param appInfo The application the permission belongs to
+ * @param user The user the app belongs to
* @param permission The name of the permission
*
* @return The policy for this permission
*/
public static @NonNull SoftRestrictedPermissionPolicy forPermission(@NonNull Context context,
- @NonNull ApplicationInfo appInfo, @NonNull String permission) {
+ @NonNull ApplicationInfo appInfo, @NonNull UserHandle user,
+ @NonNull String permission) {
switch (permission) {
// Storage uses a special app op to decide the mount state and supports soft restriction
// where the restricted state allows the permission but only for accessing the medial
@@ -88,7 +91,7 @@
case READ_EXTERNAL_STORAGE:
case WRITE_EXTERNAL_STORAGE: {
int flags = context.getPackageManager().getPermissionFlags(
- permission, appInfo.packageName, context.getUser());
+ permission, appInfo.packageName, user);
boolean applyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;
boolean isWhiteListed = (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
boolean hasRequestedLegacyExternalStorage =
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index b81d969..edf0cbf 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -91,7 +91,6 @@
private static final int MSG_USER_ACTIVITY = 1;
private static final int MSG_BROADCAST = 2;
private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
- private static final int MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED = 4;
private static final int MSG_PROFILE_TIMED_OUT = 5;
private static final int MSG_WIRED_CHARGING_STARTED = 6;
@@ -127,7 +126,6 @@
private final NotifierHandler mHandler;
private final Intent mScreenOnIntent;
private final Intent mScreenOffIntent;
- private final Intent mScreenBrightnessBoostIntent;
// True if the device should suspend when the screen is off due to proximity.
private final boolean mSuspendWhenScreenOffDueToProximityConfig;
@@ -181,10 +179,6 @@
mScreenOffIntent.addFlags(
Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND
| Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
- mScreenBrightnessBoostIntent =
- new Intent(PowerManager.ACTION_SCREEN_BRIGHTNESS_BOOST_CHANGED);
- mScreenBrightnessBoostIntent.addFlags(
- Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
mSuspendWhenScreenOffDueToProximityConfig = context.getResources().getBoolean(
com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity);
@@ -560,20 +554,6 @@
}
/**
- * Called when screen brightness boost begins or ends.
- */
- public void onScreenBrightnessBoostChanged() {
- if (DEBUG) {
- Slog.d(TAG, "onScreenBrightnessBoostChanged");
- }
-
- mSuspendBlocker.acquire();
- Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED);
- msg.setAsynchronous(true);
- mHandler.sendMessage(msg);
- }
-
- /**
* Called when there has been user activity.
*/
public void onUserActivity(int event, int uid) {
@@ -729,22 +709,6 @@
}
}
- private void sendBrightnessBoostChangedBroadcast() {
- if (DEBUG) {
- Slog.d(TAG, "Sending brightness boost changed broadcast.");
- }
-
- mContext.sendOrderedBroadcastAsUser(mScreenBrightnessBoostIntent, UserHandle.ALL, null,
- mScreeBrightnessBoostChangedDone, mHandler, 0, null, null);
- }
-
- private final BroadcastReceiver mScreeBrightnessBoostChangedDone = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- mSuspendBlocker.release();
- }
- };
-
private void sendWakeUpBroadcast() {
if (DEBUG) {
Slog.d(TAG, "Sending wake up broadcast.");
@@ -861,9 +825,6 @@
case MSG_WIRELESS_CHARGING_STARTED:
showWirelessChargingStarted(msg.arg1, msg.arg2);
break;
- case MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED:
- sendBrightnessBoostChangedBroadcast();
- break;
case MSG_PROFILE_TIMED_OUT:
lockProfile(msg.arg1);
break;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index cfd3ae6..d599441 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -2516,7 +2516,6 @@
}
}
mScreenBrightnessBoostInProgress = false;
- mNotifier.onScreenBrightnessBoostChanged();
userActivityNoUpdateLocked(now,
PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
}
@@ -3123,10 +3122,7 @@
Slog.i(TAG, "Brightness boost activated (uid " + uid +")...");
mLastScreenBrightnessBoostTime = eventTime;
- if (!mScreenBrightnessBoostInProgress) {
- mScreenBrightnessBoostInProgress = true;
- mNotifier.onScreenBrightnessBoostChanged();
- }
+ mScreenBrightnessBoostInProgress = true;
mDirty |= DIRTY_SCREEN_BRIGHTNESS_BOOST;
userActivityNoUpdateLocked(eventTime,
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 63439d5..1134853 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -1254,6 +1254,12 @@
pulledData.add(e);
}
+ private void pullProcessSystemIonHeapSize(
+ int tagId, long elapsedNanos, long wallClockNanos,
+ List<StatsLogEventWrapper> pulledData) {
+ // TODO(b/130526489): Read from debugfs.
+ }
+
private void pullBinderCallsStats(
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
@@ -2317,6 +2323,10 @@
pullSystemIonHeapSize(tagId, elapsedNanos, wallClockNanos, ret);
break;
}
+ case StatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE: {
+ pullProcessSystemIonHeapSize(tagId, elapsedNanos, wallClockNanos, ret);
+ break;
+ }
case StatsLog.BINDER_CALLS: {
pullBinderCallsStats(tagId, elapsedNanos, wallClockNanos, ret);
break;
diff --git a/services/core/java/com/android/server/utils/TimingsTraceAndSlog.java b/services/core/java/com/android/server/utils/TimingsTraceAndSlog.java
index 704881a..03c96e9 100644
--- a/services/core/java/com/android/server/utils/TimingsTraceAndSlog.java
+++ b/services/core/java/com/android/server/utils/TimingsTraceAndSlog.java
@@ -33,11 +33,25 @@
/**
* Tag for timing measurement of non-main asynchronous operations.
*/
- public static final String SYSTEM_SERVER_TIMING_ASYNC_TAG = SYSTEM_SERVER_TIMING_TAG + "Async";
+ private static final String SYSTEM_SERVER_TIMING_ASYNC_TAG = SYSTEM_SERVER_TIMING_TAG + "Async";
+
+ /**
+ * Set this to a positive value to get a {@Slog.w} log for any trace that took longer than it.
+ */
+ private static final long BOTTLENECK_DURATION_MS = -1;
private final String mTag;
/**
+ * Creates a new {@link TimingsTraceAndSlog} for async operations.
+ */
+ @NonNull
+ public static TimingsTraceAndSlog newAsyncLog() {
+ return new TimingsTraceAndSlog(SYSTEM_SERVER_TIMING_ASYNC_TAG,
+ Trace.TRACE_TAG_SYSTEM_SERVER);
+ }
+
+ /**
* Default constructor using {@code system_server} tags.
*/
public TimingsTraceAndSlog() {
@@ -60,4 +74,17 @@
Slog.i(mTag, name);
super.traceBegin(name);
}
+
+ @Override
+ public void logDuration(String name, long timeMs) {
+ super.logDuration(name, timeMs);
+ if (BOTTLENECK_DURATION_MS > 0 && timeMs >= BOTTLENECK_DURATION_MS) {
+ Slog.w(mTag, "Slow duration for " + name + ": " + timeMs + "ms");
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "TimingsTraceAndSlog[" + mTag + "]";
+ }
}
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index feef5e2..bc0f747 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -544,14 +544,30 @@
// If we have an active transition that's waiting on a certain activity that will be
// invisible now, we'll never get onWindowsDrawn, so abort the transition if necessary.
- if (info != null && !hasVisibleNonFinishingActivity(t)) {
- if (DEBUG_METRICS) Slog.i(TAG, "notifyVisibilityChanged to invisible"
- + " activity=" + r);
- logAppTransitionCancel(info);
- mWindowingModeTransitionInfo.remove(r.getWindowingMode());
- if (mWindowingModeTransitionInfo.size() == 0) {
- reset(true /* abort */, info, "notifyVisibilityChanged to invisible");
- }
+
+ // We have no active transitions.
+ if (info == null) {
+ return;
+ }
+
+ // The notified activity whose visibility changed is no longer the launched activity.
+ // We can still wait to get onWindowsDrawn.
+ if (info.launchedActivity != r) {
+ return;
+ }
+
+ // Check if there is any activity in the task that is visible and not finishing. If the
+ // launched activity finished before it is drawn and if there is another activity in
+ // the task then that activity will be draw on screen.
+ if (hasVisibleNonFinishingActivity(t)) {
+ return;
+ }
+
+ if (DEBUG_METRICS) Slog.i(TAG, "notifyVisibilityChanged to invisible activity=" + r);
+ logAppTransitionCancel(info);
+ mWindowingModeTransitionInfo.remove(r.getWindowingMode());
+ if (mWindowingModeTransitionInfo.size() == 0) {
+ reset(true /* abort */, info, "notifyVisibilityChanged to invisible");
}
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 1344727..0faea61 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2039,6 +2039,13 @@
mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
WindowVisibilityItem.obtain(true /* showWindow */));
makeActiveIfNeeded(null /* activeActivity*/);
+ if (isState(STOPPING, STOPPED) && isFocusable()) {
+ // #shouldMakeActive() only evaluates the topmost activities in task, so
+ // activities that are not the topmost in task are not being resumed or paused.
+ // For activities that are still in STOPPING or STOPPED state, updates the state
+ // to PAUSE at least when making it visible.
+ setState(PAUSED, "makeClientVisible");
+ }
} catch (Exception e) {
Slog.w(TAG, "Exception thrown sending visibility update: " + intent.getComponent(), e);
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index f76d0eb..cf4f0a6 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -246,7 +246,6 @@
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.AttributeCache;
-import com.android.server.DeviceIdleController;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
@@ -434,9 +433,6 @@
private static final long START_AS_CALLER_TOKEN_EXPIRED_TIMEOUT =
START_AS_CALLER_TOKEN_TIMEOUT_IMPL + 20 * MINUTE_IN_MILLIS;
- // How long to whitelist the Services for when requested.
- private static final int SERVICE_LAUNCH_IDLE_WHITELIST_DURATION_MS = 5 * 1000;
-
// Activity tokens of system activities that are delegating their call to
// #startActivityByCaller, keyed by the permissionToken granted to the delegate.
final HashMap<IBinder, IBinder> mStartActivitySources = new HashMap<>();
@@ -3079,9 +3075,9 @@
try {
if (TextUtils.equals(pae.intent.getAction(),
android.service.voice.VoiceInteractionService.SERVICE_INTERFACE)) {
- pae.intent.putExtras(pae.extras);
-
- startVoiceInteractionServiceAsUser(pae.intent, pae.userHandle, "AssistContext");
+ // Start voice interaction through VoiceInteractionManagerService.
+ mAssistUtils.showSessionForActiveService(sendBundle, SHOW_SOURCE_APPLICATION,
+ null, null);
} else {
pae.intent.replaceExtras(pae.extras);
pae.intent.setFlags(FLAG_ACTIVITY_NEW_TASK
@@ -3100,34 +3096,6 @@
}
}
- /**
- * Workaround for historical API which starts the Assist service with a non-foreground
- * {@code startService()} call.
- */
- private void startVoiceInteractionServiceAsUser(
- Intent intent, int userHandle, String reason) {
- // Resolve the intent to find out which package we need to whitelist.
- ResolveInfo resolveInfo =
- mContext.getPackageManager().resolveServiceAsUser(intent, 0, userHandle);
- if (resolveInfo == null || resolveInfo.serviceInfo == null) {
- Slog.e(TAG, "VoiceInteractionService intent does not resolve. Not starting.");
- return;
- }
- intent.setPackage(resolveInfo.serviceInfo.packageName);
-
- // Whitelist background services temporarily.
- LocalServices.getService(DeviceIdleController.LocalService.class)
- .addPowerSaveTempWhitelistApp(Process.myUid(), intent.getPackage(),
- SERVICE_LAUNCH_IDLE_WHITELIST_DURATION_MS, userHandle, false, reason);
-
- // Finally, try to start the service.
- try {
- mContext.startServiceAsUser(intent, UserHandle.of(userHandle));
- } catch (RuntimeException e) {
- Slog.e(TAG, "VoiceInteractionService failed to start.", e);
- }
- }
-
@Override
public int addAppTask(IBinder activityToken, Intent intent,
ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException {
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 19ccc62..b6af939 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -88,6 +88,7 @@
import android.content.res.ResourceId;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
+import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -259,6 +260,8 @@
private final boolean mGridLayoutRecentsEnabled;
private final boolean mLowRamRecentsEnabled;
+ private final int mDefaultWindowAnimationStyleResId;
+
private RemoteAnimationController mRemoteAnimationController;
final Handler mHandler;
@@ -306,6 +309,12 @@
* mContext.getResources().getDisplayMetrics().density);
mGridLayoutRecentsEnabled = SystemProperties.getBoolean("ro.recents.grid", false);
mLowRamRecentsEnabled = ActivityManager.isLowRamDeviceStatic();
+
+ final TypedArray windowStyle = mContext.getTheme().obtainStyledAttributes(
+ com.android.internal.R.styleable.Window);
+ mDefaultWindowAnimationStyleResId = windowStyle.getResourceId(
+ com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
+ windowStyle.recycle();
}
boolean isTransitionSet() {
@@ -524,6 +533,25 @@
return redoLayout;
}
+ @VisibleForTesting
+ int getDefaultWindowAnimationStyleResId() {
+ return mDefaultWindowAnimationStyleResId;
+ }
+
+ /** Returns window animation style ID from {@link LayoutParams} or from system in some cases */
+ @VisibleForTesting
+ int getAnimationStyleResId(@NonNull LayoutParams lp) {
+ int resId = lp.windowAnimations;
+ if (lp.type == LayoutParams.TYPE_APPLICATION_STARTING) {
+ // Note that we don't want application to customize starting window animation.
+ // Since this window is specific for displaying while app starting,
+ // application should not change its animation directly.
+ // In this case, it will use system resource to get default animation.
+ resId = mDefaultWindowAnimationStyleResId;
+ }
+ return resId;
+ }
+
private AttributeCache.Entry getCachedAnimations(LayoutParams lp) {
if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg="
+ (lp != null ? lp.packageName : null)
@@ -533,7 +561,7 @@
// application resources. It is nice to avoid loading application
// resources if we can.
String packageName = lp.packageName != null ? lp.packageName : "android";
- int resId = lp.windowAnimations;
+ int resId = getAnimationStyleResId(lp);
if ((resId&0xFF000000) == 0x01000000) {
packageName = "android";
}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 9189279..be3b924 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -79,6 +79,7 @@
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
import static com.android.server.wm.WindowManagerService.logWithStack;
import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
+import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
@@ -540,6 +541,14 @@
// If the app was already visible, don't reset the waitingToShow state.
if (isHidden()) {
waitingToShow = true;
+
+ // Let's reset the draw state in order to prevent the starting window to be
+ // immediately dismissed when the app still has the surface.
+ forAllWindows(w -> {
+ if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
+ w.mWinAnimator.resetDrawState();
+ }
+ }, true /* traverseTopToBottom */);
}
}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index d3dba90..2eec926 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -321,11 +321,10 @@
}
void updateInputWindowsImmediately() {
- if (mUpdateInputWindowsPending) {
- mApplyImmediately = true;
- mUpdateInputWindows.run();
- mApplyImmediately = false;
- }
+ mHandler.removeCallbacks(mUpdateInputWindows);
+ mApplyImmediately = true;
+ mUpdateInputWindows.run();
+ mApplyImmediately = false;
}
/* Called when the current input focus changes.
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index e0ab722..541a8bb 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -308,11 +308,13 @@
*/
@VisibleForTesting
void resetFreezeTaskListReorderingOnTimeout() {
- final ActivityStack focusedStack = mService.getTopDisplayFocusedStack();
- final TaskRecord topTask = focusedStack != null
- ? focusedStack.topTask()
- : null;
- resetFreezeTaskListReordering(topTask);
+ synchronized (mService.mGlobalLock) {
+ final ActivityStack focusedStack = mService.getTopDisplayFocusedStack();
+ final TaskRecord topTask = focusedStack != null
+ ? focusedStack.topTask()
+ : null;
+ resetFreezeTaskListReordering(topTask);
+ }
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index ecb0941..8d1cc71 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -28,6 +28,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.annotation.Nullable;
import android.content.ClipData;
import android.graphics.Rect;
import android.graphics.Region;
@@ -225,10 +226,11 @@
}
@Override
- public void finishDrawing(IWindow window) {
+ public void finishDrawing(IWindow window,
+ @Nullable SurfaceControl.Transaction postDrawTransaction) {
if (WindowManagerService.localLOGV) Slog.v(
TAG_WM, "IWindow finishDrawing called for " + window);
- mService.finishDrawingWindow(this, window);
+ mService.finishDrawingWindow(this, window, postDrawTransaction);
}
@Override
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 1815218..101c4b8 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -306,7 +306,8 @@
final boolean isWindowTranslucent = mainWindow.getAttrs().format != PixelFormat.OPAQUE;
return new TaskSnapshot(
appWindowToken.mActivityComponent, screenshotBuffer.getGraphicBuffer(),
- screenshotBuffer.getColorSpace(), appWindowToken.getConfiguration().orientation,
+ screenshotBuffer.getColorSpace(),
+ appWindowToken.getTask().getConfiguration().orientation,
getInsets(mainWindow), isLowRamDevice /* reduced */, scaleFraction /* scale */,
true /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
!appWindowToken.fillsParent() || isWindowTranslucent);
@@ -379,8 +380,8 @@
final LayoutParams attrs = mainWindow.getAttrs();
final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
attrs.privateFlags, attrs.systemUiVisibility, task.getTaskDescription());
- final int width = mainWindow.getFrameLw().width();
- final int height = mainWindow.getFrameLw().height();
+ final int width = task.getBounds().width();
+ final int height = task.getBounds().height();
final RenderNode node = RenderNode.create("TaskSnapshotController", null);
node.setLeftTopRightBottom(0, 0, width, height);
@@ -394,11 +395,12 @@
if (hwBitmap == null) {
return null;
}
+
// Note, the app theme snapshot is never translucent because we enforce a non-translucent
// color above
return new TaskSnapshot(topChild.mActivityComponent, hwBitmap.createGraphicBufferHandle(),
- hwBitmap.getColorSpace(), topChild.getConfiguration().orientation,
- mainWindow.getStableInsets(), ActivityManager.isLowRamDeviceStatic() /* reduced */,
+ hwBitmap.getColorSpace(), topChild.getTask().getConfiguration().orientation,
+ getInsets(mainWindow), ActivityManager.isLowRamDeviceStatic() /* reduced */,
1.0f /* scale */, false /* isRealSnapshot */, task.getWindowingMode(),
getSystemUiVisibility(task), false);
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 5d99db5..306e7f4 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -418,7 +418,7 @@
private void reportDrawn() {
try {
- mSession.finishDrawing(mWindow);
+ mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
} catch (RemoteException e) {
// Local call.
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9d8b04e..10f0922 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -100,6 +100,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerServiceDumpProto.DISPLAY_FROZEN;
import static com.android.server.wm.WindowManagerServiceDumpProto.FOCUSED_APP;
+import static com.android.server.wm.WindowManagerServiceDumpProto.FOCUSED_DISPLAY_ID;
import static com.android.server.wm.WindowManagerServiceDumpProto.FOCUSED_WINDOW;
import static com.android.server.wm.WindowManagerServiceDumpProto.INPUT_METHOD_WINDOW;
import static com.android.server.wm.WindowManagerServiceDumpProto.LAST_ORIENTATION;
@@ -2356,14 +2357,15 @@
}
}
- void finishDrawingWindow(Session session, IWindow client) {
+ void finishDrawingWindow(Session session, IWindow client,
+ @Nullable SurfaceControl.Transaction postDrawTransaction) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
WindowState win = windowForClientLocked(session, client, false);
if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "finishDrawingWindow: " + win + " mDrawState="
+ (win != null ? win.mWinAnimator.drawStateToString() : "null"));
- if (win != null && win.mWinAnimator.finishDrawingLocked()) {
+ if (win != null && win.mWinAnimator.finishDrawingLocked(postDrawTransaction)) {
if ((win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
win.getDisplayContent().pendingLayoutChanges |=
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
@@ -5929,6 +5931,7 @@
final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
proto.write(ROTATION, defaultDisplayContent.getRotation());
proto.write(LAST_ORIENTATION, defaultDisplayContent.getLastOrientation());
+ proto.write(FOCUSED_DISPLAY_ID, topFocusedDisplayContent.getDisplayId());
}
private void dumpWindowsLocked(PrintWriter pw, boolean dumpAll,
@@ -7629,22 +7632,30 @@
@Override
public boolean injectInputAfterTransactionsApplied(InputEvent ev, int mode) {
- boolean shouldWaitForAnimToComplete = false;
+ boolean isDown;
+ boolean isUp;
+
if (ev instanceof KeyEvent) {
KeyEvent keyEvent = (KeyEvent) ev;
- shouldWaitForAnimToComplete = keyEvent.getSource() == InputDevice.SOURCE_MOUSE
- || keyEvent.getAction() == KeyEvent.ACTION_DOWN;
- } else if (ev instanceof MotionEvent) {
+ isDown = keyEvent.getAction() == KeyEvent.ACTION_DOWN;
+ isUp = keyEvent.getAction() == KeyEvent.ACTION_UP;
+ } else {
MotionEvent motionEvent = (MotionEvent) ev;
- shouldWaitForAnimToComplete = motionEvent.getSource() == InputDevice.SOURCE_MOUSE
- || motionEvent.getAction() == MotionEvent.ACTION_DOWN;
+ isDown = motionEvent.getAction() == MotionEvent.ACTION_DOWN;
+ isUp = motionEvent.getAction() == MotionEvent.ACTION_UP;
}
- if (shouldWaitForAnimToComplete) {
+ // For ACTION_DOWN, syncInputTransactions before injecting input.
+ // For ACTION_UP, sync after injecting.
+ if (isDown) {
syncInputTransactions();
}
-
- return LocalServices.getService(InputManagerInternal.class).injectInputEvent(ev, mode);
+ final boolean result =
+ LocalServices.getService(InputManagerInternal.class).injectInputEvent(ev, mode);
+ if (isUp) {
+ syncInputTransactions();
+ }
+ return result;
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 84a6722..d1ddbfe 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2093,6 +2093,13 @@
return false;
}
+ final TaskStack stack = getStack();
+ if (stack != null && stack.shouldIgnoreInput()) {
+ // Ignore when the stack shouldn't receive input event.
+ // (i.e. the minimized stack in split screen mode.)
+ return false;
+ }
+
final int fl = mAttrs.flags & (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);
final int type = mAttrs.type;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 10a63ee9..4cd6731 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -20,6 +20,7 @@
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;
@@ -219,7 +220,16 @@
private final Rect mTmpSize = new Rect();
- private final SurfaceControl.Transaction mReparentTransaction = new SurfaceControl.Transaction();
+ /**
+ * Handles surface changes synchronized to after the client has drawn the surface. This
+ * transaction is currently used to reparent the old surface children to the new surface once
+ * the client has completed drawing to the new surface.
+ * This transaction is also used to merge transactions parceled in by the client. The client
+ * uses the transaction to update the relative z of its children from the old parent surface
+ * to the new parent surface once window manager reparents its children.
+ */
+ private final SurfaceControl.Transaction mPostDrawTransaction =
+ new SurfaceControl.Transaction();
// Used to track whether we have called detach children on the way to invisibility, in which
// case we need to give the client a new Surface if it lays back out to a visible state.
@@ -300,7 +310,7 @@
SurfaceControl.mergeToGlobalTransaction(mTmpTransaction);
}
- boolean finishDrawingLocked() {
+ boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction) {
final boolean startingWindow =
mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
if (DEBUG_STARTING_WINDOW && startingWindow) {
@@ -320,6 +330,9 @@
mDrawState = COMMIT_DRAW_PENDING;
layoutNeeded = true;
}
+ if (postDrawTransaction != null) {
+ mPostDrawTransaction.merge(postDrawTransaction);
+ }
return layoutNeeded;
}
@@ -384,7 +397,7 @@
// child layers need to be reparented to the new surface to make this
// transparent to the app.
if (mWin.mAppToken == null || mWin.mAppToken.isRelaunching() == false) {
- mReparentTransaction.reparentChildren(mPendingDestroySurface.mSurfaceControl,
+ mPostDrawTransaction.reparentChildren(mPendingDestroySurface.mSurfaceControl,
mSurfaceController.mSurfaceControl.getHandle())
.apply();
}
@@ -1149,7 +1162,7 @@
// LogicalDisplay.
mAnimator.setPendingLayoutChanges(w.getDisplayId(),
FINISH_LAYOUT_REDO_ANIM);
- if (DEBUG_LAYOUT_REPEATS) {
+ if (DEBUG_LAYOUT_REPEATS) {
mService.mWindowPlacerLocked.debugLayoutRepeats(
"showSurfaceRobustlyLocked " + w,
mAnimator.getPendingLayoutChanges(w.getDisplayId()));
@@ -1280,10 +1293,13 @@
// If we had a preserved surface it's no longer needed, and it may be harmful
// if we are transparent.
if (mPendingDestroySurface != null && mDestroyPreservedSurfaceUponRedraw) {
- mPendingDestroySurface.mSurfaceControl.hide();
- mPendingDestroySurface.reparentChildrenInTransaction(mSurfaceController);
+ final SurfaceControl pendingSurfaceControl = mPendingDestroySurface.mSurfaceControl;
+ mPostDrawTransaction.hide(pendingSurfaceControl);
+ mPostDrawTransaction.reparentChildren(pendingSurfaceControl,
+ mSurfaceController.getHandle());
}
+ mPostDrawTransaction.apply();
return true;
}
@@ -1294,6 +1310,13 @@
if (mWin.mSkipEnterAnimationForSeamlessReplacement) {
return;
}
+
+ // We don't apply animation for application main window here since this window type
+ // should be controlled by AppWindowToken in general.
+ if (mAttrType == TYPE_BASE_APPLICATION) {
+ return;
+ }
+
final int transit;
if (mEnterAnimationPending) {
mEnterAnimationPending = false;
@@ -1365,6 +1388,7 @@
+ " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
+ " a=" + a
+ " transit=" + transit
+ + " type=" + mAttrType
+ " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3));
if (a != null) {
if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index ba59cdb..8b61208 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -6443,7 +6443,7 @@
.setAdmin(admin)
.setStrings(vpnPackage)
.setBoolean(lockdown)
- .setInt(/* number of vpn packages */ 0)
+ .setInt(lockdownWhitelist != null ? lockdownWhitelist.size() : 0)
.write();
} finally {
mInjector.binderRestoreCallingIdentity(token);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0b75797..3ec8b2e 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -22,7 +22,6 @@
import static android.os.IServiceManager.DUMP_FLAG_PROTO;
import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.server.utils.TimingsTraceAndSlog.SYSTEM_SERVER_TIMING_ASYNC_TAG;
import static com.android.server.utils.TimingsTraceAndSlog.SYSTEM_SERVER_TIMING_TAG;
import android.annotation.NonNull;
@@ -57,7 +56,6 @@
import android.os.StrictMode;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.os.Trace;
import android.os.UserHandle;
import android.os.storage.IStorageManager;
import android.provider.DeviceConfig;
@@ -619,6 +617,8 @@
* initialized in one of the other functions.
*/
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
+ t.traceBegin("startBootstrapServices");
+
// Start the watchdog as early as possible so we can crash the system server
// if we deadlock during early boot
t.traceBegin("StartWatchdog");
@@ -710,7 +710,7 @@
// We need the default display before we can initialize the package manager.
t.traceBegin("WaitForDisplay");
- mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
+ mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
t.traceEnd();
// Only run "core" apps if we're encrypting the device.
@@ -728,9 +728,16 @@
MetricsLogger.histogram(null, "boot_package_manager_init_start",
(int) SystemClock.elapsedRealtime());
}
+
t.traceBegin("StartPackageManagerService");
- mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
- mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
+ try {
+ Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");
+ mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
+ mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
+ } finally {
+ Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
+ }
+
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
t.traceEnd();
@@ -802,18 +809,21 @@
// Start sensor service in a separate thread. Completion should be checked
// before using it.
mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {
- TimingsTraceAndSlog traceLog = new TimingsTraceAndSlog(
- SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
+ TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
traceLog.traceBegin(START_SENSOR_SERVICE);
startSensorService();
traceLog.traceEnd();
}, START_SENSOR_SERVICE);
+
+ t.traceEnd(); // startBootstrapServices
}
/**
* Starts some essential services that are not tangled up in the bootstrap process.
*/
private void startCoreServices(@NonNull TimingsTraceAndSlog t) {
+ t.traceBegin("startCoreServices");
+
t.traceBegin("StartBatteryService");
// Tracks the battery level. Requires LightService.
mSystemServiceManager.startService(BatteryService.class);
@@ -862,12 +872,16 @@
t.traceBegin("GpuService");
mSystemServiceManager.startService(GpuService.class);
t.traceEnd();
+
+ t.traceEnd(); // startCoreServices
}
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
*/
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
+ t.traceBegin("startOtherServices");
+
final Context context = mSystemContext;
VibratorService vibrator = null;
DynamicSystemService dynamicSystem = null;
@@ -922,8 +936,7 @@
mZygotePreload = SystemServerInitThreadPool.get().submit(() -> {
try {
Slog.i(TAG, SECONDARY_ZYGOTE_PRELOAD);
- TimingsTraceAndSlog traceLog = new TimingsTraceAndSlog(
- SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
+ TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
traceLog.traceBegin(SECONDARY_ZYGOTE_PRELOAD);
if (!Process.ZYGOTE_PROCESS.preloadDefault(Build.SUPPORTED_32_BIT_ABIS[0])) {
Slog.e(TAG, "Unable to preload default resources");
@@ -1033,8 +1046,7 @@
// because it need to connect to SensorManager. This have to start
// after START_SENSOR_SERVICE is done.
SystemServerInitThreadPool.get().submit(() -> {
- TimingsTraceAndSlog traceLog = new TimingsTraceAndSlog(
- SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
+ TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
traceLog.traceBegin(START_HIDL_SERVICES);
startHidlServices();
traceLog.traceEnd();
@@ -1923,11 +1935,11 @@
// Needed by DevicePolicyManager for initialization
t.traceBegin("StartBootPhaseLockSettingsReady");
- mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
+ mSystemServiceManager.startBootPhase(t, SystemService.PHASE_LOCK_SETTINGS_READY);
t.traceEnd();
t.traceBegin("StartBootPhaseSystemServicesReady");
- mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
+ mSystemServiceManager.startBootPhase(t, SystemService.PHASE_SYSTEM_SERVICES_READY);
t.traceEnd();
t.traceBegin("MakeWindowManagerServiceReady");
@@ -1997,7 +2009,7 @@
t.traceEnd();
t.traceBegin("StartBootPhaseDeviceSpecificServicesReady");
- mSystemServiceManager.startBootPhase(SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);
+ mSystemServiceManager.startBootPhase(t, SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);
t.traceEnd();
// Permission policy service
@@ -2028,8 +2040,7 @@
mActivityManagerService.systemReady(() -> {
Slog.i(TAG, "Making services ready");
t.traceBegin("StartActivityManagerReadyPhase");
- mSystemServiceManager.startBootPhase(
- SystemService.PHASE_ACTIVITY_MANAGER_READY);
+ mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY);
t.traceEnd();
t.traceBegin("StartObservingNativeCrashes");
try {
@@ -2046,8 +2057,7 @@
if (!mOnlyCore && mWebViewUpdateService != null) {
webviewPrep = SystemServerInitThreadPool.get().submit(() -> {
Slog.i(TAG, WEBVIEW_PREPARATION);
- TimingsTraceAndSlog traceLog = new TimingsTraceAndSlog(
- SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
+ TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
traceLog.traceBegin(WEBVIEW_PREPARATION);
ConcurrentUtils.waitForFutureNoInterrupt(mZygotePreload, "Zygote preload");
mZygotePreload = null;
@@ -2144,8 +2154,7 @@
if (webviewPrep != null) {
ConcurrentUtils.waitForFutureNoInterrupt(webviewPrep, WEBVIEW_PREPARATION);
}
- mSystemServiceManager.startBootPhase(
- SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
+ mSystemServiceManager.startBootPhase(t, SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
t.traceEnd();
t.traceBegin("StartNetworkStack");
@@ -2240,6 +2249,8 @@
}
t.traceEnd();
}, t);
+
+ t.traceEnd(); // startOtherServices
}
private void startSystemCaptionsManagerService(@NonNull Context context,
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index 99da637..56b728c 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -486,7 +486,9 @@
private void requestConnector(@NonNull NetworkStackCallback request) {
// TODO: PID check.
final int caller = Binder.getCallingUid();
- if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)
+ if (caller != Process.SYSTEM_UID
+ && caller != Process.NETWORK_STACK_UID
+ && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)
&& !UserHandle.isSameApp(caller, Process.PHONE_UID)) {
// Don't even attempt to obtain the connector and give a nice error message
throw new SecurityException(
diff --git a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
index 0cb21d0..be93d6ba 100644
--- a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -21,7 +21,6 @@
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.PACKAGE_USAGE_STATS;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThread;
import static com.android.server.backup.testing.TransportData.backupTransport;
import static com.google.common.truth.Truth.assertThat;
@@ -133,8 +132,7 @@
() ->
new BackupManagerService(
/* context */ null,
- new Trampoline(mContext),
- startBackupThread(null)));
+ new Trampoline(mContext)));
}
/** Test that the constructor handles {@code null} parameters. */
@@ -144,17 +142,7 @@
NullPointerException.class,
() ->
new BackupManagerService(
- mContext, /* trampoline */ null, startBackupThread(null)));
- }
-
- /** Test that the constructor handles {@code null} parameters. */
- @Test
- public void testConstructor_withNullBackupThread_throws() throws Exception {
- expectThrows(
- NullPointerException.class,
- () ->
- new BackupManagerService(
- mContext, new Trampoline(mContext), /* backupThread */ null));
+ mContext, /* trampoline */ null));
}
/** Test that the service registers users. */
@@ -1581,8 +1569,7 @@
private BackupManagerService createService() {
mShadowContext.grantPermissions(BACKUP);
- return new BackupManagerService(
- mContext, new Trampoline(mContext), startBackupThread(null));
+ return new BackupManagerService(mContext, new Trampoline(mContext));
}
private BackupManagerService createServiceAndRegisterUser(
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index bdc46ec..ce1edcd 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -49,7 +49,6 @@
import static android.telephony.CarrierConfigManager.KEY_MONTHLY_DATA_CYCLE_DAY_INT;
import static android.telephony.SubscriptionPlan.BYTES_UNLIMITED;
import static android.telephony.SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED;
-import static android.text.format.Time.TIMEZONE_UTC;
import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_JOBS;
import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH;
@@ -128,7 +127,6 @@
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.MediumTest;
import android.text.TextUtils;
-import android.text.format.Time;
import android.util.DataUnit;
import android.util.Log;
import android.util.Pair;
@@ -184,6 +182,7 @@
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.TimeZone;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@@ -213,6 +212,7 @@
* Path on assets where files used by {@link NetPolicyXml} are located.
*/
private static final String NETPOLICY_DIR = "NetworkPolicyManagerServiceTest/netpolicy";
+ private static final String TIMEZONE_UTC = "UTC";
private BroadcastInterceptingContext mServiceContext;
private File mPolicyDir;
@@ -1796,7 +1796,7 @@
private static NetworkPolicy buildFakeMobilePolicy(int cycleDay, long warningBytes,
long limitBytes, boolean inferred) {
final NetworkTemplate template = buildTemplateMobileAll(FAKE_SUBSCRIBER_ID);
- return new NetworkPolicy(template, cycleDay, new Time().timezone, warningBytes,
+ return new NetworkPolicy(template, cycleDay, TimeZone.getDefault().getID(), warningBytes,
limitBytes, SNOOZE_NEVER, SNOOZE_NEVER, true, inferred);
}
diff --git a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
new file mode 100644
index 0000000..fc24f5e
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+package com.android.server.policy;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+
+import android.app.ActivityManager;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.wm.ActivityTaskManagerInternal;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test class for {@link PhoneWindowManager}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:PhoneWindowManagerTests
+ */
+@SmallTest
+public class PhoneWindowManagerTests {
+
+ PhoneWindowManager mPhoneWindowManager;
+
+ @Before
+ public void setUp() {
+ mPhoneWindowManager = spy(new PhoneWindowManager());
+ spyOn(ActivityManager.getService());
+ }
+
+ @After
+ public void tearDown() {
+ reset(ActivityManager.getService());
+ }
+
+ @Test
+ public void testShouldNotStartDockOrHomeWhenSetup() throws Exception {
+ mockStartDockOrHome();
+ doReturn(false).when(mPhoneWindowManager).isUserSetupComplete();
+
+ mPhoneWindowManager.startDockOrHome(
+ 0 /* displayId */, false /* fromHomeKey */, false /* awakenFromDreams */);
+
+ verify(mPhoneWindowManager, never()).createHomeDockIntent();
+ }
+
+ @Test
+ public void testShouldStartDockOrHomeAfterSetup() throws Exception {
+ mockStartDockOrHome();
+ doReturn(true).when(mPhoneWindowManager).isUserSetupComplete();
+
+ mPhoneWindowManager.startDockOrHome(
+ 0 /* displayId */, false /* fromHomeKey */, false /* awakenFromDreams */);
+
+ verify(mPhoneWindowManager).createHomeDockIntent();
+ }
+
+ private void mockStartDockOrHome() throws Exception {
+ doNothing().when(ActivityManager.getService()).stopAppSwitches();
+ ActivityTaskManagerInternal mMockActivityTaskManagerInternal =
+ mock(ActivityTaskManagerInternal.class);
+ when(mMockActivityTaskManagerInternal.startHomeOnDisplay(
+ anyInt(), anyString(), anyInt(), anyBoolean(), anyBoolean())).thenReturn(false);
+ mPhoneWindowManager.mActivityTaskManagerInternal = mMockActivityTaskManagerInternal;
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 11a177a..8fbb7f5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -31,6 +31,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
+import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
@@ -56,7 +57,6 @@
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
-import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.util.MergedConfiguration;
import android.util.MutableBoolean;
@@ -163,12 +163,10 @@
// Make sure the state does not change if we are not the current top activity.
mActivity.setState(STOPPED, "testPausingWhenVisibleFromStopped behind");
- // Make sure that the state does not change when we have an activity becoming translucent
final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
mStack.mTranslucentActivityWaiting = topActivity;
mActivity.makeVisibleIfNeeded(null /* starting */, true /* reportToClient */);
-
- assertTrue(mActivity.isState(STOPPED));
+ assertTrue(mActivity.isState(PAUSED));
}
private void ensureActivityConfiguration() {
@@ -439,6 +437,15 @@
}
@Test
+ public void testShouldPauseWhenMakeClientVisible() {
+ ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
+ topActivity.changeWindowTranslucency(false);
+ mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
+ mActivity.makeClientVisible();
+ assertEquals(PAUSED, mActivity.getState());
+ }
+
+ @Test
public void testSizeCompatMode_FixedAspectRatioBoundsWithDecor() {
setupDisplayContentForCompatDisplayInsets();
final int decorHeight = 200; // e.g. The device has cutout.
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 5a72a58..f602418 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -18,6 +18,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
@@ -45,6 +46,7 @@
import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
+import android.view.WindowManager;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
@@ -224,6 +226,21 @@
assertTrue(runner.mCancelled);
}
+ @Test
+ public void testGetAnimationStyleResId() {
+ // Verify getAnimationStyleResId will return as LayoutParams.windowAnimations when without
+ // specifying window type.
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams();
+ attrs.windowAnimations = 0x12345678;
+ assertEquals(attrs.windowAnimations, mDc.mAppTransition.getAnimationStyleResId(attrs));
+
+ // Verify getAnimationStyleResId will return system resource Id when the window type is
+ // starting window.
+ attrs.type = TYPE_APPLICATION_STARTING;
+ assertEquals(mDc.mAppTransition.getDefaultWindowAnimationStyleResId(),
+ mDc.mAppTransition.getAnimationStyleResId(attrs));
+ }
+
private class TestRemoteAnimationRunner implements IRemoteAnimationRunner {
boolean mCancelled = false;
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 3a8d3b7..1b57c792 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -18,6 +18,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90;
import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.Surface.ROTATION_0;
@@ -36,6 +37,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
@@ -249,6 +251,23 @@
// Invisible window can't be IME targets even if they have the right flags.
assertFalse(appWindow.canBeImeTarget());
assertFalse(imeWindow.canBeImeTarget());
+
+ // Simulate the window is in split screen primary stack and the current state is
+ // minimized and home stack is resizable, so that we should ignore input for the stack.
+ final DockedStackDividerController controller =
+ mDisplayContent.getDockedDividerController();
+ final TaskStack stack = createTaskStackOnDisplay(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
+ ACTIVITY_TYPE_STANDARD, mDisplayContent);
+ spyOn(appWindow);
+ spyOn(controller);
+ spyOn(stack);
+ doReturn(true).when(controller).isMinimizedDock();
+ doReturn(true).when(controller).isHomeStackResizable();
+ doReturn(stack).when(appWindow).getStack();
+
+ // Make sure canBeImeTarget is false due to shouldIgnoreInput is true;
+ assertFalse(appWindow.canBeImeTarget());
+ assertTrue(stack.shouldIgnoreInput());
}
@Test
diff --git a/startop/OWNERS b/startop/OWNERS
index 5cf9582..3394be9 100644
--- a/startop/OWNERS
+++ b/startop/OWNERS
@@ -4,3 +4,4 @@
iam@google.com
mathieuc@google.com
sehr@google.com
+yawanng@google.com
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index e5971b8..484fd3b 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -3078,18 +3078,10 @@
}
/**
- * Returns whether the subscription is enabled or not. This is different from activated
- * or deactivated for two aspects. 1) For when user disables a physical subscription, we
- * actually disable the modem because we can't switch off the subscription. 2) For eSIM,
- * user may enable one subscription but the system may activate another temporarily. In this
- * case, user enabled one is different from current active one.
-
- * @param subscriptionId The subscription it asks about.
- * @return whether it's enabled or not. {@code true} if user set this subscription enabled
- * earlier, or user never set subscription enable / disable on this slot explicitly, and
- * this subscription is currently active. Otherwise, it returns {@code false}.
- *
+ * DO NOT USE.
+ * This API is designed for features that are not finished at this point. Do not call this API.
* @hide
+ * TODO b/135547512: further clean up
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -3107,14 +3099,10 @@
}
/**
- * Get which subscription is enabled on this slot. See {@link #isSubscriptionEnabled(int)}
- * for more details.
- *
- * @param slotIndex which slot it asks about.
- * @return which subscription is enabled on this slot. If there's no enabled subscription
- * in this slot, it will return {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
- *
+ * DO NOT USE.
+ * This API is designed for features that are not finished at this point. Do not call this API.
* @hide
+ * TODO b/135547512: further clean up
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 9a0f3ca9..8517b769 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -4911,7 +4911,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return DATA_ACTIVITY_NONE;
- return telephony.getDataActivity();
+ return telephony.getDataActivity(
+ getSubId(SubscriptionManager.getActiveDataSubscriptionId()));
} catch (RemoteException ex) {
// the phone process is restarting.
return DATA_ACTIVITY_NONE;
@@ -4959,7 +4960,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return DATA_DISCONNECTED;
- return telephony.getDataState();
+ return telephony.getDataState(
+ getSubId(SubscriptionManager.getActiveDataSubscriptionId()));
} catch (RemoteException ex) {
// the phone process is restarting.
return DATA_DISCONNECTED;
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 5a27a0f..e23cd68 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -308,18 +308,36 @@
*/
List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg);
- @UnsupportedAppUsage
- int getCallState();
+ @UnsupportedAppUsage
+ int getCallState();
/**
* Returns the call state for a slot.
*/
int getCallStateForSlot(int slotIndex);
- @UnsupportedAppUsage
- int getDataActivity();
- @UnsupportedAppUsage
- int getDataState();
+ /**
+ * Returns a constant indicating the type of activity on a data connection
+ * (cellular).
+ *
+ * @see #DATA_ACTIVITY_NONE
+ * @see #DATA_ACTIVITY_IN
+ * @see #DATA_ACTIVITY_OUT
+ * @see #DATA_ACTIVITY_INOUT
+ * @see #DATA_ACTIVITY_DORMANT
+ */
+ int getDataActivity(int subId);
+
+ /**
+ * Returns a constant indicating the current data connection state
+ * (cellular).
+ *
+ * @see #DATA_DISCONNECTED
+ * @see #DATA_CONNECTING
+ * @see #DATA_CONNECTED
+ * @see #DATA_SUSPENDED
+ */
+ int getDataState(int subId);
/**
* Returns the current active phone type as integer.
diff --git a/tests/net/common/java/android/net/util/SocketUtilsTest.kt b/tests/net/common/java/android/net/util/SocketUtilsTest.kt
new file mode 100644
index 0000000..9c7cfb0
--- /dev/null
+++ b/tests/net/common/java/android/net/util/SocketUtilsTest.kt
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+package android.net.util;
+
+import android.system.NetlinkSocketAddress
+import android.system.Os
+import android.system.OsConstants.AF_INET
+import android.system.OsConstants.ETH_P_ALL
+import android.system.OsConstants.IPPROTO_UDP
+import android.system.OsConstants.RTMGRP_NEIGH
+import android.system.OsConstants.SOCK_DGRAM
+import android.system.PacketSocketAddress
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Assert.fail
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val TEST_INDEX = 123
+private const val TEST_PORT = 555
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class SocketUtilsTest {
+ @Test
+ fun testMakeNetlinkSocketAddress() {
+ val nlAddress = SocketUtils.makeNetlinkSocketAddress(TEST_PORT, RTMGRP_NEIGH)
+ if (nlAddress is NetlinkSocketAddress) {
+ assertEquals(TEST_PORT, nlAddress.getPortId())
+ assertEquals(RTMGRP_NEIGH, nlAddress.getGroupsMask())
+ } else {
+ fail("Not NetlinkSocketAddress object")
+ }
+ }
+
+ @Test
+ fun testMakePacketSocketAddress() {
+ val pkAddress = SocketUtils.makePacketSocketAddress(ETH_P_ALL, TEST_INDEX)
+ assertTrue("Not PacketSocketAddress object", pkAddress is PacketSocketAddress)
+
+ val ff = 0xff.toByte()
+ val pkAddress2 = SocketUtils.makePacketSocketAddress(TEST_INDEX,
+ byteArrayOf(ff, ff, ff, ff, ff, ff))
+ assertTrue("Not PacketSocketAddress object", pkAddress2 is PacketSocketAddress)
+ }
+
+ @Test
+ fun testCloseSocket() {
+ // Expect no exception happening with null object.
+ SocketUtils.closeSocket(null)
+
+ val fd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
+ assertTrue(fd.valid())
+ SocketUtils.closeSocket(fd)
+ assertFalse(fd.valid())
+ // Expecting socket should be still invalid even closed socket again.
+ SocketUtils.closeSocket(fd)
+ assertFalse(fd.valid())
+ }
+}
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index b5b0384..c16a0f4 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -569,7 +569,7 @@
.addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
- assertTrue(delta.toString(), delta.migrateTun(tunUid, tunIface, underlyingIface));
+ delta.migrateTun(tunUid, tunIface, new String[] {underlyingIface});
assertEquals(20, delta.size());
// tunIface and TEST_IFACE entries are not changed.
@@ -650,7 +650,7 @@
.addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 75500L, 37L, 130000L, 70L, 0L);
- assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface));
+ delta.migrateTun(tunUid, tunIface, new String[]{underlyingIface});
assertEquals(9, delta.size());
// tunIface entries should not be changed.
@@ -813,6 +813,37 @@
}
@Test
+ public void testFilterDebugEntries() {
+ NetworkStats.Entry entry1 = new NetworkStats.Entry(
+ "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry2 = new NetworkStats.Entry(
+ "test2", 10101, SET_DBG_VPN_IN, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry3 = new NetworkStats.Entry(
+ "test2", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry4 = new NetworkStats.Entry(
+ "test2", 10101, SET_DBG_VPN_OUT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats stats = new NetworkStats(TEST_START, 4)
+ .addValues(entry1)
+ .addValues(entry2)
+ .addValues(entry3)
+ .addValues(entry4);
+
+ stats.filterDebugEntries();
+
+ assertEquals(2, stats.size());
+ assertEquals(entry1, stats.getValues(0, null));
+ assertEquals(entry3, stats.getValues(1, null));
+ }
+
+ @Test
public void testApply464xlatAdjustments() {
final String v4Iface = "v4-wlan0";
final String baseIface = "wlan0";
diff --git a/tests/net/java/android/net/util/KeepaliveUtilsTest.kt b/tests/net/java/android/net/util/KeepaliveUtilsTest.kt
index 814e06e..8ea226d 100644
--- a/tests/net/java/android/net/util/KeepaliveUtilsTest.kt
+++ b/tests/net/java/android/net/util/KeepaliveUtilsTest.kt
@@ -78,7 +78,6 @@
assertRunWithException(arrayOf("5"))
// Check resource with invalid slots value.
- assertRunWithException(arrayOf("2,2"))
assertRunWithException(arrayOf("3,-1"))
// Check resource with invalid transport type.
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index e099270..557b7e9 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -192,6 +192,7 @@
import com.android.server.connectivity.Vpn;
import com.android.server.net.NetworkPinner;
import com.android.server.net.NetworkPolicyManagerInternal;
+import com.android.server.net.NetworkStatsFactory;
import com.android.testutils.HandlerUtilsKt;
import org.junit.After;
@@ -4901,9 +4902,9 @@
verify(mStatsService, atLeastOnce())
.forceUpdateIfaces(
eq(onlyCell),
- eq(new VpnInfo[0]),
any(NetworkState[].class),
eq(MOBILE_IFNAME));
+ assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos());
reset(mStatsService);
// Default network switch should update ifaces.
@@ -4914,9 +4915,9 @@
verify(mStatsService, atLeastOnce())
.forceUpdateIfaces(
eq(onlyWifi),
- eq(new VpnInfo[0]),
any(NetworkState[].class),
eq(WIFI_IFNAME));
+ assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos());
reset(mStatsService);
// Disconnect should update ifaces.
@@ -4925,9 +4926,9 @@
verify(mStatsService, atLeastOnce())
.forceUpdateIfaces(
eq(onlyCell),
- eq(new VpnInfo[0]),
any(NetworkState[].class),
eq(MOBILE_IFNAME));
+ assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos());
reset(mStatsService);
// Metered change should update ifaces
@@ -4936,9 +4937,9 @@
verify(mStatsService, atLeastOnce())
.forceUpdateIfaces(
eq(onlyCell),
- eq(new VpnInfo[0]),
any(NetworkState[].class),
eq(MOBILE_IFNAME));
+ assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos());
reset(mStatsService);
mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
@@ -4946,9 +4947,9 @@
verify(mStatsService, atLeastOnce())
.forceUpdateIfaces(
eq(onlyCell),
- eq(new VpnInfo[0]),
any(NetworkState[].class),
eq(MOBILE_IFNAME));
+ assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos());
reset(mStatsService);
// Captive portal change shouldn't update ifaces
@@ -4957,9 +4958,9 @@
verify(mStatsService, never())
.forceUpdateIfaces(
eq(onlyCell),
- eq(new VpnInfo[0]),
any(NetworkState[].class),
eq(MOBILE_IFNAME));
+ assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos());
reset(mStatsService);
// Roaming change should update ifaces
@@ -4968,9 +4969,9 @@
verify(mStatsService, atLeastOnce())
.forceUpdateIfaces(
eq(onlyCell),
- eq(new VpnInfo[0]),
any(NetworkState[].class),
eq(MOBILE_IFNAME));
+ assertEquals(new VpnInfo[0], NetworkStatsFactory.getVpnInfos());
reset(mStatsService);
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java b/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java
new file mode 100644
index 0000000..28785f7
--- /dev/null
+++ b/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 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.net;
+
+import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
+import static android.net.NetworkStats.METERED_ALL;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.METERED_YES;
+import static android.net.NetworkStats.ROAMING_ALL;
+import static android.net.NetworkStats.ROAMING_NO;
+import static android.net.NetworkStats.ROAMING_YES;
+import static android.net.NetworkStats.SET_ALL;
+import static android.net.NetworkStats.SET_DEFAULT;
+import static android.net.NetworkStats.SET_FOREGROUND;
+import static android.net.NetworkStats.TAG_NONE;
+
+import static org.junit.Assert.assertEquals;
+
+import android.net.NetworkStats;
+
+import com.android.internal.net.VpnInfo;
+
+/** Superclass with utilities for NetworkStats(Service|Factory)Test */
+abstract class NetworkStatsBaseTest {
+ static final String TEST_IFACE = "test0";
+ static final String TEST_IFACE2 = "test1";
+ static final String TUN_IFACE = "test_nss_tun0";
+
+ static final int UID_RED = 1001;
+ static final int UID_BLUE = 1002;
+ static final int UID_GREEN = 1003;
+ static final int UID_VPN = 1004;
+
+ void assertValues(NetworkStats stats, String iface, int uid, long rxBytes,
+ long rxPackets, long txBytes, long txPackets) {
+ assertValues(
+ stats, iface, uid, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL,
+ rxBytes, rxPackets, txBytes, txPackets, 0);
+ }
+
+ void assertValues(NetworkStats stats, String iface, int uid, int set, int tag,
+ int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets,
+ long txBytes, long txPackets, long operations) {
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+ final int[] sets;
+ if (set == SET_ALL) {
+ sets = new int[] {SET_ALL, SET_DEFAULT, SET_FOREGROUND};
+ } else {
+ sets = new int[] {set};
+ }
+
+ final int[] roamings;
+ if (roaming == ROAMING_ALL) {
+ roamings = new int[] {ROAMING_ALL, ROAMING_YES, ROAMING_NO};
+ } else {
+ roamings = new int[] {roaming};
+ }
+
+ final int[] meterings;
+ if (metered == METERED_ALL) {
+ meterings = new int[] {METERED_ALL, METERED_YES, METERED_NO};
+ } else {
+ meterings = new int[] {metered};
+ }
+
+ final int[] defaultNetworks;
+ if (defaultNetwork == DEFAULT_NETWORK_ALL) {
+ defaultNetworks =
+ new int[] {DEFAULT_NETWORK_ALL, DEFAULT_NETWORK_YES, DEFAULT_NETWORK_NO};
+ } else {
+ defaultNetworks = new int[] {defaultNetwork};
+ }
+
+ for (int s : sets) {
+ for (int r : roamings) {
+ for (int m : meterings) {
+ for (int d : defaultNetworks) {
+ final int i = stats.findIndex(iface, uid, s, tag, m, r, d);
+ if (i != -1) {
+ entry.add(stats.getValues(i, null));
+ }
+ }
+ }
+ }
+ }
+
+ assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
+ assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
+ assertEquals("unexpected txBytes", txBytes, entry.txBytes);
+ assertEquals("unexpected txPackets", txPackets, entry.txPackets);
+ assertEquals("unexpected operations", operations, entry.operations);
+ }
+
+ VpnInfo createVpnInfo(String[] underlyingIfaces) {
+ VpnInfo info = new VpnInfo();
+ info.ownerUid = UID_VPN;
+ info.vpnIface = TUN_IFACE;
+ info.underlyingIfaces = underlyingIfaces;
+ return info;
+ }
+}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
index 95bc7d9..7329474 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
@@ -16,8 +16,11 @@
package com.android.server.net;
+import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.METERED_ALL;
import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.ROAMING_ALL;
import static android.net.NetworkStats.ROAMING_NO;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.SET_DEFAULT;
@@ -39,6 +42,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.frameworks.tests.net.R;
+import com.android.internal.net.VpnInfo;
import libcore.io.IoUtils;
import libcore.io.Streams;
@@ -54,12 +58,12 @@
import java.io.InputStream;
import java.io.OutputStream;
-/**
- * Tests for {@link NetworkStatsFactory}.
- */
+/** Tests for {@link NetworkStatsFactory}. */
@RunWith(AndroidJUnit4.class)
@SmallTest
-public class NetworkStatsFactoryTest {
+public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
+ private static final String CLAT_PREFIX = "v4-";
+
private File mTestProc;
private NetworkStatsFactory mFactory;
@@ -75,6 +79,8 @@
// related to networkStatsFactory is compiled to a minimal native library and loaded here.
System.loadLibrary("networkstatsfactorytestjni");
mFactory = new NetworkStatsFactory(mTestProc, false);
+ NetworkStatsFactory.updateVpnInfos(new VpnInfo[0]);
+ NetworkStatsFactory.clearStackedIfaces();
}
@After
@@ -99,6 +105,236 @@
}
@Test
+ public void vpnRewriteTrafficThroughItself() throws Exception {
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ NetworkStatsFactory.updateVpnInfos(vpnInfos);
+
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ //
+ // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED
+ // over VPN.
+ // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE
+ // over VPN.
+ //
+ // VPN UID rewrites packets read from TUN back to TUN, plus some of its own traffic
+
+ final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_rewrite_through_self);
+
+ assertValues(tunStats, TUN_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 2000L, 200L, 1000L, 100L, 0);
+ assertValues(tunStats, TUN_IFACE, UID_BLUE, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 1000L, 100L, 500L, 50L, 0);
+ assertValues(tunStats, TUN_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 0L, 0L, 1600L, 160L, 0);
+
+ assertValues(tunStats, TEST_IFACE, UID_RED, 2000L, 200L, 1000L, 100L);
+ assertValues(tunStats, TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L);
+ assertValues(tunStats, TEST_IFACE, UID_VPN, 300L, 0L, 260L, 26L);
+ }
+
+ @Test
+ public void vpnWithClat() throws Exception {
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {CLAT_PREFIX + TEST_IFACE})};
+ NetworkStatsFactory.updateVpnInfos(vpnInfos);
+ NetworkStatsFactory.noteStackedIface(CLAT_PREFIX + TEST_IFACE, TEST_IFACE);
+
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED
+ // over VPN.
+ // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE
+ // over VPN.
+ // VPN sent 1650 bytes (150 packets), and received 3300 (300 packets) over v4-WiFi, and clat
+ // added 20 bytes per packet of extra overhead
+ //
+ // For 1650 bytes sent over v4-WiFi, 4650 bytes were actually sent over WiFi, which is
+ // expected to be split as follows:
+ // UID_RED: 1000 bytes, 100 packets
+ // UID_BLUE: 500 bytes, 50 packets
+ // UID_VPN: 3150 bytes, 0 packets
+ //
+ // For 3300 bytes received over v4-WiFi, 9300 bytes were actually sent over WiFi, which is
+ // expected to be split as follows:
+ // UID_RED: 2000 bytes, 200 packets
+ // UID_BLUE: 1000 bytes, 100 packets
+ // UID_VPN: 6300 bytes, 0 packets
+ final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_with_clat);
+
+ assertValues(tunStats, CLAT_PREFIX + TEST_IFACE, UID_RED, 2000L, 200L, 1000, 100L);
+ assertValues(tunStats, CLAT_PREFIX + TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L);
+ assertValues(tunStats, CLAT_PREFIX + TEST_IFACE, UID_VPN, 6300L, 0L, 3150L, 0L);
+ }
+
+ @Test
+ public void vpnWithOneUnderlyingIface() throws Exception {
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ NetworkStatsFactory.updateVpnInfos(vpnInfos);
+
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED
+ // over VPN.
+ // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE
+ // over VPN.
+ // VPN sent 1650 bytes (150 packets), and received 3300 (300 packets) over WiFi.
+ // Of 1650 bytes sent over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes
+ // attributed to UID_BLUE, and 150 bytes attributed to UID_VPN.
+ // Of 3300 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes
+ // attributed to UID_BLUE, and 300 bytes attributed to UID_VPN.
+ final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying);
+
+ assertValues(tunStats, TEST_IFACE, UID_RED, 2000L, 200L, 1000L, 100L);
+ assertValues(tunStats, TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L);
+ assertValues(tunStats, TEST_IFACE, UID_VPN, 300L, 0L, 150L, 0L);
+ }
+
+ @Test
+ public void vpnWithOneUnderlyingIfaceAndOwnTraffic() throws Exception {
+ // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ NetworkStatsFactory.updateVpnInfos(vpnInfos);
+
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED
+ // over VPN.
+ // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE
+ // over VPN.
+ // Additionally, the VPN sends 6000 bytes (600 packets) of its own traffic into the tun
+ // interface (passing that traffic to the VPN endpoint), and receives 5000 bytes (500
+ // packets) from it. Including overhead that is 6600/5500 bytes.
+ // VPN sent 8250 bytes (750 packets), and received 8800 (800 packets) over WiFi.
+ // Of 8250 bytes sent over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes
+ // attributed to UID_BLUE, and 6750 bytes attributed to UID_VPN.
+ // Of 8800 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes
+ // attributed to UID_BLUE, and 5800 bytes attributed to UID_VPN.
+ final NetworkStats tunStats =
+ parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying_own_traffic);
+
+ assertValues(tunStats, TEST_IFACE, UID_RED, 2000L, 200L, 1000L, 100L);
+ assertValues(tunStats, TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L);
+ assertValues(tunStats, TEST_IFACE, UID_VPN, 5800L, 500L, 6750L, 600L);
+ }
+
+ @Test
+ public void vpnWithOneUnderlyingIface_withCompression() throws Exception {
+ // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ NetworkStatsFactory.updateVpnInfos(vpnInfos);
+
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ // 1000 bytes (100 packets) were sent/received by UID_RED over VPN.
+ // 3000 bytes (300 packets) were sent/received by UID_BLUE over VPN.
+ // VPN sent/received 1000 bytes (100 packets) over WiFi.
+ // Of 1000 bytes over WiFi, expect 250 bytes attributed UID_RED and 750 bytes to UID_BLUE,
+ // with nothing attributed to UID_VPN for both rx/tx traffic.
+ final NetworkStats tunStats =
+ parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying_compression);
+
+ assertValues(tunStats, TEST_IFACE, UID_RED, 250L, 25L, 250L, 25L);
+ assertValues(tunStats, TEST_IFACE, UID_BLUE, 750L, 75L, 750L, 75L);
+ assertValues(tunStats, TEST_IFACE, UID_VPN, 0L, 0L, 0L, 0L);
+ }
+
+ @Test
+ public void vpnWithTwoUnderlyingIfaces_packetDuplication() throws Exception {
+ // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
+ // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
+ // Additionally, VPN is duplicating traffic across both WiFi and Cell.
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
+ NetworkStatsFactory.updateVpnInfos(vpnInfos);
+
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ // 1000 bytes (100 packets) were sent/received by UID_RED and UID_BLUE over VPN.
+ // VPN sent/received 4400 bytes (400 packets) over both WiFi and Cell (8800 bytes in total).
+ // Of 8800 bytes over WiFi/Cell, expect:
+ // - 500 bytes rx/tx each over WiFi/Cell attributed to both UID_RED and UID_BLUE.
+ // - 1200 bytes rx/tx each over WiFi/Cell for VPN_UID.
+ final NetworkStats tunStats =
+ parseDetailedStats(R.raw.xt_qtaguid_vpn_two_underlying_duplication);
+
+ assertValues(tunStats, TEST_IFACE, UID_RED, 500L, 50L, 500L, 50L);
+ assertValues(tunStats, TEST_IFACE, UID_BLUE, 500L, 50L, 500L, 50L);
+ assertValues(tunStats, TEST_IFACE, UID_VPN, 1200L, 100L, 1200L, 100L);
+ assertValues(tunStats, TEST_IFACE2, UID_RED, 500L, 50L, 500L, 50L);
+ assertValues(tunStats, TEST_IFACE2, UID_BLUE, 500L, 50L, 500L, 50L);
+ assertValues(tunStats, TEST_IFACE2, UID_VPN, 1200L, 100L, 1200L, 100L);
+ }
+
+ @Test
+ public void vpnWithTwoUnderlyingIfaces_splitTraffic() throws Exception {
+ // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
+ // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
+ // Additionally, VPN is arbitrarily splitting traffic across WiFi and Cell.
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
+ NetworkStatsFactory.updateVpnInfos(vpnInfos);
+
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ // 1000 bytes (100 packets) were sent, and 500 bytes (50 packets) received by UID_RED over
+ // VPN.
+ // VPN sent 660 bytes (60 packets) over WiFi and 440 bytes (40 packets) over Cell.
+ // And, it received 330 bytes (30 packets) over WiFi and 220 bytes (20 packets) over Cell.
+ // For UID_RED, expect 600 bytes attributed over WiFi and 400 bytes over Cell for sent (tx)
+ // traffic. For received (rx) traffic, expect 300 bytes over WiFi and 200 bytes over Cell.
+ //
+ // For UID_VPN, expect 60 bytes attributed over WiFi and 40 bytes over Cell for tx traffic.
+ // And, 30 bytes over WiFi and 20 bytes over Cell for rx traffic.
+ final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_two_underlying_split);
+
+ assertValues(tunStats, TEST_IFACE, UID_RED, 300L, 30L, 600L, 60L);
+ assertValues(tunStats, TEST_IFACE, UID_VPN, 30L, 0L, 60L, 0L);
+ assertValues(tunStats, TEST_IFACE2, UID_RED, 200L, 20L, 400L, 40L);
+ assertValues(tunStats, TEST_IFACE2, UID_VPN, 20L, 0L, 40L, 0L);
+ }
+
+ @Test
+ public void vpnWithTwoUnderlyingIfaces_splitTrafficWithCompression() throws Exception {
+ // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
+ // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
+ // Additionally, VPN is arbitrarily splitting compressed traffic across WiFi and Cell.
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
+ NetworkStatsFactory.updateVpnInfos(vpnInfos);
+
+ // create some traffic (assume 10 bytes of MTU for VPN interface:
+ // 1000 bytes (100 packets) were sent/received by UID_RED over VPN.
+ // VPN sent/received 600 bytes (60 packets) over WiFi and 200 bytes (20 packets) over Cell.
+ // For UID_RED, expect 600 bytes attributed over WiFi and 200 bytes over Cell for both
+ // rx/tx.
+ // UID_VPN gets nothing attributed to it (avoiding negative stats).
+ final NetworkStats tunStats =
+ parseDetailedStats(R.raw.xt_qtaguid_vpn_two_underlying_split_compression);
+
+ assertValues(tunStats, TEST_IFACE, UID_RED, 600L, 60L, 600L, 60L);
+ assertValues(tunStats, TEST_IFACE, UID_VPN, 0L, 0L, 0L, 0L);
+ assertValues(tunStats, TEST_IFACE2, UID_RED, 200L, 20L, 200L, 20L);
+ assertValues(tunStats, TEST_IFACE2, UID_VPN, 0L, 0L, 0L, 0L);
+ }
+
+ @Test
+ public void vpnWithIncorrectUnderlyingIface() throws Exception {
+ // WiFi and Cell networks are connected and VPN is using Cell (which has TEST_IFACE2),
+ // but has declared only WiFi (TEST_IFACE) in its underlying network set.
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ NetworkStatsFactory.updateVpnInfos(vpnInfos);
+
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ // 1000 bytes (100 packets) were sent/received by UID_RED over VPN.
+ // VPN sent/received 1100 bytes (100 packets) over Cell.
+ // Of 1100 bytes over Cell, expect all of it attributed to UID_VPN for both rx/tx traffic.
+ final NetworkStats tunStats = parseDetailedStats(R.raw.xt_qtaguid_vpn_incorrect_iface);
+
+ assertValues(tunStats, TEST_IFACE, UID_RED, 0L, 0L, 0L, 0L);
+ assertValues(tunStats, TEST_IFACE, UID_VPN, 0L, 0L, 0L, 0L);
+ assertValues(tunStats, TEST_IFACE2, UID_RED, 0L, 0L, 0L, 0L);
+ assertValues(tunStats, TEST_IFACE2, UID_VPN, 1100L, 100L, 1100L, 100L);
+ }
+
+ @Test
public void testKernelTags() throws Exception {
assertEquals(0, kernelToTag("0x0000000000000000"));
assertEquals(0x32, kernelToTag("0x0000003200000000"));
@@ -146,7 +382,7 @@
}
@Test
- public void testDoubleClatAccounting() throws Exception {
+ public void testDoubleClatAccountingSimple() throws Exception {
NetworkStatsFactory.noteStackedIface("v4-wlan0", "wlan0");
// xt_qtaguid_with_clat_simple is a synthetic file that simulates
@@ -154,12 +390,17 @@
// - 41 sent 464xlat packets of size 100 bytes
// - no other traffic on base interface for root uid.
NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat_simple);
- assertEquals(4, stats.size());
+ assertEquals(3, stats.size());
assertStatsEntry(stats, "v4-wlan0", 10060, SET_DEFAULT, 0x0, 46860L, 4920L);
assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, 0L, 0L);
+ }
- stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat);
+ @Test
+ public void testDoubleClatAccounting() throws Exception {
+ NetworkStatsFactory.noteStackedIface("v4-wlan0", "wlan0");
+
+ NetworkStats stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat);
assertEquals(42, stats.size());
assertStatsEntry(stats, "v4-wlan0", 0, SET_DEFAULT, 0x0, 356L, 276L);
@@ -272,11 +513,19 @@
private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set,
int tag, long rxBytes, long rxPackets, long txBytes, long txPackets) {
- final int i = stats.findIndex(iface, uid, set, tag, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO);
+ assertStatsEntry(stats, iface, uid, set, tag, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO,
+ rxBytes, rxPackets, txBytes, txPackets);
+ }
+
+ private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set,
+ int tag, int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets,
+ long txBytes, long txPackets) {
+ final int i = stats.findIndex(iface, uid, set, tag, metered, roaming, defaultNetwork);
+
if (i < 0) {
- fail(String.format("no NetworkStats for (iface: %s, uid: %d, set: %d, tag: %d)",
- iface, uid, set, tag));
+ fail(String.format("no NetworkStats for (iface: %s, uid: %d, set: %d, tag: %d, metered:"
+ + " %d, roaming: %d, defaultNetwork: %d)",
+ iface, uid, set, tag, metered, roaming, defaultNetwork));
}
final NetworkStats.Entry entry = stats.getValues(i, null);
assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
diff --git a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
index 9a47f35..c0f9dc1 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -52,7 +52,6 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.net.VpnInfo;
import com.android.server.net.NetworkStatsServiceTest.LatchedHandler;
import com.android.testutils.HandlerUtilsKt;
@@ -93,8 +92,6 @@
private static final long BASE_BYTES = 7 * MB_IN_BYTES;
private static final int INVALID_TYPE = -1;
- private static final VpnInfo[] VPN_INFO = new VpnInfo[0];
-
private long mElapsedRealtime;
private HandlerThread mObserverHandlerThread;
@@ -247,8 +244,7 @@
NetworkStats uidSnapshot = null;
mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
+ xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
waitForObserverToIdle();
}
@@ -271,15 +267,13 @@
.addIfaceValues(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L);
NetworkStats uidSnapshot = null;
mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
+ xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
xtSnapshot = new NetworkStats(TEST_START, 1 /* initialSize */)
.addIfaceValues(TEST_IFACE, BASE_BYTES + 1024L, 10L, BASE_BYTES + 2048L, 20L);
mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
+ xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
waitForObserverToIdle();
}
@@ -303,16 +297,14 @@
.addIfaceValues(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L);
NetworkStats uidSnapshot = null;
mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
+ xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
xtSnapshot = new NetworkStats(TEST_START + MINUTE_IN_MILLIS, 1 /* initialSize */)
.addIfaceValues(TEST_IFACE, BASE_BYTES + THRESHOLD_BYTES, 12L,
BASE_BYTES + THRESHOLD_BYTES, 22L);
mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
+ xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
waitForObserverToIdle();
assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.lastMessageType);
}
@@ -337,8 +329,7 @@
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
+ xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
@@ -346,8 +337,7 @@
DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
+ xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
waitForObserverToIdle();
assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.lastMessageType);
}
@@ -372,8 +362,7 @@
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
+ xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
@@ -381,8 +370,7 @@
DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
+ xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
waitForObserverToIdle();
}
@@ -406,8 +394,7 @@
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
+ xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
@@ -415,8 +402,7 @@
DEFAULT_NETWORK_YES, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
+ xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
waitForObserverToIdle();
assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.lastMessageType);
}
@@ -441,8 +427,7 @@
.addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
ROAMING_NO, DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
+ xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
@@ -450,8 +435,7 @@
ROAMING_NO, DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
- xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
- VPN_INFO, TEST_START);
+ xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
waitForObserverToIdle();
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index f453f6e..1682dd1 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -23,7 +23,6 @@
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.TYPE_WIMAX;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
-import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.INTERFACES_ALL;
@@ -42,7 +41,6 @@
import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
-import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.net.TrafficStats.UID_REMOVED;
@@ -60,7 +58,6 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -98,7 +95,6 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.net.VpnInfo;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
@@ -129,13 +125,9 @@
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
-public class NetworkStatsServiceTest {
+public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
private static final String TAG = "NetworkStatsServiceTest";
- private static final String TEST_IFACE = "test0";
- private static final String TEST_IFACE2 = "test1";
- private static final String TUN_IFACE = "test_nss_tun0";
-
private static final long TEST_START = 1194220800000L;
private static final String IMSI_1 = "310004";
@@ -146,11 +138,6 @@
private static NetworkTemplate sTemplateImsi1 = buildTemplateMobileAll(IMSI_1);
private static NetworkTemplate sTemplateImsi2 = buildTemplateMobileAll(IMSI_2);
- private static final int UID_RED = 1001;
- private static final int UID_BLUE = 1002;
- private static final int UID_GREEN = 1003;
- private static final int UID_VPN = 1004;
-
private static final Network WIFI_NETWORK = new Network(100);
private static final Network MOBILE_NETWORK = new Network(101);
private static final Network VPN_NETWORK = new Network(102);
@@ -217,10 +204,12 @@
expectSystemReady();
mService.systemReady();
+ // Verify that system ready fetches realtime stats
+ verify(mNetManager).getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL);
+
mSession = mService.openSession();
assertNotNull("openSession() failed", mSession);
-
// catch INetworkManagementEventObserver during systemReady()
ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
@@ -252,7 +241,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_WIFI, new VpnInfo[0], states, getActiveIface(states));
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states));
// verify service has empty history for wifi
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -296,7 +285,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_WIFI, new VpnInfo[0], states, getActiveIface(states));
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states));
// verify service has empty history for wifi
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -370,8 +359,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_WIFI, new VpnInfo[0], states, getActiveIface(states));
-
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states));
// modify some number on wifi, and trigger poll event
incrementCurrentTime(2 * HOUR_IN_MILLIS);
@@ -412,8 +400,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_MOBILE, new VpnInfo[0], states, getActiveIface(states));
-
+ mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states));
// create some traffic on first network
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -448,7 +435,7 @@
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_MOBILE, new VpnInfo[0], states, getActiveIface(states));
+ mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states));
forcePollAndWaitForIdle();
@@ -488,8 +475,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_WIFI, new VpnInfo[0], states, getActiveIface(states));
-
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states));
// create some traffic
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -547,8 +533,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_MOBILE, new VpnInfo[0], states, getActiveIface(states));
-
+ mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states));
// create some traffic
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -575,7 +560,7 @@
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_MOBILE, new VpnInfo[0], states, getActiveIface(states));
+ mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states));
forcePollAndWaitForIdle();
@@ -605,8 +590,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_WIFI, new VpnInfo[0], states, getActiveIface(states));
-
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states));
// create some traffic for two apps
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -664,7 +648,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_WIFI, new VpnInfo[0], states, getActiveIface(states));
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states));
NetworkStats.Entry entry1 = new NetworkStats.Entry(
TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L);
@@ -708,7 +692,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_WIFI, new VpnInfo[0], states, getActiveIface(states));
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states));
NetworkStats.Entry uidStats = new NetworkStats.Entry(
TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L);
@@ -733,11 +717,17 @@
NetworkStats stats = mService.getDetailedUidStats(ifaceFilter);
- verify(mNetManager, times(1)).getNetworkStatsUidDetail(eq(UID_ALL), argThat(ifaces ->
- ifaces != null && ifaces.length == 2
- && ArrayUtils.contains(ifaces, TEST_IFACE)
- && ArrayUtils.contains(ifaces, stackedIface)));
-
+ // mNetManager#getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL) has following invocations:
+ // 1) NetworkStatsService#systemReady from #setUp.
+ // 2) mService#forceUpdateIfaces in the test above.
+ //
+ // Additionally, we should have one call from the above call to mService#getDetailedUidStats
+ // with the augmented ifaceFilter
+ verify(mNetManager, times(2)).getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL);
+ verify(mNetManager, times(1)).getNetworkStatsUidDetail(
+ eq(UID_ALL), eq(NetworkStatsFactory.augmentWithStackedInterfaces(ifaceFilter)));
+ assertTrue(ArrayUtils.contains(stats.getUniqueIfaces(), TEST_IFACE));
+ assertTrue(ArrayUtils.contains(stats.getUniqueIfaces(), stackedIface));
assertEquals(2, stats.size());
assertEquals(uidStats, stats.getValues(0, null));
assertEquals(tetheredStats1, stats.getValues(1, null));
@@ -752,8 +742,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_WIFI, new VpnInfo[0], states, getActiveIface(states));
-
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states));
// create some initial traffic
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -810,8 +799,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_WIFI, new VpnInfo[0], states, getActiveIface(states));
-
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states));
// create some initial traffic
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -851,8 +839,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_MOBILE, new VpnInfo[0], states, getActiveIface(states));
-
+ mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states));
// Create some traffic
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -890,8 +877,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_MOBILE, new VpnInfo[0], states, getActiveIface(states));
-
+ mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states));
// create some tethering traffic
incrementCurrentTime(HOUR_IN_MILLIS);
@@ -923,113 +909,6 @@
}
@Test
- public void vpnWithOneUnderlyingIface() throws Exception {
- // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
- expectDefaultSettings();
- NetworkState[] networkStates = new NetworkState[] {buildWifiState(), buildVpnState()};
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(TEST_IFACE)};
- expectNetworkStatsUidDetail(buildEmptyStats());
- expectBandwidthControlCheck();
-
- mService.forceUpdateIfaces(
- new Network[] {WIFI_NETWORK, VPN_NETWORK},
- vpnInfos,
- networkStates,
- getActiveIface(networkStates));
- // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
- // overhead per packet):
- // 1000 bytes (100 packets) were sent/received by UID_RED over VPN.
- // 500 bytes (50 packets) were sent/received by UID_BLUE over VPN.
- // VPN sent/received 1650 bytes (150 packets) over WiFi.
- // Of 1650 bytes over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes attributed to
- // UID_BLUE, and 150 bytes attributed to UID_VPN for both rx/tx traffic.
- incrementCurrentTime(HOUR_IN_MILLIS);
- expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 1L)
- .addValues(TUN_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 500L, 50L, 500L, 50L, 1L)
- .addValues(
- TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1650L, 150L, 1650L, 150L, 2L));
-
- forcePollAndWaitForIdle();
-
- assertUidTotal(sTemplateWifi, UID_RED, 1000L, 100L, 1000L, 100L, 1);
- assertUidTotal(sTemplateWifi, UID_BLUE, 500L, 50L, 500L, 50L, 1);
- assertUidTotal(sTemplateWifi, UID_VPN, 150L, 0L, 150L, 0L, 2);
- }
-
- @Test
- public void vpnWithOneUnderlyingIface_withCompression() throws Exception {
- // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
- expectDefaultSettings();
- NetworkState[] networkStates = new NetworkState[] {buildWifiState(), buildVpnState()};
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(TEST_IFACE)};
- expectNetworkStatsUidDetail(buildEmptyStats());
- expectBandwidthControlCheck();
-
- mService.forceUpdateIfaces(
- new Network[] {WIFI_NETWORK, VPN_NETWORK},
- vpnInfos,
- networkStates,
- getActiveIface(networkStates));
- // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
- // overhead per packet):
- // 1000 bytes (100 packets) were sent/received by UID_RED over VPN.
- // 3000 bytes (300 packets) were sent/received by UID_BLUE over VPN.
- // VPN sent/received 1000 bytes (100 packets) over WiFi.
- // Of 1000 bytes over WiFi, expect 250 bytes attributed UID_RED and 750 bytes to UID_BLUE,
- // with nothing attributed to UID_VPN for both rx/tx traffic.
- incrementCurrentTime(HOUR_IN_MILLIS);
- expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 1L)
- .addValues(TUN_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 3000L, 300L, 3000L, 300L, 1L)
- .addValues(
- TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 0L));
-
- forcePollAndWaitForIdle();
-
- assertUidTotal(sTemplateWifi, UID_RED, 250L, 25L, 250L, 25L, 0);
- assertUidTotal(sTemplateWifi, UID_BLUE, 750L, 75L, 750L, 75L, 0);
- assertUidTotal(sTemplateWifi, UID_VPN, 0L, 0L, 0L, 0L, 0);
- }
-
- @Test
- public void vpnWithIncorrectUnderlyingIface() throws Exception {
- // WiFi and Cell networks are connected and VPN is using Cell (which has TEST_IFACE2),
- // but has declared only WiFi (TEST_IFACE) in its underlying network set.
- expectDefaultSettings();
- NetworkState[] networkStates =
- new NetworkState[] {
- buildWifiState(), buildMobile4gState(TEST_IFACE2), buildVpnState()
- };
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(TEST_IFACE)};
- expectNetworkStatsUidDetail(buildEmptyStats());
- expectBandwidthControlCheck();
-
- mService.forceUpdateIfaces(
- new Network[] {WIFI_NETWORK, VPN_NETWORK},
- vpnInfos,
- networkStates,
- getActiveIface(networkStates));
- // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
- // overhead per packet):
- // 1000 bytes (100 packets) were sent/received by UID_RED over VPN.
- // VPN sent/received 1100 bytes (100 packets) over Cell.
- // Of 1100 bytes over Cell, expect all of it attributed to UID_VPN for both rx/tx traffic.
- incrementCurrentTime(HOUR_IN_MILLIS);
- expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2)
- .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 1L)
- .addValues(
- TEST_IFACE2, UID_VPN, SET_DEFAULT, TAG_NONE, 1100L, 100L, 1100L, 100L, 1L));
-
- forcePollAndWaitForIdle();
-
- assertUidTotal(sTemplateWifi, UID_RED, 0L, 0L, 0L, 0L, 0);
- assertUidTotal(sTemplateWifi, UID_VPN, 0L, 0L, 0L, 0L, 0);
- assertUidTotal(buildTemplateMobileWildcard(), UID_RED, 0L, 0L, 0L, 0L, 0);
- assertUidTotal(buildTemplateMobileWildcard(), UID_VPN, 1100L, 100L, 1100L, 100L, 1);
- }
-
- @Test
public void testRegisterUsageCallback() throws Exception {
// pretend that wifi network comes online; service should ask about full
// network state, and poll any existing interfaces before updating.
@@ -1039,7 +918,7 @@
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
- mService.forceUpdateIfaces(NETWORKS_WIFI, new VpnInfo[0], states, getActiveIface(states));
+ mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states));
// verify service has empty history for wifi
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -1259,59 +1138,6 @@
}
}
- private static void assertValues(NetworkStats stats, String iface, int uid, int set,
- int tag, int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets,
- long txBytes, long txPackets, int operations) {
- final NetworkStats.Entry entry = new NetworkStats.Entry();
- final int[] sets;
- if (set == SET_ALL) {
- sets = new int[] { SET_ALL, SET_DEFAULT, SET_FOREGROUND };
- } else {
- sets = new int[] { set };
- }
-
- final int[] roamings;
- if (roaming == ROAMING_ALL) {
- roamings = new int[] { ROAMING_ALL, ROAMING_YES, ROAMING_NO };
- } else {
- roamings = new int[] { roaming };
- }
-
- final int[] meterings;
- if (metered == METERED_ALL) {
- meterings = new int[] { METERED_ALL, METERED_YES, METERED_NO };
- } else {
- meterings = new int[] { metered };
- }
-
- final int[] defaultNetworks;
- if (defaultNetwork == DEFAULT_NETWORK_ALL) {
- defaultNetworks = new int[] { DEFAULT_NETWORK_ALL, DEFAULT_NETWORK_YES,
- DEFAULT_NETWORK_NO };
- } else {
- defaultNetworks = new int[] { defaultNetwork };
- }
-
- for (int s : sets) {
- for (int r : roamings) {
- for (int m : meterings) {
- for (int d : defaultNetworks) {
- final int i = stats.findIndex(iface, uid, s, tag, m, r, d);
- if (i != -1) {
- entry.add(stats.getValues(i, null));
- }
- }
- }
- }
- }
-
- assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
- assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
- assertEquals("unexpected txBytes", txBytes, entry.txBytes);
- assertEquals("unexpected txPackets", txPackets, entry.txPackets);
- assertEquals("unexpected operations", operations, entry.operations);
- }
-
private static void assertValues(NetworkStatsHistory stats, long start, long end, long rxBytes,
long rxPackets, long txBytes, long txPackets, int operations) {
final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null);
@@ -1377,14 +1203,6 @@
return new NetworkState(info, prop, new NetworkCapabilities(), VPN_NETWORK, null, null);
}
- private static VpnInfo createVpnInfo(String underlyingIface) {
- VpnInfo info = new VpnInfo();
- info.ownerUid = UID_VPN;
- info.vpnIface = TUN_IFACE;
- info.primaryUnderlyingIface = underlyingIface;
- return info;
- }
-
private long getElapsedRealtime() {
return mElapsedRealtime;
}
diff --git a/tests/net/res/raw/xt_qtaguid_vpn_incorrect_iface b/tests/net/res/raw/xt_qtaguid_vpn_incorrect_iface
new file mode 100644
index 0000000..fc92715
--- /dev/null
+++ b/tests/net/res/raw/xt_qtaguid_vpn_incorrect_iface
@@ -0,0 +1,3 @@
+idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets
+2 test_nss_tun0 0x0 1001 0 1000 100 1000 100 0 0 0 0 0 0 0 0 0 0 0 0
+3 test1 0x0 1004 0 1100 100 1100 100 0 0 0 0 0 0 0 0 0 0 0 0
\ No newline at end of file
diff --git a/tests/net/res/raw/xt_qtaguid_vpn_one_underlying b/tests/net/res/raw/xt_qtaguid_vpn_one_underlying
new file mode 100644
index 0000000..1ef1889
--- /dev/null
+++ b/tests/net/res/raw/xt_qtaguid_vpn_one_underlying
@@ -0,0 +1,5 @@
+idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets
+2 test_nss_tun0 0x0 1001 0 2000 200 1000 100 0 0 0 0 0 0 0 0 0 0 0 0
+3 test_nss_tun0 0x0 1002 0 1000 100 500 50 0 0 0 0 0 0 0 0 0 0 0 0
+4 test0 0x0 1004 0 3300 300 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+5 test0 0x0 1004 1 0 0 1650 150 0 0 0 0 0 0 0 0 0 0 0 0
\ No newline at end of file
diff --git a/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_compression b/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_compression
new file mode 100644
index 0000000..6d6bf55
--- /dev/null
+++ b/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_compression
@@ -0,0 +1,4 @@
+idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets
+2 test_nss_tun0 0x0 1001 0 1000 100 1000 100 0 0 0 0 0 0 0 0 0 0 0 0
+3 test_nss_tun0 0x0 1002 0 3000 300 3000 300 0 0 0 0 0 0 0 0 0 0 0 0
+4 test0 0x0 1004 0 1000 100 1000 100 0 0 0 0 0 0 0 0 0 0 0 0
\ No newline at end of file
diff --git a/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_own_traffic b/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_own_traffic
new file mode 100644
index 0000000..2c2e5d2
--- /dev/null
+++ b/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_own_traffic
@@ -0,0 +1,6 @@
+idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets
+2 test_nss_tun0 0x0 1001 0 2000 200 1000 100 0 0 0 0 0 0 0 0 0 0 0 0
+3 test_nss_tun0 0x0 1002 0 1000 100 500 50 0 0 0 0 0 0 0 0 0 0 0 0
+4 test_nss_tun0 0x0 1004 0 5000 500 6000 600 0 0 0 0 0 0 0 0 0 0 0 0
+5 test0 0x0 1004 0 8800 800 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+6 test0 0x0 1004 1 0 0 8250 750 0 0 0 0 0 0 0 0 0 0 0 0
\ No newline at end of file
diff --git a/tests/net/res/raw/xt_qtaguid_vpn_rewrite_through_self b/tests/net/res/raw/xt_qtaguid_vpn_rewrite_through_self
new file mode 100644
index 0000000..afcdd71
--- /dev/null
+++ b/tests/net/res/raw/xt_qtaguid_vpn_rewrite_through_self
@@ -0,0 +1,6 @@
+idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets
+2 test_nss_tun0 0x0 1001 0 2000 200 1000 100 0 0 0 0 0 0 0 0 0 0 0 0
+3 test_nss_tun0 0x0 1002 0 1000 100 500 50 0 0 0 0 0 0 0 0 0 0 0 0
+4 test_nss_tun0 0x0 1004 0 0 0 1600 160 0 0 0 0 0 0 0 0 0 0 0 0
+5 test0 0x0 1004 1 0 0 1760 176 0 0 0 0 0 0 0 0 0 0 0 0
+6 test0 0x0 1004 0 3300 300 0 0 0 0 0 0 0 0 0 0 0 0 0 0
\ No newline at end of file
diff --git a/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_duplication b/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_duplication
new file mode 100644
index 0000000..d7c7eb9
--- /dev/null
+++ b/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_duplication
@@ -0,0 +1,5 @@
+idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets
+2 test_nss_tun0 0x0 1001 0 1000 100 1000 100 0 0 0 0 0 0 0 0 0 0 0 0
+3 test_nss_tun0 0x0 1002 0 1000 100 1000 100 0 0 0 0 0 0 0 0 0 0 0 0
+4 test0 0x0 1004 0 2200 200 2200 200 0 0 0 0 0 0 0 0 0 0 0 0
+5 test1 0x0 1004 0 2200 200 2200 200 0 0 0 0 0 0 0 0 0 0 0 0
\ No newline at end of file
diff --git a/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_split b/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_split
new file mode 100644
index 0000000..38a3dce
--- /dev/null
+++ b/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_split
@@ -0,0 +1,4 @@
+idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets
+2 test_nss_tun0 0x0 1001 0 500 50 1000 100 0 0 0 0 0 0 0 0 0 0 0 0
+3 test0 0x0 1004 0 330 30 660 60 0 0 0 0 0 0 0 0 0 0 0 0
+4 test1 0x0 1004 0 220 20 440 40 0 0 0 0 0 0 0 0 0 0 0 0
\ No newline at end of file
diff --git a/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_split_compression b/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_split_compression
new file mode 100644
index 0000000..d35244b
--- /dev/null
+++ b/tests/net/res/raw/xt_qtaguid_vpn_two_underlying_split_compression
@@ -0,0 +1,4 @@
+idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets
+2 test_nss_tun0 0x0 1001 0 1000 100 1000 100 0 0 0 0 0 0 0 0 0 0 0 0
+3 test0 0x0 1004 0 600 60 600 60 0 0 0 0 0 0 0 0 0 0 0 0
+4 test1 0x0 1004 0 200 20 200 20 0 0 0 0 0 0 0 0 0 0 0 0
\ No newline at end of file
diff --git a/tests/net/res/raw/xt_qtaguid_vpn_with_clat b/tests/net/res/raw/xt_qtaguid_vpn_with_clat
new file mode 100644
index 0000000..0d893d5
--- /dev/null
+++ b/tests/net/res/raw/xt_qtaguid_vpn_with_clat
@@ -0,0 +1,8 @@
+idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets
+2 test_nss_tun0 0x0 1001 0 2000 200 1000 100 0 0 0 0 0 0 0 0 0 0 0 0
+3 test_nss_tun0 0x0 1002 0 1000 100 500 50 0 0 0 0 0 0 0 0 0 0 0 0
+4 v4-test0 0x0 1004 0 3300 300 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+5 v4-test0 0x0 1004 1 0 0 1650 150 0 0 0 0 0 0 0 0 0 0 0 0
+6 test0 0x0 0 0 9300 300 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+7 test0 0x0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+8 test0 0x0 1029 0 0 0 4650 150 0 0 0 0 0 0 0 0 0 0 0 0
\ No newline at end of file
diff --git a/tests/net/res/raw/xt_qtaguid_with_clat_simple b/tests/net/res/raw/xt_qtaguid_with_clat_simple
index 8c132e7..b37fae6 100644
--- a/tests/net/res/raw/xt_qtaguid_with_clat_simple
+++ b/tests/net/res/raw/xt_qtaguid_with_clat_simple
@@ -2,5 +2,4 @@
2 v4-wlan0 0x0 10060 0 42600 213 4100 41 42600 213 0 0 0 0 4100 41 0 0 0 0
3 v4-wlan0 0x0 10060 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
4 wlan0 0x0 0 0 46860 213 0 0 46860 213 0 0 0 0 0 0 0 0 0 0
-5 wlan0 0x0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-6 wlan0 0x0 1029 0 0 0 4920 41 0 0 0 0 0 0 4920 41 0 0 0 0
+5 wlan0 0x0 1029 0 0 0 4920 41 0 0 0 0 0 0 4920 41 0 0 0 0
diff --git a/tools/aapt2/cmd/Convert_test.cpp b/tools/aapt2/cmd/Convert_test.cpp
index ddc146c..f35237e 100644
--- a/tools/aapt2/cmd/Convert_test.cpp
+++ b/tools/aapt2/cmd/Convert_test.cpp
@@ -132,7 +132,7 @@
int count = 0;
// Can't pass nullptrs into Next()
- ZipString zip_name;
+ std::string zip_name;
ZipEntry zip_data;
while ((result = Next(cookie, &zip_data, &zip_name)) == 0) {
diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp
index a692ba5..4380586 100644
--- a/tools/aapt2/io/ZipArchive.cpp
+++ b/tools/aapt2/io/ZipArchive.cpp
@@ -123,13 +123,9 @@
using IterationEnder = std::unique_ptr<void, decltype(EndIteration)*>;
IterationEnder iteration_ender(cookie, EndIteration);
- ZipString zip_entry_name;
+ std::string zip_entry_path;
ZipEntry zip_data;
- while ((result = Next(cookie, &zip_data, &zip_entry_name)) == 0) {
- std::string zip_entry_path =
- std::string(reinterpret_cast<const char*>(zip_entry_name.name),
- zip_entry_name.name_length);
-
+ while ((result = Next(cookie, &zip_data, &zip_entry_path)) == 0) {
// Do not add folders to the file collection
if (util::EndsWith(zip_entry_path, "/")) {
continue;